From 62f57a591ef9bde0ec6b2d45b2fb975d19d71abd Mon Sep 17 00:00:00 2001 From: Patrick Jackson Date: Wed, 14 Nov 2018 11:50:16 -0500 Subject: [PATCH] apply v2 to master git history --- README.md | 31 +- action-sdk-samples/action.json | 21 - action-sdk-samples/build.gradle | 44 - .../actions/ConversationComponentsSample.kt | 234 - .../src/main/webapp/WEB-INF/appengine-web.xml | 16 - .../src/main/webapp/WEB-INF/web.xml | 4 - build.gradle | 81 +- common-mock/build.gradle | 19 + .../src/main/kotlin/actions/AogMockFactory.kt | 7 + .../src/main/kotlin/actions/Requests.kt | 131 + .../src/test/kotlin/actions/ActionsSdkTest.kt | 96 + ...onversation_sample_basic_card_request.json | 63 + ...nversation_sample_basic_card_response.json | 76 + .../conversation_sample_welcome_request.json | 113 + .../conversation_sample_welcome_response.json | 58 + .../df_sample_basic_card_response.json | 77 + .../df_sample_browse_carousel_response.json | 82 + .../df_sample_carousel_response.json | 123 + .../resources/df_sample_list_response.json | 124 + .../resources/df_sample_media_response.json | 68 + .../df_sample_suggestions_response.json | 59 + .../resources/df_sample_table_response.json | 71 + .../resources/df_sample_test_response.json | 77 + .../resources/df_sample_welcome_response.json | 59 + .../resources/df_transaction_got_address.json | 26 + .../df_transactions_confirm_transaction.json | 201 + common/build.gradle | 31 + common/src/main/kotlin/actions/Assistant.kt | 158 + common/src/main/kotlin/actions/Common.kt | 69 + .../actions/expected/BuiltInFrameworks.kt | 17 + .../main/kotlin/actions/expected/Expected.kt | 64 + .../kotlin/actions/expected/GoogleAuthLib.kt | 9 + .../kotlin/actions/framework/Framework.kt | 54 + .../actions/service/actionssdk/ActionsSdk.kt | 451 ++ .../service/actionssdk/CommonExtensions.kt | 28 + .../kotlin/actions/service/actionssdk/Conv.kt | 111 + .../actions/service/actionssdk/api/V2.kt | 2315 ++++++++ .../actionssdk/conversation/Conversation.kt | 517 ++ .../service/actionssdk/conversation/Device.kt | 19 + .../service/actionssdk/conversation/Input.kt | 41 + .../service/actionssdk/conversation/Intent.kt | 25 + .../actionssdk/conversation/Surface.kt | 81 + .../service/actionssdk/conversation/User.kt | 284 + .../conversation/argument/Argument.kt | 314 + .../actionssdk/conversation/argument/Media.kt | 5 + .../conversation/argument/NoInput.kt | 5 + .../conversation/question/Confirmation.kt | 63 + .../conversation/question/DateTime.kt | 114 + .../conversation/question/DeepLink.kt | 106 + .../conversation/question/NewSurface.kt | 124 + .../actionssdk/conversation/question/Place.kt | 98 + .../conversation/question/RegisterUpdate.kt | 96 + .../conversation/question/SignIn.kt | 69 + .../conversation/question/option/Carousel.kt | 37 + .../conversation/question/option/List.kt | 28 + .../conversation/question/option/Option.kt | 78 + .../question/permission/Permission.kt | 120 + .../question/permission/Update.kt | 102 + .../question/transaction/Decision.kt | 30 + .../question/transaction/DeliveryAddress.kt | 28 + .../question/transaction/Requirements.kt | 28 + .../conversation/response/Browse.kt | 83 + .../actionssdk/conversation/response/Image.kt | 28 + .../conversation/response/Linkout.kt | 17 + .../actionssdk/conversation/response/Media.kt | 60 + .../actionssdk/conversation/response/Order.kt | 3 + .../conversation/response/Response.kt | 771 +++ .../actionssdk/conversation/response/Rich.kt | 37 + .../conversation/response/RichResponseItem.kt | 7 + .../conversation/response/Simple.kt | 16 + .../conversation/response/Suggestion.kt | 4 + .../actionssdk/conversation/response/Url.kt | 10 + .../conversation/response/card/Basic.kt | 19 + .../conversation/response/card/Button.kt | 48 + .../conversation/response/card/Table.kt | 114 + .../actions/service/dialogflow/Context.kt | 292 + .../kotlin/actions/service/dialogflow/Conv.kt | 380 ++ .../actions/service/dialogflow/Dialogflow.kt | 509 ++ .../service/dialogflow/DialogflowV1Message.kt | 116 + .../actions/service/dialogflow/Incoming.kt | 383 ++ .../actions/service/dialogflow/api/V1.kt | 141 + .../actions/service/dialogflow/api/V2.kt | 281 + common/src/test/kotlin/Test.kt | 4 + dialogflow-samples/.gitignore | 1 - dialogflow-samples/README.md | 10 - dialogflow-samples/Transactions_agent.zip | Bin 5680 -> 0 bytes dialogflow-samples/build.gradle | 44 - dialogflow-samples/conversation_agent.zip | Bin 6586 -> 0 bytes .../actions/ConversationComponentsSample.kt | 215 - .../ConversationComponentsSampleJava.java | 215 - .../tmsdurham/actions/TransactionsSample.kt | 169 - .../main/webapp/WEB-INF/logging.properties | 13 - .../src/main/webapp/WEB-INF/web.xml | 4 - gradle.properties | 17 - gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 54413 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 72 +- gradlew.bat | 174 +- js-app/build.gradle | 48 + js-app/src/main/kotlin/js/JsApp.kt | 5 + js/build.gradle | 54 + js/node_modules/.bin/atob | 1 + js/node_modules/.bin/qunit | 1 + js/node_modules/.bin/which | 1 + js/node_modules/anymatch/LICENSE | 15 + js/node_modules/anymatch/README.md | 98 + js/node_modules/anymatch/index.js | 67 + js/node_modules/anymatch/package.json | 72 + js/node_modules/arr-diff/LICENSE | 21 + js/node_modules/arr-diff/README.md | 74 + js/node_modules/arr-diff/index.js | 58 + js/node_modules/arr-diff/package.json | 80 + js/node_modules/arr-flatten/LICENSE | 21 + js/node_modules/arr-flatten/README.md | 86 + js/node_modules/arr-flatten/index.js | 22 + js/node_modules/arr-flatten/package.json | 114 + js/node_modules/arr-union/LICENSE | 21 + js/node_modules/arr-union/README.md | 99 + js/node_modules/arr-union/index.js | 29 + js/node_modules/arr-union/package.json | 108 + js/node_modules/array-unique/LICENSE | 21 + js/node_modules/array-unique/README.md | 51 + js/node_modules/array-unique/index.js | 28 + js/node_modules/array-unique/package.json | 62 + js/node_modules/assign-symbols/LICENSE | 21 + js/node_modules/assign-symbols/README.md | 73 + js/node_modules/assign-symbols/index.js | 40 + js/node_modules/assign-symbols/package.json | 71 + js/node_modules/async-each/.npmignore | 3 + js/node_modules/async-each/CHANGELOG.md | 23 + js/node_modules/async-each/README.md | 38 + js/node_modules/async-each/index.js | 38 + js/node_modules/async-each/package.json | 60 + js/node_modules/atob/LICENSE | 230 + js/node_modules/atob/LICENSE.DOCS | 319 + js/node_modules/atob/README.md | 49 + js/node_modules/atob/bower.json | 25 + js/node_modules/atob/browser-atob.js | 44 + js/node_modules/atob/node-atob.js | 7 + js/node_modules/atob/package.json | 53 + js/node_modules/atob/test.js | 18 + js/node_modules/balanced-match/.npmignore | 5 + js/node_modules/balanced-match/LICENSE.md | 21 + js/node_modules/balanced-match/README.md | 91 + js/node_modules/balanced-match/index.js | 59 + js/node_modules/balanced-match/package.json | 77 + js/node_modules/base/LICENSE | 21 + js/node_modules/base/README.md | 491 ++ js/node_modules/base/index.js | 435 ++ .../base/node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 95 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 93 + .../is-accessor-descriptor/LICENSE | 21 + .../is-accessor-descriptor/README.md | 144 + .../is-accessor-descriptor/index.js | 69 + .../is-accessor-descriptor/package.json | 110 + .../node_modules/is-data-descriptor/LICENSE | 21 + .../node_modules/is-data-descriptor/README.md | 161 + .../node_modules/is-data-descriptor/index.js | 49 + .../is-data-descriptor/package.json | 109 + .../base/node_modules/is-descriptor/LICENSE | 21 + .../base/node_modules/is-descriptor/README.md | 193 + .../base/node_modules/is-descriptor/index.js | 22 + .../node_modules/is-descriptor/package.json | 114 + .../base/node_modules/isobject/LICENSE | 21 + .../base/node_modules/isobject/README.md | 122 + .../base/node_modules/isobject/index.d.ts | 5 + .../base/node_modules/isobject/index.js | 12 + .../base/node_modules/isobject/package.json | 119 + .../base/node_modules/kind-of/CHANGELOG.md | 157 + .../base/node_modules/kind-of/LICENSE | 21 + .../base/node_modules/kind-of/README.md | 365 ++ .../base/node_modules/kind-of/index.js | 129 + .../base/node_modules/kind-of/package.json | 145 + js/node_modules/base/package.json | 162 + .../binary-extensions/binary-extensions.json | 246 + js/node_modules/binary-extensions/license | 9 + .../binary-extensions/package.json | 68 + js/node_modules/binary-extensions/readme.md | 33 + js/node_modules/brace-expansion/LICENSE | 21 + js/node_modules/brace-expansion/README.md | 129 + js/node_modules/brace-expansion/index.js | 201 + js/node_modules/brace-expansion/package.json | 75 + js/node_modules/braces/LICENSE | 21 + js/node_modules/braces/README.md | 248 + js/node_modules/braces/index.js | 399 ++ js/node_modules/braces/package.json | 114 + js/node_modules/cache-base/LICENSE | 21 + js/node_modules/cache-base/README.md | 291 + js/node_modules/cache-base/index.js | 261 + .../cache-base/node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../cache-base/node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/cache-base/package.json | 118 + js/node_modules/chokidar/CHANGELOG.md | 274 + js/node_modules/chokidar/README.md | 293 + js/node_modules/chokidar/index.js | 716 +++ .../chokidar/lib/fsevents-handler.js | 397 ++ .../chokidar/lib/nodefs-handler.js | 481 ++ js/node_modules/chokidar/package.json | 84 + js/node_modules/class-utils/LICENSE | 21 + js/node_modules/class-utils/README.md | 300 + js/node_modules/class-utils/index.js | 370 ++ .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 77 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 82 + .../class-utils/node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/class-utils/package.json | 131 + js/node_modules/collection-visit/LICENSE | 21 + js/node_modules/collection-visit/README.md | 89 + js/node_modules/collection-visit/index.js | 30 + js/node_modules/collection-visit/package.json | 115 + js/node_modules/commander/CHANGELOG.md | 326 + js/node_modules/commander/LICENSE | 22 + js/node_modules/commander/Readme.md | 370 ++ js/node_modules/commander/index.js | 1158 ++++ js/node_modules/commander/package.json | 66 + js/node_modules/commander/typings/index.d.ts | 295 + js/node_modules/component-emitter/History.md | 68 + js/node_modules/component-emitter/LICENSE | 24 + js/node_modules/component-emitter/Readme.md | 74 + js/node_modules/component-emitter/index.js | 163 + .../component-emitter/package.json | 57 + js/node_modules/concat-map/.travis.yml | 4 + js/node_modules/concat-map/LICENSE | 18 + js/node_modules/concat-map/README.markdown | 62 + js/node_modules/concat-map/example/map.js | 6 + js/node_modules/concat-map/index.js | 13 + js/node_modules/concat-map/package.json | 88 + js/node_modules/concat-map/test/map.js | 39 + js/node_modules/copy-descriptor/LICENSE | 21 + js/node_modules/copy-descriptor/index.js | 81 + js/node_modules/copy-descriptor/package.json | 87 + js/node_modules/core-util-is/LICENSE | 19 + js/node_modules/core-util-is/README.md | 3 + js/node_modules/core-util-is/float.patch | 604 ++ js/node_modules/core-util-is/lib/util.js | 107 + js/node_modules/core-util-is/package.json | 62 + js/node_modules/core-util-is/test.js | 68 + js/node_modules/debug/.coveralls.yml | 1 + js/node_modules/debug/.eslintrc | 11 + js/node_modules/debug/.npmignore | 9 + js/node_modules/debug/.travis.yml | 14 + js/node_modules/debug/CHANGELOG.md | 362 ++ js/node_modules/debug/LICENSE | 19 + js/node_modules/debug/Makefile | 50 + js/node_modules/debug/README.md | 312 + js/node_modules/debug/component.json | 19 + js/node_modules/debug/karma.conf.js | 70 + js/node_modules/debug/node.js | 1 + js/node_modules/debug/package.json | 89 + js/node_modules/debug/src/browser.js | 185 + js/node_modules/debug/src/debug.js | 202 + js/node_modules/debug/src/index.js | 10 + js/node_modules/debug/src/inspector-log.js | 15 + js/node_modules/debug/src/node.js | 248 + js/node_modules/decode-uri-component/index.js | 94 + js/node_modules/decode-uri-component/license | 21 + .../decode-uri-component/package.json | 69 + .../decode-uri-component/readme.md | 70 + js/node_modules/define-property/CHANGELOG.md | 82 + js/node_modules/define-property/LICENSE | 21 + js/node_modules/define-property/README.md | 117 + js/node_modules/define-property/index.js | 38 + .../is-accessor-descriptor/LICENSE | 21 + .../is-accessor-descriptor/README.md | 144 + .../is-accessor-descriptor/index.js | 69 + .../is-accessor-descriptor/package.json | 110 + .../node_modules/is-data-descriptor/LICENSE | 21 + .../node_modules/is-data-descriptor/README.md | 161 + .../node_modules/is-data-descriptor/index.js | 49 + .../is-data-descriptor/package.json | 109 + .../node_modules/is-descriptor/LICENSE | 21 + .../node_modules/is-descriptor/README.md | 193 + .../node_modules/is-descriptor/index.js | 22 + .../node_modules/is-descriptor/package.json | 114 + .../node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + .../node_modules/kind-of/CHANGELOG.md | 157 + .../node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 365 ++ .../node_modules/kind-of/index.js | 129 + .../node_modules/kind-of/package.json | 145 + js/node_modules/define-property/package.json | 106 + js/node_modules/detect-file/LICENSE | 21 + js/node_modules/detect-file/README.md | 99 + js/node_modules/detect-file/index.js | 109 + js/node_modules/detect-file/package.json | 91 + js/node_modules/ensure-posix-path/README.md | 4 + js/node_modules/ensure-posix-path/index.js | 9 + .../ensure-posix-path/package.json | 57 + js/node_modules/exists-stat/.npmignore | 1 + js/node_modules/exists-stat/.travis.yml | 7 + js/node_modules/exists-stat/README.md | 11 + js/node_modules/exists-stat/index.js | 12 + js/node_modules/exists-stat/package.json | 50 + js/node_modules/exists-stat/test.js | 32 + js/node_modules/expand-brackets/LICENSE | 21 + js/node_modules/expand-brackets/README.md | 107 + js/node_modules/expand-brackets/index.js | 163 + js/node_modules/expand-brackets/package.json | 93 + js/node_modules/expand-range/LICENSE | 24 + js/node_modules/expand-range/README.md | 145 + js/node_modules/expand-range/index.js | 43 + js/node_modules/expand-range/package.json | 104 + js/node_modules/expand-tilde/LICENSE | 21 + js/node_modules/expand-tilde/README.md | 80 + js/node_modules/expand-tilde/index.js | 22 + js/node_modules/expand-tilde/package.json | 99 + js/node_modules/extend-shallow/LICENSE | 21 + js/node_modules/extend-shallow/README.md | 97 + js/node_modules/extend-shallow/index.js | 60 + .../node_modules/is-extendable/LICENSE | 21 + .../node_modules/is-extendable/README.md | 88 + .../node_modules/is-extendable/index.d.ts | 5 + .../node_modules/is-extendable/index.js | 14 + .../node_modules/is-extendable/package.json | 98 + js/node_modules/extend-shallow/package.json | 126 + js/node_modules/extglob/LICENSE | 21 + js/node_modules/extglob/README.md | 88 + js/node_modules/extglob/index.js | 178 + js/node_modules/extglob/package.json | 85 + js/node_modules/filename-regex/LICENSE | 21 + js/node_modules/filename-regex/README.md | 63 + js/node_modules/filename-regex/index.js | 10 + js/node_modules/filename-regex/package.json | 81 + js/node_modules/fill-range/LICENSE | 21 + js/node_modules/fill-range/README.md | 317 + js/node_modules/fill-range/index.js | 408 ++ js/node_modules/fill-range/package.json | 109 + js/node_modules/findup-sync/README.md | 69 + js/node_modules/findup-sync/index.js | 85 + .../findup-sync/node_modules/arr-diff/LICENSE | 21 + .../node_modules/arr-diff/README.md | 130 + .../node_modules/arr-diff/index.js | 47 + .../node_modules/arr-diff/package.json | 108 + .../node_modules/array-unique/LICENSE | 21 + .../node_modules/array-unique/README.md | 77 + .../node_modules/array-unique/index.js | 43 + .../node_modules/array-unique/package.json | 95 + .../findup-sync/node_modules/braces/LICENSE | 21 + .../findup-sync/node_modules/braces/README.md | 640 ++ .../findup-sync/node_modules/braces/index.js | 318 + .../node_modules/braces/lib/braces.js | 104 + .../node_modules/braces/lib/compilers.js | 282 + .../node_modules/braces/lib/parsers.js | 360 ++ .../node_modules/braces/lib/utils.js | 343 ++ .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + .../node_modules/braces/package.json | 156 + .../node_modules/expand-brackets/LICENSE | 21 + .../node_modules/expand-brackets/README.md | 302 + .../node_modules/expand-brackets/changelog.md | 35 + .../node_modules/expand-brackets/index.js | 211 + .../expand-brackets/lib/compilers.js | 87 + .../expand-brackets/lib/parsers.js | 219 + .../node_modules/expand-brackets/lib/utils.js | 34 + .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 77 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 82 + .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + .../is-accessor-descriptor/LICENSE | 21 + .../is-accessor-descriptor/README.md | 123 + .../is-accessor-descriptor/index.js | 69 + .../node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 261 + .../node_modules/kind-of/index.js | 116 + .../node_modules/kind-of/package.json | 139 + .../is-accessor-descriptor/package.json | 94 + .../node_modules/is-data-descriptor/LICENSE | 21 + .../node_modules/is-data-descriptor/README.md | 128 + .../node_modules/is-data-descriptor/index.js | 55 + .../node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 261 + .../node_modules/kind-of/index.js | 116 + .../node_modules/kind-of/package.json | 139 + .../is-data-descriptor/package.json | 93 + .../node_modules/is-descriptor/LICENSE | 21 + .../node_modules/is-descriptor/README.md | 193 + .../node_modules/is-descriptor/index.js | 22 + .../node_modules/is-descriptor/package.json | 114 + .../node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 342 ++ .../node_modules/kind-of/index.js | 147 + .../node_modules/kind-of/package.json | 146 + .../node_modules/expand-brackets/package.json | 133 + .../findup-sync/node_modules/extglob/LICENSE | 21 + .../node_modules/extglob/README.md | 362 ++ .../node_modules/extglob/changelog.md | 25 + .../findup-sync/node_modules/extglob/index.js | 331 ++ .../node_modules/extglob/lib/compilers.js | 169 + .../node_modules/extglob/lib/extglob.js | 78 + .../node_modules/extglob/lib/parsers.js | 156 + .../node_modules/extglob/lib/utils.js | 69 + .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 95 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 93 + .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + .../node_modules/extglob/package.json | 160 + .../node_modules/fill-range/LICENSE | 21 + .../node_modules/fill-range/README.md | 250 + .../node_modules/fill-range/index.js | 208 + .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + .../node_modules/fill-range/package.json | 130 + .../is-accessor-descriptor/LICENSE | 21 + .../is-accessor-descriptor/README.md | 144 + .../is-accessor-descriptor/index.js | 69 + .../is-accessor-descriptor/package.json | 110 + .../node_modules/is-data-descriptor/LICENSE | 21 + .../node_modules/is-data-descriptor/README.md | 161 + .../node_modules/is-data-descriptor/index.js | 49 + .../is-data-descriptor/package.json | 109 + .../node_modules/is-descriptor/LICENSE | 21 + .../node_modules/is-descriptor/README.md | 193 + .../node_modules/is-descriptor/index.js | 22 + .../node_modules/is-descriptor/package.json | 114 + .../node_modules/is-extglob/LICENSE | 21 + .../node_modules/is-extglob/README.md | 107 + .../node_modules/is-extglob/index.js | 20 + .../node_modules/is-extglob/package.json | 100 + .../findup-sync/node_modules/is-glob/LICENSE | 21 + .../node_modules/is-glob/README.md | 142 + .../findup-sync/node_modules/is-glob/index.js | 25 + .../node_modules/is-glob/package.json | 119 + .../node_modules/is-number/LICENSE | 21 + .../node_modules/is-number/README.md | 115 + .../node_modules/is-number/index.js | 22 + .../is-number/node_modules/kind-of/LICENSE | 21 + .../is-number/node_modules/kind-of/README.md | 261 + .../is-number/node_modules/kind-of/index.js | 116 + .../node_modules/kind-of/package.json | 139 + .../node_modules/is-number/package.json | 123 + .../findup-sync/node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + .../node_modules/kind-of/CHANGELOG.md | 157 + .../findup-sync/node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 365 ++ .../findup-sync/node_modules/kind-of/index.js | 129 + .../node_modules/kind-of/package.json | 146 + .../node_modules/micromatch/CHANGELOG.md | 37 + .../node_modules/micromatch/LICENSE | 21 + .../node_modules/micromatch/README.md | 1150 ++++ .../node_modules/micromatch/index.js | 877 +++ .../node_modules/micromatch/lib/cache.js | 1 + .../node_modules/micromatch/lib/compilers.js | 77 + .../node_modules/micromatch/lib/parsers.js | 83 + .../node_modules/micromatch/lib/utils.js | 309 + .../node_modules/micromatch/package.json | 216 + js/node_modules/findup-sync/package.json | 98 + js/node_modules/for-in/LICENSE | 21 + js/node_modules/for-in/README.md | 85 + js/node_modules/for-in/index.js | 16 + js/node_modules/for-in/package.json | 107 + js/node_modules/for-own/LICENSE | 21 + js/node_modules/for-own/README.md | 85 + js/node_modules/for-own/index.js | 19 + js/node_modules/for-own/package.json | 109 + js/node_modules/fragment-cache/LICENSE | 21 + js/node_modules/fragment-cache/README.md | 156 + js/node_modules/fragment-cache/index.js | 128 + js/node_modules/fragment-cache/package.json | 93 + js/node_modules/fsevents/.npmignore | 1 + js/node_modules/fsevents/.travis.yml | 102 + js/node_modules/fsevents/ISSUE_TEMPLATE.md | 8 + js/node_modules/fsevents/LICENSE | 22 + js/node_modules/fsevents/Readme.md | 78 + js/node_modules/fsevents/binding.gyp | 29 + js/node_modules/fsevents/fsevents.cc | 100 + js/node_modules/fsevents/fsevents.js | 108 + js/node_modules/fsevents/install.js | 7 + .../Release/node-v11-darwin-x64/fse.node | Bin 0 -> 33384 bytes .../Release/node-v46-darwin-x64/fse.node | Bin 0 -> 34672 bytes .../Release/node-v47-darwin-x64/fse.node | Bin 0 -> 34672 bytes .../Release/node-v48-darwin-x64/fse.node | Bin 0 -> 38328 bytes .../Release/node-v57-darwin-x64/fse.node | Bin 0 -> 40736 bytes .../fsevents/node_modules/.bin/detect-libc | 1 + .../fsevents/node_modules/.bin/mkdirp | 1 + .../fsevents/node_modules/.bin/needle | 1 + .../fsevents/node_modules/.bin/node-pre-gyp | 1 + .../fsevents/node_modules/.bin/nopt | 1 + js/node_modules/fsevents/node_modules/.bin/rc | 1 + .../fsevents/node_modules/.bin/rimraf | 1 + .../fsevents/node_modules/.bin/semver | 1 + .../fsevents/node_modules/abbrev/LICENSE | 46 + .../fsevents/node_modules/abbrev/README.md | 23 + .../fsevents/node_modules/abbrev/abbrev.js | 61 + .../fsevents/node_modules/abbrev/package.json | 59 + .../fsevents/node_modules/ansi-regex/index.js | 4 + .../fsevents/node_modules/ansi-regex/license | 21 + .../node_modules/ansi-regex/package.json | 111 + .../node_modules/ansi-regex/readme.md | 39 + .../fsevents/node_modules/aproba/LICENSE | 14 + .../fsevents/node_modules/aproba/README.md | 94 + .../fsevents/node_modules/aproba/index.js | 105 + .../fsevents/node_modules/aproba/package.json | 65 + .../node_modules/are-we-there-yet/CHANGES.md | 31 + .../node_modules/are-we-there-yet/LICENSE | 5 + .../node_modules/are-we-there-yet/README.md | 195 + .../node_modules/are-we-there-yet/index.js | 4 + .../are-we-there-yet/package.json | 66 + .../are-we-there-yet/tracker-base.js | 11 + .../are-we-there-yet/tracker-group.js | 107 + .../are-we-there-yet/tracker-stream.js | 35 + .../node_modules/are-we-there-yet/tracker.js | 30 + .../node_modules/balanced-match/.npmignore | 5 + .../node_modules/balanced-match/LICENSE.md | 21 + .../node_modules/balanced-match/README.md | 91 + .../node_modules/balanced-match/index.js | 59 + .../node_modules/balanced-match/package.json | 80 + .../node_modules/brace-expansion/LICENSE | 21 + .../node_modules/brace-expansion/README.md | 129 + .../node_modules/brace-expansion/index.js | 201 + .../node_modules/brace-expansion/package.json | 78 + .../fsevents/node_modules/chownr/LICENSE | 15 + .../fsevents/node_modules/chownr/README.md | 3 + .../fsevents/node_modules/chownr/chownr.js | 52 + .../fsevents/node_modules/chownr/package.json | 59 + .../node_modules/code-point-at/index.js | 32 + .../node_modules/code-point-at/license | 21 + .../node_modules/code-point-at/package.json | 73 + .../node_modules/code-point-at/readme.md | 32 + .../node_modules/concat-map/.travis.yml | 4 + .../fsevents/node_modules/concat-map/LICENSE | 18 + .../node_modules/concat-map/README.markdown | 62 + .../node_modules/concat-map/example/map.js | 6 + .../fsevents/node_modules/concat-map/index.js | 13 + .../node_modules/concat-map/package.json | 91 + .../node_modules/concat-map/test/map.js | 39 + .../console-control-strings/LICENSE | 13 + .../console-control-strings/README.md | 145 + .../console-control-strings/index.js | 125 + .../console-control-strings/package.json | 64 + .../node_modules/core-util-is/LICENSE | 19 + .../node_modules/core-util-is/README.md | 3 + .../node_modules/core-util-is/float.patch | 604 ++ .../node_modules/core-util-is/lib/util.js | 107 + .../node_modules/core-util-is/package.json | 65 + .../node_modules/core-util-is/test.js | 68 + .../node_modules/debug/.coveralls.yml | 1 + .../fsevents/node_modules/debug/.eslintrc | 11 + .../fsevents/node_modules/debug/.npmignore | 9 + .../fsevents/node_modules/debug/.travis.yml | 14 + .../fsevents/node_modules/debug/CHANGELOG.md | 362 ++ .../fsevents/node_modules/debug/LICENSE | 19 + .../fsevents/node_modules/debug/Makefile | 50 + .../fsevents/node_modules/debug/README.md | 312 + .../node_modules/debug/component.json | 19 + .../fsevents/node_modules/debug/karma.conf.js | 70 + .../fsevents/node_modules/debug/node.js | 1 + .../fsevents/node_modules/debug/package.json | 91 + .../node_modules/debug/src/browser.js | 185 + .../fsevents/node_modules/debug/src/debug.js | 202 + .../fsevents/node_modules/debug/src/index.js | 10 + .../node_modules/debug/src/inspector-log.js | 15 + .../fsevents/node_modules/debug/src/node.js | 248 + .../node_modules/deep-extend/CHANGELOG.md | 21 + .../fsevents/node_modules/deep-extend/LICENSE | 20 + .../node_modules/deep-extend/README.md | 90 + .../node_modules/deep-extend/index.js | 1 + .../deep-extend/lib/deep-extend.js | 144 + .../node_modules/deep-extend/package.json | 96 + .../node_modules/delegates/.npmignore | 1 + .../node_modules/delegates/History.md | 22 + .../fsevents/node_modules/delegates/License | 20 + .../fsevents/node_modules/delegates/Makefile | 8 + .../fsevents/node_modules/delegates/Readme.md | 94 + .../fsevents/node_modules/delegates/index.js | 121 + .../node_modules/delegates/package.json | 51 + .../node_modules/delegates/test/index.js | 94 + .../node_modules/detect-libc/.npmignore | 7 + .../fsevents/node_modules/detect-libc/LICENSE | 201 + .../node_modules/detect-libc/README.md | 78 + .../detect-libc/lib/detect-libc.js | 92 + .../node_modules/detect-libc/package.json | 73 + .../fsevents/node_modules/fs-minipass/LICENSE | 15 + .../node_modules/fs-minipass/README.md | 70 + .../node_modules/fs-minipass/index.js | 386 ++ .../node_modules/fs-minipass/package.json | 65 + .../fsevents/node_modules/fs.realpath/LICENSE | 43 + .../node_modules/fs.realpath/README.md | 33 + .../node_modules/fs.realpath/index.js | 66 + .../fsevents/node_modules/fs.realpath/old.js | 303 + .../node_modules/fs.realpath/package.json | 62 + .../fsevents/node_modules/gauge/CHANGELOG.md | 160 + .../fsevents/node_modules/gauge/LICENSE | 13 + .../fsevents/node_modules/gauge/README.md | 399 ++ .../fsevents/node_modules/gauge/base-theme.js | 14 + .../fsevents/node_modules/gauge/error.js | 24 + .../fsevents/node_modules/gauge/has-color.js | 12 + .../fsevents/node_modules/gauge/index.js | 233 + .../fsevents/node_modules/gauge/package.json | 94 + .../fsevents/node_modules/gauge/plumbing.js | 48 + .../fsevents/node_modules/gauge/process.js | 3 + .../node_modules/gauge/progress-bar.js | 35 + .../node_modules/gauge/render-template.js | 181 + .../node_modules/gauge/set-immediate.js | 7 + .../node_modules/gauge/set-interval.js | 3 + .../fsevents/node_modules/gauge/spin.js | 5 + .../node_modules/gauge/template-item.js | 73 + .../fsevents/node_modules/gauge/theme-set.js | 115 + .../fsevents/node_modules/gauge/themes.js | 54 + .../node_modules/gauge/wide-truncate.js | 25 + .../fsevents/node_modules/glob/LICENSE | 15 + .../fsevents/node_modules/glob/README.md | 368 ++ .../fsevents/node_modules/glob/changelog.md | 67 + .../fsevents/node_modules/glob/common.js | 240 + .../fsevents/node_modules/glob/glob.js | 790 +++ .../fsevents/node_modules/glob/package.json | 79 + .../fsevents/node_modules/glob/sync.js | 486 ++ .../fsevents/node_modules/has-unicode/LICENSE | 14 + .../node_modules/has-unicode/README.md | 43 + .../node_modules/has-unicode/index.js | 16 + .../node_modules/has-unicode/package.json | 61 + .../node_modules/iconv-lite/.travis.yml | 23 + .../node_modules/iconv-lite/Changelog.md | 146 + .../fsevents/node_modules/iconv-lite/LICENSE | 21 + .../node_modules/iconv-lite/README.md | 156 + .../iconv-lite/encodings/dbcs-codec.js | 555 ++ .../iconv-lite/encodings/dbcs-data.js | 176 + .../iconv-lite/encodings/index.js | 22 + .../iconv-lite/encodings/internal.js | 188 + .../iconv-lite/encodings/sbcs-codec.js | 72 + .../encodings/sbcs-data-generated.js | 451 ++ .../iconv-lite/encodings/sbcs-data.js | 169 + .../encodings/tables/big5-added.json | 122 + .../iconv-lite/encodings/tables/cp936.json | 264 + .../iconv-lite/encodings/tables/cp949.json | 273 + .../iconv-lite/encodings/tables/cp950.json | 177 + .../iconv-lite/encodings/tables/eucjp.json | 182 + .../encodings/tables/gb18030-ranges.json | 1 + .../encodings/tables/gbk-added.json | 55 + .../iconv-lite/encodings/tables/shiftjis.json | 125 + .../iconv-lite/encodings/utf16.js | 177 + .../node_modules/iconv-lite/encodings/utf7.js | 290 + .../iconv-lite/lib/bom-handling.js | 52 + .../iconv-lite/lib/extend-node.js | 217 + .../node_modules/iconv-lite/lib/index.d.ts | 24 + .../node_modules/iconv-lite/lib/index.js | 153 + .../node_modules/iconv-lite/lib/streams.js | 121 + .../node_modules/iconv-lite/package.json | 79 + .../fsevents/node_modules/ignore-walk/LICENSE | 15 + .../node_modules/ignore-walk/README.md | 60 + .../node_modules/ignore-walk/index.js | 265 + .../node_modules/ignore-walk/package.json | 74 + .../fsevents/node_modules/inflight/LICENSE | 15 + .../fsevents/node_modules/inflight/README.md | 37 + .../node_modules/inflight/inflight.js | 54 + .../node_modules/inflight/package.json | 61 + .../fsevents/node_modules/inherits/LICENSE | 16 + .../fsevents/node_modules/inherits/README.md | 42 + .../node_modules/inherits/inherits.js | 7 + .../node_modules/inherits/inherits_browser.js | 23 + .../node_modules/inherits/package.json | 65 + .../fsevents/node_modules/ini/LICENSE | 15 + .../fsevents/node_modules/ini/README.md | 102 + .../fsevents/node_modules/ini/ini.js | 194 + .../fsevents/node_modules/ini/package.json | 66 + .../is-fullwidth-code-point/index.js | 46 + .../is-fullwidth-code-point/license | 21 + .../is-fullwidth-code-point/package.json | 80 + .../is-fullwidth-code-point/readme.md | 39 + .../fsevents/node_modules/isarray/.npmignore | 1 + .../fsevents/node_modules/isarray/.travis.yml | 4 + .../fsevents/node_modules/isarray/Makefile | 6 + .../fsevents/node_modules/isarray/README.md | 60 + .../node_modules/isarray/component.json | 19 + .../fsevents/node_modules/isarray/index.js | 5 + .../node_modules/isarray/package.json | 76 + .../fsevents/node_modules/isarray/test.js | 20 + .../fsevents/node_modules/minimatch/LICENSE | 15 + .../fsevents/node_modules/minimatch/README.md | 209 + .../node_modules/minimatch/minimatch.js | 923 +++ .../node_modules/minimatch/package.json | 67 + .../node_modules/minimist/.travis.yml | 4 + .../fsevents/node_modules/minimist/LICENSE | 18 + .../node_modules/minimist/example/parse.js | 2 + .../fsevents/node_modules/minimist/index.js | 187 + .../node_modules/minimist/package.json | 74 + .../node_modules/minimist/readme.markdown | 73 + .../node_modules/minimist/test/dash.js | 24 + .../minimist/test/default_bool.js | 20 + .../node_modules/minimist/test/dotted.js | 16 + .../node_modules/minimist/test/long.js | 31 + .../node_modules/minimist/test/parse.js | 318 + .../minimist/test/parse_modified.js | 9 + .../node_modules/minimist/test/short.js | 67 + .../node_modules/minimist/test/whitespace.js | 8 + .../fsevents/node_modules/minipass/README.md | 46 + .../fsevents/node_modules/minipass/index.js | 304 + .../node_modules/minipass/package.json | 72 + .../fsevents/node_modules/minizlib/LICENSE | 26 + .../fsevents/node_modules/minizlib/README.md | 44 + .../node_modules/minizlib/constants.js | 46 + .../fsevents/node_modules/minizlib/index.js | 364 ++ .../node_modules/minizlib/package.json | 74 + .../fsevents/node_modules/mkdirp/.travis.yml | 8 + .../fsevents/node_modules/mkdirp/LICENSE | 21 + .../node_modules/mkdirp/examples/pow.js | 6 + .../fsevents/node_modules/mkdirp/index.js | 98 + .../fsevents/node_modules/mkdirp/package.json | 66 + .../node_modules/mkdirp/readme.markdown | 100 + .../node_modules/mkdirp/test/chmod.js | 41 + .../node_modules/mkdirp/test/clobber.js | 38 + .../node_modules/mkdirp/test/mkdirp.js | 28 + .../node_modules/mkdirp/test/opts_fs.js | 29 + .../node_modules/mkdirp/test/opts_fs_sync.js | 27 + .../fsevents/node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 36 + .../fsevents/node_modules/mkdirp/test/race.js | 37 + .../fsevents/node_modules/mkdirp/test/rel.js | 32 + .../node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../fsevents/node_modules/mkdirp/test/root.js | 19 + .../fsevents/node_modules/mkdirp/test/sync.js | 32 + .../node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + .../fsevents/node_modules/ms/index.js | 152 + .../fsevents/node_modules/ms/license.md | 21 + .../fsevents/node_modules/ms/package.json | 72 + .../fsevents/node_modules/ms/readme.md | 51 + .../fsevents/node_modules/needle/README.md | 593 ++ .../needle/examples/deflated-stream.js | 22 + .../needle/examples/digest-auth.js | 16 + .../needle/examples/download-to-file.js | 18 + .../needle/examples/multipart-stream.js | 25 + .../needle/examples/parsed-stream.js | 23 + .../needle/examples/parsed-stream2.js | 21 + .../needle/examples/stream-events.js | 23 + .../needle/examples/stream-to-file.js | 14 + .../needle/examples/upload-image.js | 51 + .../fsevents/node_modules/needle/lib/auth.js | 110 + .../node_modules/needle/lib/cookies.js | 77 + .../node_modules/needle/lib/decoder.js | 53 + .../node_modules/needle/lib/multipart.js | 98 + .../node_modules/needle/lib/needle.js | 783 +++ .../node_modules/needle/lib/parsers.js | 120 + .../node_modules/needle/lib/querystring.js | 49 + .../fsevents/node_modules/needle/license.txt | 19 + .../fsevents/node_modules/needle/package.json | 105 + .../needle/test/basic_auth_spec.js | 196 + .../needle/test/compression_spec.js | 94 + .../node_modules/needle/test/cookies_spec.js | 305 + .../node_modules/needle/test/decoder_spec.js | 86 + .../node_modules/needle/test/errors_spec.js | 286 + .../node_modules/needle/test/headers_spec.js | 198 + .../node_modules/needle/test/helpers.js | 72 + .../needle/test/long_string_spec.js | 34 + .../node_modules/needle/test/output_spec.js | 254 + .../node_modules/needle/test/parsing_spec.js | 494 ++ .../needle/test/post_data_spec.js | 1021 ++++ .../node_modules/needle/test/proxy_spec.js | 202 + .../needle/test/querystring_spec.js | 128 + .../node_modules/needle/test/redirect_spec.js | 392 ++ .../needle/test/redirect_with_timeout.js | 45 + .../needle/test/request_stream_spec.js | 202 + .../needle/test/response_stream_spec.js | 139 + .../needle/test/socket_pool_spec.js | 66 + .../node_modules/needle/test/url_spec.js | 147 + .../needle/test/utils/formidable.js | 17 + .../node_modules/needle/test/utils/proxy.js | 62 + .../node_modules/needle/test/utils/test.js | 104 + .../node_modules/node-pre-gyp/CHANGELOG.md | 401 ++ .../node_modules/node-pre-gyp/LICENSE | 27 + .../node_modules/node-pre-gyp/README.md | 661 +++ .../node_modules/node-pre-gyp/appveyor.yml | 37 + .../node_modules/node-pre-gyp/contributing.md | 10 + .../node_modules/node-pre-gyp/lib/build.js | 51 + .../node_modules/node-pre-gyp/lib/clean.js | 32 + .../node-pre-gyp/lib/configure.js | 52 + .../node_modules/node-pre-gyp/lib/info.js | 40 + .../node_modules/node-pre-gyp/lib/install.js | 221 + .../node-pre-gyp/lib/node-pre-gyp.js | 203 + .../node_modules/node-pre-gyp/lib/package.js | 53 + .../node-pre-gyp/lib/pre-binding.js | 30 + .../node_modules/node-pre-gyp/lib/publish.js | 79 + .../node_modules/node-pre-gyp/lib/rebuild.js | 21 + .../node-pre-gyp/lib/reinstall.js | 20 + .../node_modules/node-pre-gyp/lib/reveal.js | 33 + .../node-pre-gyp/lib/testbinary.js | 81 + .../node-pre-gyp/lib/testpackage.js | 55 + .../node-pre-gyp/lib/unpublish.js | 43 + .../node-pre-gyp/lib/util/abi_crosswalk.json | 1682 ++++++ .../node-pre-gyp/lib/util/compile.js | 87 + .../node-pre-gyp/lib/util/handle_gyp_opts.js | 100 + .../node-pre-gyp/lib/util/napi.js | 156 + .../lib/util/nw-pre-gyp/index.html | 26 + .../lib/util/nw-pre-gyp/package.json | 9 + .../node-pre-gyp/lib/util/s3_setup.js | 27 + .../node-pre-gyp/lib/util/versioning.js | 330 ++ .../node_modules/node-pre-gyp/package.json | 90 + .../fsevents/node_modules/nopt/.npmignore | 1 + .../fsevents/node_modules/nopt/.travis.yml | 8 + .../fsevents/node_modules/nopt/CHANGELOG.md | 58 + .../fsevents/node_modules/nopt/LICENSE | 15 + .../fsevents/node_modules/nopt/README.md | 213 + .../node_modules/nopt/examples/my-program.js | 30 + .../fsevents/node_modules/nopt/lib/nopt.js | 436 ++ .../fsevents/node_modules/nopt/package.json | 61 + .../fsevents/node_modules/nopt/test/basic.js | 303 + .../node_modules/npm-bundled/README.md | 46 + .../node_modules/npm-bundled/index.js | 227 + .../node_modules/npm-bundled/package.json | 63 + .../node_modules/npm-packlist/LICENSE | 15 + .../node_modules/npm-packlist/README.md | 68 + .../node_modules/npm-packlist/index.js | 220 + .../node_modules/npm-packlist/package.json | 69 + .../fsevents/node_modules/npmlog/CHANGELOG.md | 49 + .../fsevents/node_modules/npmlog/LICENSE | 15 + .../fsevents/node_modules/npmlog/README.md | 216 + .../fsevents/node_modules/npmlog/log.js | 309 + .../fsevents/node_modules/npmlog/package.json | 64 + .../node_modules/number-is-nan/index.js | 4 + .../node_modules/number-is-nan/license | 21 + .../node_modules/number-is-nan/package.json | 70 + .../node_modules/number-is-nan/readme.md | 28 + .../node_modules/object-assign/index.js | 90 + .../node_modules/object-assign/license | 21 + .../node_modules/object-assign/package.json | 77 + .../node_modules/object-assign/readme.md | 61 + .../fsevents/node_modules/once/LICENSE | 15 + .../fsevents/node_modules/once/README.md | 79 + .../fsevents/node_modules/once/once.js | 42 + .../fsevents/node_modules/once/package.json | 70 + .../fsevents/node_modules/os-homedir/index.js | 24 + .../fsevents/node_modules/os-homedir/license | 21 + .../node_modules/os-homedir/package.json | 76 + .../node_modules/os-homedir/readme.md | 31 + .../fsevents/node_modules/os-tmpdir/index.js | 25 + .../fsevents/node_modules/os-tmpdir/license | 21 + .../node_modules/os-tmpdir/package.json | 76 + .../fsevents/node_modules/os-tmpdir/readme.md | 32 + .../fsevents/node_modules/osenv/LICENSE | 15 + .../fsevents/node_modules/osenv/README.md | 63 + .../fsevents/node_modules/osenv/osenv.js | 72 + .../fsevents/node_modules/osenv/package.json | 76 + .../node_modules/path-is-absolute/index.js | 20 + .../node_modules/path-is-absolute/license | 21 + .../path-is-absolute/package.json | 78 + .../node_modules/path-is-absolute/readme.md | 59 + .../process-nextick-args/index.js | 44 + .../process-nextick-args/license.md | 19 + .../process-nextick-args/package.json | 53 + .../process-nextick-args/readme.md | 18 + .../fsevents/node_modules/rc/.npmignore | 3 + .../fsevents/node_modules/rc/LICENSE.APACHE2 | 15 + .../fsevents/node_modules/rc/LICENSE.BSD | 26 + .../fsevents/node_modules/rc/LICENSE.MIT | 24 + .../fsevents/node_modules/rc/README.md | 227 + .../fsevents/node_modules/rc/browser.js | 7 + .../fsevents/node_modules/rc/cli.js | 4 + .../fsevents/node_modules/rc/index.js | 53 + .../fsevents/node_modules/rc/lib/utils.js | 104 + .../rc/node_modules/minimist/.travis.yml | 8 + .../rc/node_modules/minimist/LICENSE | 18 + .../rc/node_modules/minimist/example/parse.js | 2 + .../rc/node_modules/minimist/index.js | 236 + .../rc/node_modules/minimist/package.json | 76 + .../rc/node_modules/minimist/readme.markdown | 91 + .../rc/node_modules/minimist/test/all_bool.js | 32 + .../rc/node_modules/minimist/test/bool.js | 166 + .../rc/node_modules/minimist/test/dash.js | 31 + .../minimist/test/default_bool.js | 35 + .../rc/node_modules/minimist/test/dotted.js | 22 + .../rc/node_modules/minimist/test/kv_short.js | 16 + .../rc/node_modules/minimist/test/long.js | 31 + .../rc/node_modules/minimist/test/num.js | 36 + .../rc/node_modules/minimist/test/parse.js | 197 + .../minimist/test/parse_modified.js | 9 + .../rc/node_modules/minimist/test/short.js | 67 + .../node_modules/minimist/test/stop_early.js | 15 + .../rc/node_modules/minimist/test/unknown.js | 102 + .../node_modules/minimist/test/whitespace.js | 8 + .../fsevents/node_modules/rc/package.json | 67 + .../fsevents/node_modules/rc/test/ini.js | 16 + .../node_modules/rc/test/nested-env-vars.js | 50 + .../fsevents/node_modules/rc/test/test.js | 59 + .../node_modules/readable-stream/.travis.yml | 55 + .../readable-stream/CONTRIBUTING.md | 38 + .../readable-stream/GOVERNANCE.md | 136 + .../node_modules/readable-stream/LICENSE | 47 + .../node_modules/readable-stream/README.md | 58 + .../doc/wg-meetings/2015-01-30.md | 60 + .../readable-stream/duplex-browser.js | 1 + .../node_modules/readable-stream/duplex.js | 1 + .../readable-stream/lib/_stream_duplex.js | 131 + .../lib/_stream_passthrough.js | 47 + .../readable-stream/lib/_stream_readable.js | 1019 ++++ .../readable-stream/lib/_stream_transform.js | 214 + .../readable-stream/lib/_stream_writable.js | 687 +++ .../lib/internal/streams/BufferList.js | 79 + .../lib/internal/streams/destroy.js | 74 + .../lib/internal/streams/stream-browser.js | 1 + .../lib/internal/streams/stream.js | 1 + .../node_modules/readable-stream/package.json | 84 + .../readable-stream/passthrough.js | 1 + .../readable-stream/readable-browser.js | 7 + .../node_modules/readable-stream/readable.js | 19 + .../node_modules/readable-stream/transform.js | 1 + .../readable-stream/writable-browser.js | 1 + .../node_modules/readable-stream/writable.js | 8 + .../fsevents/node_modules/rimraf/LICENSE | 15 + .../fsevents/node_modules/rimraf/README.md | 101 + .../fsevents/node_modules/rimraf/bin.js | 50 + .../fsevents/node_modules/rimraf/package.json | 67 + .../fsevents/node_modules/rimraf/rimraf.js | 364 ++ .../node_modules/safe-buffer/.travis.yml | 7 + .../fsevents/node_modules/safe-buffer/LICENSE | 21 + .../node_modules/safe-buffer/README.md | 584 ++ .../node_modules/safe-buffer/index.js | 62 + .../node_modules/safe-buffer/package.json | 68 + .../fsevents/node_modules/safe-buffer/test.js | 101 + .../node_modules/safer-buffer/LICENSE | 21 + .../safer-buffer/Porting-Buffer.md | 268 + .../node_modules/safer-buffer/Readme.md | 156 + .../node_modules/safer-buffer/dangerous.js | 58 + .../node_modules/safer-buffer/package.json | 63 + .../node_modules/safer-buffer/safer.js | 77 + .../node_modules/safer-buffer/tests.js | 406 ++ .../fsevents/node_modules/sax/LICENSE | 41 + .../fsevents/node_modules/sax/README.md | 225 + .../fsevents/node_modules/sax/lib/sax.js | 1565 +++++ .../fsevents/node_modules/sax/package.json | 64 + .../fsevents/node_modules/semver/LICENSE | 15 + .../fsevents/node_modules/semver/README.md | 388 ++ .../fsevents/node_modules/semver/package.json | 57 + .../fsevents/node_modules/semver/range.bnf | 16 + .../fsevents/node_modules/semver/semver.js | 1324 +++++ .../node_modules/set-blocking/CHANGELOG.md | 26 + .../node_modules/set-blocking/LICENSE.txt | 14 + .../node_modules/set-blocking/README.md | 31 + .../node_modules/set-blocking/index.js | 7 + .../node_modules/set-blocking/package.json | 73 + .../node_modules/signal-exit/CHANGELOG.md | 27 + .../node_modules/signal-exit/LICENSE.txt | 16 + .../node_modules/signal-exit/README.md | 40 + .../node_modules/signal-exit/index.js | 157 + .../node_modules/signal-exit/package.json | 69 + .../node_modules/signal-exit/signals.js | 53 + .../node_modules/string-width/index.js | 37 + .../node_modules/string-width/license | 21 + .../node_modules/string-width/package.json | 92 + .../node_modules/string-width/readme.md | 42 + .../node_modules/string_decoder/.travis.yml | 50 + .../node_modules/string_decoder/LICENSE | 48 + .../node_modules/string_decoder/README.md | 47 + .../string_decoder/lib/string_decoder.js | 296 + .../node_modules/string_decoder/package.json | 62 + .../fsevents/node_modules/strip-ansi/index.js | 6 + .../fsevents/node_modules/strip-ansi/license | 21 + .../node_modules/strip-ansi/package.json | 105 + .../node_modules/strip-ansi/readme.md | 33 + .../node_modules/strip-json-comments/index.js | 70 + .../node_modules/strip-json-comments/license | 21 + .../strip-json-comments/package.json | 77 + .../strip-json-comments/readme.md | 64 + .../fsevents/node_modules/tar/LICENSE | 15 + .../fsevents/node_modules/tar/README.md | 949 +++ .../fsevents/node_modules/tar/index.js | 18 + .../fsevents/node_modules/tar/lib/buffer.js | 11 + .../fsevents/node_modules/tar/lib/create.js | 105 + .../fsevents/node_modules/tar/lib/extract.js | 112 + .../fsevents/node_modules/tar/lib/header.js | 273 + .../node_modules/tar/lib/high-level-opt.js | 29 + .../node_modules/tar/lib/large-numbers.js | 92 + .../fsevents/node_modules/tar/lib/list.js | 130 + .../fsevents/node_modules/tar/lib/mkdir.js | 206 + .../fsevents/node_modules/tar/lib/pack.js | 403 ++ .../fsevents/node_modules/tar/lib/parse.js | 422 ++ .../fsevents/node_modules/tar/lib/pax.js | 146 + .../node_modules/tar/lib/read-entry.js | 94 + .../fsevents/node_modules/tar/lib/replace.js | 220 + .../fsevents/node_modules/tar/lib/types.js | 44 + .../fsevents/node_modules/tar/lib/unpack.js | 560 ++ .../fsevents/node_modules/tar/lib/update.js | 36 + .../node_modules/tar/lib/warn-mixin.js | 14 + .../fsevents/node_modules/tar/lib/winchars.js | 23 + .../node_modules/tar/lib/write-entry.js | 403 ++ .../fsevents/node_modules/tar/package.json | 81 + .../node_modules/util-deprecate/History.md | 16 + .../node_modules/util-deprecate/LICENSE | 24 + .../node_modules/util-deprecate/README.md | 53 + .../node_modules/util-deprecate/browser.js | 67 + .../node_modules/util-deprecate/node.js | 6 + .../node_modules/util-deprecate/package.json | 59 + .../fsevents/node_modules/wide-align/LICENSE | 14 + .../node_modules/wide-align/README.md | 47 + .../fsevents/node_modules/wide-align/align.js | 65 + .../node_modules/wide-align/package.json | 69 + .../fsevents/node_modules/wrappy/LICENSE | 15 + .../fsevents/node_modules/wrappy/README.md | 36 + .../fsevents/node_modules/wrappy/package.json | 62 + .../fsevents/node_modules/wrappy/wrappy.js | 33 + .../fsevents/node_modules/yallist/LICENSE | 15 + .../fsevents/node_modules/yallist/README.md | 204 + .../fsevents/node_modules/yallist/iterator.js | 8 + .../node_modules/yallist/package.json | 66 + .../fsevents/node_modules/yallist/yallist.js | 376 ++ js/node_modules/fsevents/package.json | 76 + js/node_modules/fsevents/src/async.cc | 43 + js/node_modules/fsevents/src/constants.cc | 110 + js/node_modules/fsevents/src/locking.cc | 27 + js/node_modules/fsevents/src/methods.cc | 44 + js/node_modules/fsevents/src/storage.cc | 27 + js/node_modules/fsevents/src/thread.cc | 72 + js/node_modules/get-value/LICENSE | 21 + js/node_modules/get-value/index.js | 50 + js/node_modules/get-value/package.json | 113 + js/node_modules/glob-base/LICENSE | 21 + js/node_modules/glob-base/README.md | 158 + js/node_modules/glob-base/index.js | 51 + js/node_modules/glob-base/package.json | 77 + js/node_modules/glob-parent/.npmignore | 4 + js/node_modules/glob-parent/.travis.yml | 8 + js/node_modules/glob-parent/LICENSE | 15 + js/node_modules/glob-parent/README.md | 43 + js/node_modules/glob-parent/index.js | 10 + js/node_modules/glob-parent/package.json | 63 + js/node_modules/glob-parent/test.js | 28 + js/node_modules/global-modules/LICENSE | 21 + js/node_modules/global-modules/README.md | 75 + js/node_modules/global-modules/index.js | 31 + js/node_modules/global-modules/package.json | 112 + js/node_modules/global-prefix/LICENSE | 21 + js/node_modules/global-prefix/README.md | 78 + js/node_modules/global-prefix/index.js | 96 + js/node_modules/global-prefix/package.json | 130 + js/node_modules/graceful-fs/LICENSE | 15 + js/node_modules/graceful-fs/README.md | 133 + js/node_modules/graceful-fs/fs.js | 21 + js/node_modules/graceful-fs/graceful-fs.js | 262 + js/node_modules/graceful-fs/legacy-streams.js | 118 + js/node_modules/graceful-fs/package.json | 76 + js/node_modules/graceful-fs/polyfills.js | 330 ++ js/node_modules/has-value/LICENSE | 21 + js/node_modules/has-value/README.md | 149 + js/node_modules/has-value/index.js | 16 + .../has-value/node_modules/isobject/LICENSE | 21 + .../has-value/node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../has-value/node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/has-value/package.json | 120 + js/node_modules/has-values/LICENSE | 21 + js/node_modules/has-values/README.md | 129 + js/node_modules/has-values/index.js | 60 + .../has-values/node_modules/is-number/LICENSE | 21 + .../node_modules/is-number/README.md | 115 + .../node_modules/is-number/index.js | 22 + .../is-number/node_modules/kind-of/LICENSE | 21 + .../is-number/node_modules/kind-of/README.md | 261 + .../is-number/node_modules/kind-of/index.js | 116 + .../node_modules/kind-of/package.json | 139 + .../node_modules/is-number/package.json | 123 + .../has-values/node_modules/kind-of/LICENSE | 21 + .../has-values/node_modules/kind-of/README.md | 267 + .../has-values/node_modules/kind-of/index.js | 119 + .../node_modules/kind-of/package.json | 139 + js/node_modules/has-values/package.json | 115 + js/node_modules/homedir-polyfill/LICENSE | 21 + js/node_modules/homedir-polyfill/README.md | 75 + js/node_modules/homedir-polyfill/index.js | 85 + js/node_modules/homedir-polyfill/package.json | 93 + js/node_modules/inherits/LICENSE | 16 + js/node_modules/inherits/README.md | 42 + js/node_modules/inherits/inherits.js | 7 + js/node_modules/inherits/inherits_browser.js | 23 + js/node_modules/inherits/package.json | 62 + js/node_modules/ini/LICENSE | 15 + js/node_modules/ini/README.md | 102 + js/node_modules/ini/ini.js | 194 + js/node_modules/ini/package.json | 63 + .../is-accessor-descriptor/LICENSE | 21 + .../is-accessor-descriptor/README.md | 123 + .../is-accessor-descriptor/index.js | 69 + .../is-accessor-descriptor/package.json | 92 + js/node_modules/is-binary-path/index.js | 12 + js/node_modules/is-binary-path/license | 21 + js/node_modules/is-binary-path/package.json | 71 + js/node_modules/is-binary-path/readme.md | 34 + js/node_modules/is-buffer/LICENSE | 21 + js/node_modules/is-buffer/README.md | 53 + js/node_modules/is-buffer/index.js | 21 + js/node_modules/is-buffer/package.json | 82 + js/node_modules/is-buffer/test/basic.js | 24 + js/node_modules/is-data-descriptor/LICENSE | 21 + js/node_modules/is-data-descriptor/README.md | 128 + js/node_modules/is-data-descriptor/index.js | 55 + .../is-data-descriptor/package.json | 91 + js/node_modules/is-descriptor/LICENSE | 21 + js/node_modules/is-descriptor/README.md | 193 + js/node_modules/is-descriptor/index.js | 22 + .../node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 342 ++ .../node_modules/kind-of/index.js | 147 + .../node_modules/kind-of/package.json | 146 + js/node_modules/is-descriptor/package.json | 117 + js/node_modules/is-dotfile/LICENSE | 21 + js/node_modules/is-dotfile/README.md | 95 + js/node_modules/is-dotfile/index.js | 14 + js/node_modules/is-dotfile/package.json | 106 + js/node_modules/is-equal-shallow/LICENSE | 21 + js/node_modules/is-equal-shallow/README.md | 90 + js/node_modules/is-equal-shallow/index.js | 27 + js/node_modules/is-equal-shallow/package.json | 85 + js/node_modules/is-extendable/LICENSE | 21 + js/node_modules/is-extendable/README.md | 72 + js/node_modules/is-extendable/index.js | 13 + js/node_modules/is-extendable/package.json | 92 + js/node_modules/is-extglob/LICENSE | 21 + js/node_modules/is-extglob/README.md | 75 + js/node_modules/is-extglob/index.js | 11 + js/node_modules/is-extglob/package.json | 79 + js/node_modules/is-glob/LICENSE | 21 + js/node_modules/is-glob/README.md | 105 + js/node_modules/is-glob/index.js | 14 + js/node_modules/is-glob/package.json | 92 + js/node_modules/is-number/LICENSE | 21 + js/node_modules/is-number/README.md | 103 + js/node_modules/is-number/index.js | 19 + js/node_modules/is-number/package.json | 90 + js/node_modules/is-odd/LICENSE | 21 + js/node_modules/is-odd/README.md | 94 + js/node_modules/is-odd/index.js | 20 + .../is-odd/node_modules/is-number/LICENSE | 21 + .../is-odd/node_modules/is-number/README.md | 135 + .../is-odd/node_modules/is-number/index.js | 21 + .../node_modules/is-number/package.json | 113 + js/node_modules/is-odd/package.json | 110 + js/node_modules/is-plain-object/LICENSE | 21 + js/node_modules/is-plain-object/README.md | 104 + js/node_modules/is-plain-object/index.d.ts | 5 + js/node_modules/is-plain-object/index.js | 37 + .../node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/is-plain-object/package.json | 124 + js/node_modules/is-posix-bracket/LICENSE | 21 + js/node_modules/is-posix-bracket/README.md | 88 + js/node_modules/is-posix-bracket/index.js | 10 + js/node_modules/is-posix-bracket/package.json | 95 + js/node_modules/is-primitive/LICENSE | 21 + js/node_modules/is-primitive/README.md | 57 + js/node_modules/is-primitive/index.js | 13 + js/node_modules/is-primitive/package.json | 71 + js/node_modules/is-windows/LICENSE | 21 + js/node_modules/is-windows/README.md | 95 + js/node_modules/is-windows/index.js | 27 + js/node_modules/is-windows/package.json | 113 + js/node_modules/isarray/.npmignore | 1 + js/node_modules/isarray/.travis.yml | 4 + js/node_modules/isarray/Makefile | 6 + js/node_modules/isarray/README.md | 60 + js/node_modules/isarray/component.json | 19 + js/node_modules/isarray/index.js | 5 + js/node_modules/isarray/package.json | 75 + js/node_modules/isarray/test.js | 20 + js/node_modules/isexe/.npmignore | 2 + js/node_modules/isexe/LICENSE | 15 + js/node_modules/isexe/README.md | 51 + js/node_modules/isexe/index.js | 57 + js/node_modules/isexe/mode.js | 41 + js/node_modules/isexe/package.json | 60 + js/node_modules/isexe/test/basic.js | 221 + js/node_modules/isexe/windows.js | 42 + js/node_modules/isobject/LICENSE | 21 + js/node_modules/isobject/README.md | 112 + js/node_modules/isobject/index.js | 14 + js/node_modules/isobject/package.json | 98 + js/node_modules/js-reporters/.babelrc | 8 + js/node_modules/js-reporters/CHANGELOG.md | 45 + js/node_modules/js-reporters/LICENSE | 21 + js/node_modules/js-reporters/README.md | 212 + js/node_modules/js-reporters/RELEASE.md | 10 + .../js-reporters/dist/js-reporters.js | 1685 ++++++ js/node_modules/js-reporters/docs/example.md | 236 + .../js-reporters/docs/frameworks.md | 232 + .../js-reporters/img/situation-expected.png | Bin 0 -> 120377 bytes .../js-reporters/img/situation-now.png | Bin 0 -> 130072 bytes js/node_modules/js-reporters/index.js | 26 + js/node_modules/js-reporters/karma.conf.js | 46 + js/node_modules/js-reporters/lib/Data.js | 168 + .../lib/adapters/JasmineAdapter.js | 142 + .../js-reporters/lib/adapters/MochaAdapter.js | 152 + .../js-reporters/lib/adapters/QUnitAdapter.js | 181 + js/node_modules/js-reporters/lib/helpers.js | 54 + .../lib/reporters/ConsoleReporter.js | 47 + .../js-reporters/lib/reporters/TapReporter.js | 65 + js/node_modules/js-reporters/license-header | 10 + js/node_modules/js-reporters/package.json | 90 + js/node_modules/js-reporters/rollup.config.js | 24 + .../js-reporters/test/fixtures/jasmine.js | 49 + .../js-reporters/test/fixtures/mocha.js | 49 + .../js-reporters/test/fixtures/qunit.js | 47 + .../test/integration/adapters-run.js | 62 + .../js-reporters/test/integration/adapters.js | 343 ++ .../test/integration/reference-data.js | 176 + .../js-reporters/test/unit/data.js | 38 + .../js-reporters/test/unit/helpers.js | 97 + .../js-reporters/test/unit/tap-reporter.js | 140 + .../test/versions/failing-versions.js | 29 + .../test/versions/versions-reporting.js | 52 + .../js-reporters/test/versions/versions.js | 21 + js/node_modules/kind-of/LICENSE | 21 + js/node_modules/kind-of/README.md | 261 + js/node_modules/kind-of/index.js | 116 + js/node_modules/kind-of/package.json | 146 + js/node_modules/map-cache/LICENSE | 21 + js/node_modules/map-cache/README.md | 145 + js/node_modules/map-cache/index.js | 100 + js/node_modules/map-cache/package.json | 91 + js/node_modules/map-visit/LICENSE | 21 + js/node_modules/map-visit/README.md | 155 + js/node_modules/map-visit/index.js | 37 + js/node_modules/map-visit/package.json | 113 + js/node_modules/matcher-collection/README.md | 26 + js/node_modules/matcher-collection/index.js | 36 + .../matcher-collection/package.json | 56 + js/node_modules/math-random/.npmignore | 1 + js/node_modules/math-random/.travis.yml | 6 + js/node_modules/math-random/browser.js | 17 + js/node_modules/math-random/node.js | 13 + js/node_modules/math-random/package.json | 58 + js/node_modules/math-random/readme.md | 26 + js/node_modules/math-random/test.js | 26 + js/node_modules/micromatch/LICENSE | 21 + js/node_modules/micromatch/README.md | 689 +++ js/node_modules/micromatch/index.js | 431 ++ js/node_modules/micromatch/lib/chars.js | 67 + js/node_modules/micromatch/lib/expand.js | 304 + js/node_modules/micromatch/lib/glob.js | 193 + js/node_modules/micromatch/lib/utils.js | 149 + js/node_modules/micromatch/package.json | 145 + js/node_modules/minimatch/LICENSE | 15 + js/node_modules/minimatch/README.md | 209 + js/node_modules/minimatch/minimatch.js | 923 +++ js/node_modules/minimatch/package.json | 64 + js/node_modules/mixin-deep/LICENSE | 21 + js/node_modules/mixin-deep/README.md | 80 + js/node_modules/mixin-deep/index.js | 53 + .../node_modules/is-extendable/LICENSE | 21 + .../node_modules/is-extendable/README.md | 88 + .../node_modules/is-extendable/index.d.ts | 5 + .../node_modules/is-extendable/index.js | 14 + .../node_modules/is-extendable/package.json | 98 + js/node_modules/mixin-deep/package.json | 98 + js/node_modules/ms/index.js | 152 + js/node_modules/ms/license.md | 21 + js/node_modules/ms/package.json | 69 + js/node_modules/ms/readme.md | 51 + js/node_modules/nan/CHANGELOG.md | 492 ++ js/node_modules/nan/LICENSE.md | 13 + js/node_modules/nan/README.md | 456 ++ js/node_modules/nan/doc/asyncworker.md | 146 + js/node_modules/nan/doc/buffers.md | 54 + js/node_modules/nan/doc/callback.md | 76 + js/node_modules/nan/doc/converters.md | 41 + js/node_modules/nan/doc/errors.md | 226 + js/node_modules/nan/doc/json.md | 62 + js/node_modules/nan/doc/maybe_types.md | 583 ++ js/node_modules/nan/doc/methods.md | 659 +++ js/node_modules/nan/doc/new.md | 147 + js/node_modules/nan/doc/node_misc.md | 123 + js/node_modules/nan/doc/object_wrappers.md | 263 + js/node_modules/nan/doc/persistent.md | 295 + js/node_modules/nan/doc/scopes.md | 73 + js/node_modules/nan/doc/script.md | 38 + js/node_modules/nan/doc/string_bytes.md | 62 + js/node_modules/nan/doc/v8_internals.md | 199 + js/node_modules/nan/doc/v8_misc.md | 85 + js/node_modules/nan/include_dirs.js | 1 + js/node_modules/nan/nan.h | 2761 +++++++++ js/node_modules/nan/nan_callbacks.h | 88 + js/node_modules/nan/nan_callbacks_12_inl.h | 512 ++ .../nan/nan_callbacks_pre_12_inl.h | 520 ++ js/node_modules/nan/nan_converters.h | 72 + js/node_modules/nan/nan_converters_43_inl.h | 48 + .../nan/nan_converters_pre_43_inl.h | 42 + .../nan/nan_define_own_property_helper.h | 29 + .../nan/nan_implementation_12_inl.h | 399 ++ .../nan/nan_implementation_pre_12_inl.h | 263 + js/node_modules/nan/nan_json.h | 166 + js/node_modules/nan/nan_maybe_43_inl.h | 369 ++ js/node_modules/nan/nan_maybe_pre_43_inl.h | 316 + js/node_modules/nan/nan_new.h | 340 ++ js/node_modules/nan/nan_object_wrap.h | 155 + js/node_modules/nan/nan_persistent_12_inl.h | 132 + .../nan/nan_persistent_pre_12_inl.h | 242 + js/node_modules/nan/nan_private.h | 73 + js/node_modules/nan/nan_string_bytes.h | 305 + js/node_modules/nan/nan_typedarray_contents.h | 90 + js/node_modules/nan/nan_weak.h | 432 ++ js/node_modules/nan/package.json | 97 + js/node_modules/nan/tools/1to2.js | 412 ++ js/node_modules/nan/tools/README.md | 14 + js/node_modules/nan/tools/package.json | 19 + js/node_modules/nanomatch/CHANGELOG.md | 57 + js/node_modules/nanomatch/LICENSE | 21 + js/node_modules/nanomatch/README.md | 1148 ++++ js/node_modules/nanomatch/index.js | 838 +++ js/node_modules/nanomatch/lib/cache.js | 1 + js/node_modules/nanomatch/lib/compiler2.js | 320 + js/node_modules/nanomatch/lib/compilers.js | 339 ++ js/node_modules/nanomatch/lib/parsers.js | 387 ++ js/node_modules/nanomatch/lib/utils.js | 379 ++ .../nanomatch/node_modules/arr-diff/LICENSE | 21 + .../nanomatch/node_modules/arr-diff/README.md | 130 + .../nanomatch/node_modules/arr-diff/index.js | 47 + .../node_modules/arr-diff/package.json | 108 + .../node_modules/array-unique/LICENSE | 21 + .../node_modules/array-unique/README.md | 77 + .../node_modules/array-unique/index.js | 43 + .../node_modules/array-unique/package.json | 93 + .../node_modules/kind-of/CHANGELOG.md | 157 + .../nanomatch/node_modules/kind-of/LICENSE | 21 + .../nanomatch/node_modules/kind-of/README.md | 365 ++ .../nanomatch/node_modules/kind-of/index.js | 129 + .../node_modules/kind-of/package.json | 143 + js/node_modules/nanomatch/package.json | 172 + js/node_modules/normalize-path/LICENSE | 21 + js/node_modules/normalize-path/README.md | 92 + js/node_modules/normalize-path/index.js | 19 + js/node_modules/normalize-path/package.json | 118 + js/node_modules/object-copy/LICENSE | 21 + js/node_modules/object-copy/index.js | 174 + .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 77 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 82 + js/node_modules/object-copy/package.json | 80 + js/node_modules/object-visit/LICENSE | 21 + js/node_modules/object-visit/README.md | 83 + js/node_modules/object-visit/index.js | 33 + .../node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/object-visit/package.json | 97 + js/node_modules/object.omit/LICENSE | 21 + js/node_modules/object.omit/README.md | 118 + js/node_modules/object.omit/index.js | 40 + js/node_modules/object.omit/package.json | 98 + js/node_modules/object.pick/LICENSE | 21 + js/node_modules/object.pick/README.md | 76 + js/node_modules/object.pick/index.js | 35 + .../object.pick/node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/object.pick/package.json | 92 + js/node_modules/parse-glob/LICENSE | 21 + js/node_modules/parse-glob/README.md | 115 + js/node_modules/parse-glob/index.js | 156 + js/node_modules/parse-glob/package.json | 93 + js/node_modules/parse-passwd/LICENSE | 21 + js/node_modules/parse-passwd/README.md | 86 + js/node_modules/parse-passwd/index.js | 56 + js/node_modules/parse-passwd/package.json | 86 + js/node_modules/pascalcase/LICENSE | 21 + js/node_modules/pascalcase/README.md | 80 + js/node_modules/pascalcase/index.js | 21 + js/node_modules/pascalcase/package.json | 77 + js/node_modules/path-is-absolute/index.js | 20 + js/node_modules/path-is-absolute/license | 21 + js/node_modules/path-is-absolute/package.json | 75 + js/node_modules/path-is-absolute/readme.md | 59 + js/node_modules/path-parse/.travis.yml | 9 + js/node_modules/path-parse/README.md | 44 + js/node_modules/path-parse/index.js | 93 + js/node_modules/path-parse/index.min.js | 1 + js/node_modules/path-parse/package.json | 61 + js/node_modules/path-parse/test.js | 77 + js/node_modules/path-parse/test.min.js | 1 + .../posix-character-classes/LICENSE | 21 + .../posix-character-classes/README.md | 103 + .../posix-character-classes/index.js | 22 + .../posix-character-classes/package.json | 85 + js/node_modules/preserve/.gitattributes | 14 + js/node_modules/preserve/.jshintrc | 24 + js/node_modules/preserve/.npmignore | 53 + js/node_modules/preserve/.travis.yml | 3 + js/node_modules/preserve/.verb.md | 59 + js/node_modules/preserve/LICENSE | 24 + js/node_modules/preserve/README.md | 90 + js/node_modules/preserve/index.js | 54 + js/node_modules/preserve/package.json | 73 + js/node_modules/preserve/test.js | 48 + js/node_modules/process-nextick-args/index.js | 44 + .../process-nextick-args/license.md | 19 + .../process-nextick-args/package.json | 50 + .../process-nextick-args/readme.md | 18 + js/node_modules/qunit/History.md | 1004 ++++ js/node_modules/qunit/LICENSE.txt | 35 + js/node_modules/qunit/README.md | 34 + js/node_modules/qunit/package.json | 130 + js/node_modules/qunit/qunit/qunit.css | 436 ++ js/node_modules/qunit/qunit/qunit.js | 5264 +++++++++++++++++ js/node_modules/randomatic/LICENSE | 21 + js/node_modules/randomatic/README.md | 170 + js/node_modules/randomatic/index.js | 86 + .../randomatic/node_modules/is-number/LICENSE | 21 + .../node_modules/is-number/README.md | 135 + .../node_modules/is-number/index.js | 21 + .../node_modules/is-number/package.json | 113 + .../node_modules/kind-of/CHANGELOG.md | 157 + .../randomatic/node_modules/kind-of/LICENSE | 21 + .../randomatic/node_modules/kind-of/README.md | 365 ++ .../randomatic/node_modules/kind-of/index.js | 129 + .../node_modules/kind-of/package.json | 143 + js/node_modules/randomatic/package.json | 135 + js/node_modules/readable-stream/.travis.yml | 55 + .../readable-stream/CONTRIBUTING.md | 38 + js/node_modules/readable-stream/GOVERNANCE.md | 136 + js/node_modules/readable-stream/LICENSE | 47 + js/node_modules/readable-stream/README.md | 58 + .../doc/wg-meetings/2015-01-30.md | 60 + .../readable-stream/duplex-browser.js | 1 + js/node_modules/readable-stream/duplex.js | 1 + .../readable-stream/lib/_stream_duplex.js | 131 + .../lib/_stream_passthrough.js | 47 + .../readable-stream/lib/_stream_readable.js | 1019 ++++ .../readable-stream/lib/_stream_transform.js | 214 + .../readable-stream/lib/_stream_writable.js | 687 +++ .../lib/internal/streams/BufferList.js | 79 + .../lib/internal/streams/destroy.js | 74 + .../lib/internal/streams/stream-browser.js | 1 + .../lib/internal/streams/stream.js | 1 + js/node_modules/readable-stream/package.json | 81 + .../readable-stream/passthrough.js | 1 + .../readable-stream/readable-browser.js | 7 + js/node_modules/readable-stream/readable.js | 19 + js/node_modules/readable-stream/transform.js | 1 + .../readable-stream/writable-browser.js | 1 + js/node_modules/readable-stream/writable.js | 8 + js/node_modules/readdirp/.npmignore | 15 + js/node_modules/readdirp/.travis.yml | 6 + js/node_modules/readdirp/LICENSE | 20 + js/node_modules/readdirp/README.md | 233 + js/node_modules/readdirp/examples/Readme.md | 37 + .../readdirp/examples/callback-api.js | 10 + js/node_modules/readdirp/examples/grep.js | 71 + .../readdirp/examples/package.json | 9 + .../readdirp/examples/stream-api-pipe.js | 19 + .../readdirp/examples/stream-api.js | 15 + js/node_modules/readdirp/package.json | 79 + js/node_modules/readdirp/readdirp.js | 300 + js/node_modules/readdirp/stream-api.js | 99 + .../test/bed/root_dir1/root_dir1_file1.ext1 | 0 .../test/bed/root_dir1/root_dir1_file2.ext2 | 0 .../test/bed/root_dir1/root_dir1_file3.ext3 | 0 .../root1_dir1_subdir1_file1.ext1 | 0 .../test/bed/root_dir2/root_dir2_file1.ext1 | 0 .../test/bed/root_dir2/root_dir2_file2.ext2 | 0 .../readdirp/test/bed/root_file1.ext1 | 0 .../readdirp/test/bed/root_file2.ext2 | 0 .../readdirp/test/bed/root_file3.ext3 | 0 .../readdirp/test/readdirp-stream.js | 338 ++ js/node_modules/readdirp/test/readdirp.js | 289 + js/node_modules/regex-cache/LICENSE | 21 + js/node_modules/regex-cache/README.md | 166 + js/node_modules/regex-cache/index.js | 68 + js/node_modules/regex-cache/package.json | 101 + js/node_modules/regex-not/LICENSE | 21 + js/node_modules/regex-not/README.md | 133 + js/node_modules/regex-not/index.js | 72 + js/node_modules/regex-not/package.json | 98 + .../remove-trailing-separator/history.md | 17 + .../remove-trailing-separator/index.js | 17 + .../remove-trailing-separator/license | 3 + .../remove-trailing-separator/package.json | 64 + .../remove-trailing-separator/readme.md | 51 + js/node_modules/repeat-element/LICENSE | 21 + js/node_modules/repeat-element/README.md | 71 + js/node_modules/repeat-element/index.js | 18 + js/node_modules/repeat-element/package.json | 71 + js/node_modules/repeat-string/LICENSE | 21 + js/node_modules/repeat-string/README.md | 136 + js/node_modules/repeat-string/index.js | 70 + js/node_modules/repeat-string/package.json | 130 + js/node_modules/resolve-dir/LICENSE | 21 + js/node_modules/resolve-dir/README.md | 88 + js/node_modules/resolve-dir/index.js | 22 + js/node_modules/resolve-dir/package.json | 105 + js/node_modules/resolve-url/.jshintrc | 44 + js/node_modules/resolve-url/LICENSE | 21 + js/node_modules/resolve-url/bower.json | 15 + js/node_modules/resolve-url/changelog.md | 15 + js/node_modules/resolve-url/component.json | 15 + js/node_modules/resolve-url/package.json | 68 + js/node_modules/resolve-url/readme.md | 83 + js/node_modules/resolve-url/resolve-url.js | 47 + .../resolve-url/test/resolve-url.js | 70 + js/node_modules/resolve/.editorconfig | 20 + js/node_modules/resolve/.eslintignore | 1 + js/node_modules/resolve/.eslintrc | 30 + js/node_modules/resolve/.travis.yml | 173 + js/node_modules/resolve/LICENSE | 18 + js/node_modules/resolve/appveyor.yml | 44 + js/node_modules/resolve/example/async.js | 5 + js/node_modules/resolve/example/sync.js | 3 + js/node_modules/resolve/index.js | 8 + js/node_modules/resolve/lib/async.js | 203 + js/node_modules/resolve/lib/caller.js | 8 + js/node_modules/resolve/lib/core.js | 34 + js/node_modules/resolve/lib/core.json | 43 + .../resolve/lib/node-modules-paths.js | 45 + js/node_modules/resolve/lib/sync.js | 93 + js/node_modules/resolve/package.json | 69 + js/node_modules/resolve/readme.markdown | 160 + js/node_modules/resolve/test/core.js | 36 + js/node_modules/resolve/test/dotdot.js | 29 + .../resolve/test/dotdot/abc/index.js | 2 + js/node_modules/resolve/test/dotdot/index.js | 1 + .../resolve/test/faulty_basedir.js | 13 + js/node_modules/resolve/test/filter.js | 19 + js/node_modules/resolve/test/filter_sync.js | 16 + js/node_modules/resolve/test/mock.js | 143 + js/node_modules/resolve/test/mock_sync.js | 67 + js/node_modules/resolve/test/module_dir.js | 56 + .../test/module_dir/xmodules/aaa/index.js | 1 + .../test/module_dir/ymodules/aaa/index.js | 1 + .../test/module_dir/zmodules/bbb/main.js | 1 + .../test/module_dir/zmodules/bbb/package.json | 3 + .../resolve/test/node-modules-paths.js | 93 + js/node_modules/resolve/test/node_path.js | 49 + .../resolve/test/node_path/x/aaa/index.js | 1 + .../resolve/test/node_path/x/ccc/index.js | 1 + .../resolve/test/node_path/y/bbb/index.js | 1 + .../resolve/test/node_path/y/ccc/index.js | 1 + js/node_modules/resolve/test/nonstring.js | 9 + js/node_modules/resolve/test/pathfilter.js | 42 + .../resolve/test/pathfilter/deep_ref/main.js | 0 js/node_modules/resolve/test/precedence.js | 23 + .../resolve/test/precedence/aaa.js | 1 + .../resolve/test/precedence/aaa/index.js | 1 + .../resolve/test/precedence/aaa/main.js | 1 + .../resolve/test/precedence/bbb.js | 1 + .../resolve/test/precedence/bbb/main.js | 1 + js/node_modules/resolve/test/resolver.js | 349 ++ .../resolve/test/resolver/baz/doom.js | 0 .../resolve/test/resolver/baz/package.json | 3 + .../resolve/test/resolver/baz/quux.js | 1 + .../resolve/test/resolver/cup.coffee | 1 + .../resolve/test/resolver/dot_main/index.js | 1 + .../test/resolver/dot_main/package.json | 3 + .../test/resolver/dot_slash_main/index.js | 1 + .../test/resolver/dot_slash_main/package.json | 3 + js/node_modules/resolve/test/resolver/foo.js | 1 + .../test/resolver/incorrect_main/index.js | 2 + .../test/resolver/incorrect_main/package.json | 3 + .../resolve/test/resolver/mug.coffee | 0 js/node_modules/resolve/test/resolver/mug.js | 0 .../test/resolver/other_path/lib/other-lib.js | 0 .../resolve/test/resolver/other_path/root.js | 0 .../resolve/test/resolver/quux/foo/index.js | 1 + .../resolve/test/resolver/same_names/foo.js | 1 + .../test/resolver/same_names/foo/index.js | 1 + .../symlinked/_/symlink_target/.gitkeep | 0 .../test/resolver/without_basedir/main.js | 5 + js/node_modules/resolve/test/resolver_sync.js | 267 + js/node_modules/resolve/test/subdirs.js | 13 + js/node_modules/resolve/test/symlinks.js | 54 + js/node_modules/ret/LICENSE | 19 + js/node_modules/ret/README.md | 183 + js/node_modules/ret/lib/index.js | 282 + js/node_modules/ret/lib/positions.js | 17 + js/node_modules/ret/lib/sets.js | 82 + js/node_modules/ret/lib/types.js | 10 + js/node_modules/ret/lib/util.js | 111 + js/node_modules/ret/package.json | 67 + js/node_modules/safe-buffer/LICENSE | 21 + js/node_modules/safe-buffer/README.md | 584 ++ js/node_modules/safe-buffer/index.d.ts | 187 + js/node_modules/safe-buffer/index.js | 62 + js/node_modules/safe-buffer/package.json | 63 + js/node_modules/safe-regex/.travis.yml | 4 + js/node_modules/safe-regex/LICENSE | 18 + js/node_modules/safe-regex/example/safe.js | 3 + js/node_modules/safe-regex/index.js | 43 + js/node_modules/safe-regex/package.json | 74 + js/node_modules/safe-regex/readme.markdown | 65 + js/node_modules/safe-regex/test/regex.js | 50 + js/node_modules/set-immediate-shim/index.js | 7 + .../set-immediate-shim/package.json | 66 + js/node_modules/set-immediate-shim/readme.md | 31 + js/node_modules/set-value/LICENSE | 21 + js/node_modules/set-value/README.md | 150 + js/node_modules/set-value/index.js | 51 + .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + js/node_modules/set-value/package.json | 120 + js/node_modules/snapdragon-node/LICENSE | 21 + js/node_modules/snapdragon-node/README.md | 453 ++ js/node_modules/snapdragon-node/index.js | 492 ++ .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 95 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 93 + .../is-accessor-descriptor/LICENSE | 21 + .../is-accessor-descriptor/README.md | 144 + .../is-accessor-descriptor/index.js | 69 + .../is-accessor-descriptor/package.json | 110 + .../node_modules/is-data-descriptor/LICENSE | 21 + .../node_modules/is-data-descriptor/README.md | 161 + .../node_modules/is-data-descriptor/index.js | 49 + .../is-data-descriptor/package.json | 109 + .../node_modules/is-descriptor/LICENSE | 21 + .../node_modules/is-descriptor/README.md | 193 + .../node_modules/is-descriptor/index.js | 22 + .../node_modules/is-descriptor/package.json | 114 + .../node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + .../node_modules/kind-of/CHANGELOG.md | 157 + .../node_modules/kind-of/LICENSE | 21 + .../node_modules/kind-of/README.md | 365 ++ .../node_modules/kind-of/index.js | 129 + .../node_modules/kind-of/package.json | 145 + js/node_modules/snapdragon-node/package.json | 107 + js/node_modules/snapdragon-util/LICENSE | 21 + js/node_modules/snapdragon-util/README.md | 807 +++ js/node_modules/snapdragon-util/index.js | 1019 ++++ js/node_modules/snapdragon-util/package.json | 96 + js/node_modules/snapdragon/LICENSE | 21 + js/node_modules/snapdragon/README.md | 321 + js/node_modules/snapdragon/index.js | 174 + js/node_modules/snapdragon/lib/compiler.js | 177 + js/node_modules/snapdragon/lib/parser.js | 533 ++ js/node_modules/snapdragon/lib/position.js | 14 + js/node_modules/snapdragon/lib/source-maps.js | 145 + js/node_modules/snapdragon/lib/utils.js | 48 + .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 77 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 82 + .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + js/node_modules/snapdragon/package.json | 126 + js/node_modules/source-map-resolve/.jshintrc | 46 + .../source-map-resolve/.travis.yml | 3 + js/node_modules/source-map-resolve/LICENSE | 21 + js/node_modules/source-map-resolve/bower.json | 30 + .../source-map-resolve/changelog.md | 100 + .../source-map-resolve/component.json | 29 + .../generate-source-map-resolve.js | 28 + .../lib/decode-uri-component.js | 11 + .../source-map-resolve/lib/resolve-url.js | 12 + .../lib/source-map-resolve-node.js | 302 + .../source-map-resolve/package.json | 77 + js/node_modules/source-map-resolve/readme.md | 231 + .../source-map-resolve/source-map-resolve.js | 309 + .../source-map-resolve.js.template | 22 + .../source-map-resolve/test/common.js | 27 + .../source-map-resolve/test/read.js | 105 + .../test/source-map-resolve.js | 1162 ++++ .../source-map-resolve/test/windows.js | 166 + .../source-map-resolve/x-package.json5 | 68 + js/node_modules/source-map-url/.jshintrc | 43 + js/node_modules/source-map-url/LICENSE | 21 + js/node_modules/source-map-url/bower.json | 20 + js/node_modules/source-map-url/changelog.md | 52 + js/node_modules/source-map-url/component.json | 18 + js/node_modules/source-map-url/package.json | 73 + js/node_modules/source-map-url/readme.md | 97 + .../source-map-url/source-map-url.js | 57 + .../source-map-url/test/source-map-url.js | 402 ++ .../source-map-url/x-package.json5 | 55 + js/node_modules/source-map/CHANGELOG.md | 301 + js/node_modules/source-map/LICENSE | 28 + js/node_modules/source-map/README.md | 729 +++ .../source-map/dist/source-map.debug.js | 3091 ++++++++++ js/node_modules/source-map/dist/source-map.js | 3090 ++++++++++ .../source-map/dist/source-map.min.js | 2 + .../source-map/dist/source-map.min.js.map | 1 + js/node_modules/source-map/lib/array-set.js | 121 + js/node_modules/source-map/lib/base64-vlq.js | 140 + js/node_modules/source-map/lib/base64.js | 67 + .../source-map/lib/binary-search.js | 111 + .../source-map/lib/mapping-list.js | 79 + js/node_modules/source-map/lib/quick-sort.js | 114 + .../source-map/lib/source-map-consumer.js | 1082 ++++ .../source-map/lib/source-map-generator.js | 416 ++ js/node_modules/source-map/lib/source-node.js | 413 ++ js/node_modules/source-map/lib/util.js | 417 ++ js/node_modules/source-map/package.json | 211 + js/node_modules/source-map/source-map.js | 8 + js/node_modules/split-string/LICENSE | 21 + js/node_modules/split-string/README.md | 321 + js/node_modules/split-string/index.js | 171 + js/node_modules/split-string/package.json | 103 + js/node_modules/static-extend/LICENSE | 21 + js/node_modules/static-extend/index.js | 90 + .../node_modules/define-property/LICENSE | 21 + .../node_modules/define-property/README.md | 77 + .../node_modules/define-property/index.js | 31 + .../node_modules/define-property/package.json | 82 + js/node_modules/static-extend/package.json | 96 + js/node_modules/string_decoder/.travis.yml | 50 + js/node_modules/string_decoder/LICENSE | 48 + js/node_modules/string_decoder/README.md | 47 + .../string_decoder/lib/string_decoder.js | 296 + js/node_modules/string_decoder/package.json | 59 + js/node_modules/to-object-path/LICENSE | 21 + js/node_modules/to-object-path/README.md | 71 + js/node_modules/to-object-path/index.js | 33 + js/node_modules/to-object-path/package.json | 80 + js/node_modules/to-regex-range/LICENSE | 21 + js/node_modules/to-regex-range/README.md | 281 + js/node_modules/to-regex-range/index.js | 294 + .../node_modules/is-number/LICENSE | 21 + .../node_modules/is-number/README.md | 115 + .../node_modules/is-number/index.js | 22 + .../node_modules/is-number/package.json | 121 + js/node_modules/to-regex-range/package.json | 119 + js/node_modules/to-regex/LICENSE | 21 + js/node_modules/to-regex/README.md | 205 + js/node_modules/to-regex/index.js | 155 + js/node_modules/to-regex/package.json | 97 + js/node_modules/union-value/LICENSE | 21 + js/node_modules/union-value/README.md | 73 + js/node_modules/union-value/index.js | 30 + .../node_modules/extend-shallow/LICENSE | 21 + .../node_modules/extend-shallow/README.md | 61 + .../node_modules/extend-shallow/index.js | 33 + .../node_modules/extend-shallow/package.json | 87 + .../node_modules/set-value/LICENSE | 21 + .../node_modules/set-value/README.md | 81 + .../node_modules/set-value/index.js | 63 + .../node_modules/set-value/package.json | 121 + js/node_modules/union-value/package.json | 105 + js/node_modules/unset-value/LICENSE | 21 + js/node_modules/unset-value/README.md | 131 + js/node_modules/unset-value/index.js | 32 + .../node_modules/has-value/LICENSE | 21 + .../node_modules/has-value/README.md | 130 + .../node_modules/has-value/index.js | 19 + .../has-value/node_modules/isobject/LICENSE | 21 + .../has-value/node_modules/isobject/README.md | 112 + .../has-value/node_modules/isobject/index.js | 14 + .../node_modules/isobject/package.json | 98 + .../node_modules/has-value/package.json | 114 + .../node_modules/has-values/LICENSE | 21 + .../node_modules/has-values/README.md | 114 + .../node_modules/has-values/index.js | 36 + .../node_modules/has-values/package.json | 106 + .../unset-value/node_modules/isobject/LICENSE | 21 + .../node_modules/isobject/README.md | 122 + .../node_modules/isobject/index.d.ts | 5 + .../node_modules/isobject/index.js | 12 + .../node_modules/isobject/package.json | 119 + js/node_modules/unset-value/package.json | 112 + js/node_modules/urix/.jshintrc | 42 + js/node_modules/urix/LICENSE | 21 + js/node_modules/urix/index.js | 17 + js/node_modules/urix/package.json | 59 + js/node_modules/urix/readme.md | 46 + js/node_modules/urix/test/index.js | 43 + js/node_modules/use/LICENSE | 21 + js/node_modules/use/README.md | 90 + js/node_modules/use/index.js | 153 + .../use/node_modules/kind-of/CHANGELOG.md | 157 + .../use/node_modules/kind-of/LICENSE | 21 + .../use/node_modules/kind-of/README.md | 365 ++ .../use/node_modules/kind-of/index.js | 129 + .../use/node_modules/kind-of/package.json | 143 + js/node_modules/use/package.json | 111 + js/node_modules/util-deprecate/History.md | 16 + js/node_modules/util-deprecate/LICENSE | 24 + js/node_modules/util-deprecate/README.md | 53 + js/node_modules/util-deprecate/browser.js | 67 + js/node_modules/util-deprecate/node.js | 6 + js/node_modules/util-deprecate/package.json | 56 + js/node_modules/walk-sync/CHANGELOG.md | 64 + js/node_modules/walk-sync/LICENSE | 21 + js/node_modules/walk-sync/README.md | 101 + js/node_modules/walk-sync/index.js | 153 + js/node_modules/walk-sync/package.json | 60 + js/node_modules/which/CHANGELOG.md | 147 + js/node_modules/which/LICENSE | 15 + js/node_modules/which/README.md | 51 + js/node_modules/which/package.json | 65 + js/node_modules/which/which.js | 135 + js/package-lock.json | 2073 +++++++ .../actions/expected/BuiltinFrameworks.kt | 17 + .../main/kotlin/actions/expected/Expected.kt | 8 + .../kotlin/actions/expected/OAuth2Client.kt | 26 + .../kotlin/actions/expected/Serializer.kt | 16 + .../kotlin/actions/expected/deserialize.kt | 5 + js/src/main/kotlin/actions/expected/log.kt | 5 + jvm-app/build.gradle | 20 + .../src/main/kotlin/jvm/ActionsSdkSample.kt | 359 ++ jvm-app/src/main/kotlin/jvm/AogMockFactory.kt | 7 + jvm-app/src/main/kotlin/jvm/AogSample.kt | 84 + .../jvm/DelegationServletInputStream.kt | 60 + .../main/kotlin/jvm/DfSampleTransactions.kt | 297 + .../src/main/kotlin/jvm/DialogflowSample.kt | 392 ++ jvm-app/src/main/kotlin/jvm/JvmApp.kt | 6 + jvm-app/src/main/kotlin/jvm/Requests.kt | 131 + {sdk-gson-servlet => jvm}/build.gradle | 59 +- .../actions/expected/BuiltinFrameworks.kt | 87 + .../main/java/actions/expected/Expected.kt | 10 + .../java/actions/expected/OAuth2Client.kt | 30 + .../main/java/actions/expected/Serializer.kt | 47 + .../java/actions/expected/ServletUtils.java | 93 + .../java/actions/expected/TypeAdapters.kt | 64 +- .../main/java/actions/expected/deserialize.kt | 5 + .../expected/framework/ServletFramework.kt | 2 + .../expected/framework/TestHttpServlet.kt | 438 ++ jvm/src/main/java/actions/expected/log.kt | 10 + sample-gae-jvm/build.gradle | 40 + .../main/java/jvm/DfTransactionsWebhook.kt | 37 + .../src/main/java/jvm/DialogflowWebhook.kt | 34 + .../src/main/java/jvm/SampleWebhook.kt | 34 + .../src/main/webapp/WEB-INF/appengine-web.xml | 17 +- .../main/webapp/WEB-INF/logging.properties | 0 .../src/main/webapp/WEB-INF/web.xml | 59 + sdk-gson-servlet/README.md | 24 - .../java/com/tmsdurham/actions/Actions.kt | 103 - sdk/.gitignore | 1 - sdk/build.gradle | 124 - sdk/build.gradle.kts.bak | 38 - .../java/com/tmsdurham/actions/ActionsApp.kt | 1137 ---- .../com/tmsdurham/actions/AssistantApp.kt | 1389 ----- .../com/tmsdurham/actions/DialogflowApp.kt | 1437 ----- .../tmsdurham/actions/DialogflowRequest.kt | 183 - .../tmsdurham/actions/DialogflowResponse.kt | 9 - .../java/com/tmsdurham/actions/GoogleData.kt | 138 - .../com/tmsdurham/actions/RequestExtractor.kt | 459 -- .../com/tmsdurham/actions/RequestWrapper.kt | 7 - .../com/tmsdurham/actions/ResponseBuilder.kt | 619 -- .../com/tmsdurham/actions/ResponseWrapper.kt | 39 - .../com/tmsdurham/actions/Transactions.kt | 1361 ----- .../actions/actions/ActionRequest.kt | 24 - .../actions/actions/ActionResponse.kt | 27 - .../com/tmsdurham/actions/ActionsSdkTest.kt | 2151 ------- .../com/tmsdurham/actions/DialogflowTest.kt | 2875 --------- .../tmsdurham/actions/ResponseBuilderTest.kt | 781 --- .../com/tmsdurham/actions/TransactionsTest.kt | 1184 ---- settings.gradle | 10 +- uploadArtifacts.sh | 3 +- 1876 files changed, 202728 insertions(+), 15361 deletions(-) delete mode 100644 action-sdk-samples/action.json delete mode 100644 action-sdk-samples/build.gradle delete mode 100644 action-sdk-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt delete mode 100644 action-sdk-samples/src/main/webapp/WEB-INF/appengine-web.xml delete mode 100644 action-sdk-samples/src/main/webapp/WEB-INF/web.xml create mode 100644 common-mock/build.gradle create mode 100644 common-mock/src/main/kotlin/actions/AogMockFactory.kt create mode 100644 common-mock/src/main/kotlin/actions/Requests.kt create mode 100644 common-mock/src/test/kotlin/actions/ActionsSdkTest.kt create mode 100644 common-mock/src/test/resources/conversation_sample_basic_card_request.json create mode 100644 common-mock/src/test/resources/conversation_sample_basic_card_response.json create mode 100644 common-mock/src/test/resources/conversation_sample_welcome_request.json create mode 100644 common-mock/src/test/resources/conversation_sample_welcome_response.json create mode 100644 common-mock/src/test/resources/df_sample_basic_card_response.json create mode 100644 common-mock/src/test/resources/df_sample_browse_carousel_response.json create mode 100644 common-mock/src/test/resources/df_sample_carousel_response.json create mode 100644 common-mock/src/test/resources/df_sample_list_response.json create mode 100644 common-mock/src/test/resources/df_sample_media_response.json create mode 100644 common-mock/src/test/resources/df_sample_suggestions_response.json create mode 100644 common-mock/src/test/resources/df_sample_table_response.json create mode 100644 common-mock/src/test/resources/df_sample_test_response.json create mode 100644 common-mock/src/test/resources/df_sample_welcome_response.json create mode 100644 common-mock/src/test/resources/df_transaction_got_address.json create mode 100644 common-mock/src/test/resources/df_transactions_confirm_transaction.json create mode 100644 common/build.gradle create mode 100644 common/src/main/kotlin/actions/Assistant.kt create mode 100644 common/src/main/kotlin/actions/Common.kt create mode 100644 common/src/main/kotlin/actions/expected/BuiltInFrameworks.kt create mode 100644 common/src/main/kotlin/actions/expected/Expected.kt create mode 100644 common/src/main/kotlin/actions/expected/GoogleAuthLib.kt create mode 100644 common/src/main/kotlin/actions/framework/Framework.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/ActionsSdk.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/CommonExtensions.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/Conv.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/api/V2.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/Conversation.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/Device.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/Input.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/Intent.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/Surface.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/User.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Argument.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Media.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/argument/NoInput.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/Confirmation.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/DateTime.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/DeepLink.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/NewSurface.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/Place.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/RegisterUpdate.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/SignIn.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Carousel.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/List.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Option.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Permission.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Update.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Decision.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/DeliveryAddress.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Requirements.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Browse.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Image.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Linkout.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Media.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Order.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Response.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Rich.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/RichResponseItem.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Simple.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Suggestion.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/Url.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Basic.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Button.kt create mode 100644 common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Table.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/Context.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/Conv.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/Dialogflow.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/DialogflowV1Message.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/Incoming.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/api/V1.kt create mode 100644 common/src/main/kotlin/actions/service/dialogflow/api/V2.kt create mode 100644 common/src/test/kotlin/Test.kt delete mode 100644 dialogflow-samples/.gitignore delete mode 100644 dialogflow-samples/README.md delete mode 100644 dialogflow-samples/Transactions_agent.zip delete mode 100644 dialogflow-samples/build.gradle delete mode 100644 dialogflow-samples/conversation_agent.zip delete mode 100644 dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt delete mode 100644 dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSampleJava.java delete mode 100644 dialogflow-samples/src/main/java/com/tmsdurham/actions/TransactionsSample.kt delete mode 100644 dialogflow-samples/src/main/webapp/WEB-INF/logging.properties delete mode 100644 dialogflow-samples/src/main/webapp/WEB-INF/web.xml delete mode 100644 gradle.properties create mode 100644 js-app/build.gradle create mode 100644 js-app/src/main/kotlin/js/JsApp.kt create mode 100644 js/build.gradle create mode 120000 js/node_modules/.bin/atob create mode 120000 js/node_modules/.bin/qunit create mode 120000 js/node_modules/.bin/which create mode 100644 js/node_modules/anymatch/LICENSE create mode 100644 js/node_modules/anymatch/README.md create mode 100644 js/node_modules/anymatch/index.js create mode 100644 js/node_modules/anymatch/package.json create mode 100755 js/node_modules/arr-diff/LICENSE create mode 100644 js/node_modules/arr-diff/README.md create mode 100644 js/node_modules/arr-diff/index.js create mode 100644 js/node_modules/arr-diff/package.json create mode 100755 js/node_modules/arr-flatten/LICENSE create mode 100755 js/node_modules/arr-flatten/README.md create mode 100644 js/node_modules/arr-flatten/index.js create mode 100644 js/node_modules/arr-flatten/package.json create mode 100644 js/node_modules/arr-union/LICENSE create mode 100644 js/node_modules/arr-union/README.md create mode 100644 js/node_modules/arr-union/index.js create mode 100644 js/node_modules/arr-union/package.json create mode 100755 js/node_modules/array-unique/LICENSE create mode 100755 js/node_modules/array-unique/README.md create mode 100755 js/node_modules/array-unique/index.js create mode 100755 js/node_modules/array-unique/package.json create mode 100644 js/node_modules/assign-symbols/LICENSE create mode 100644 js/node_modules/assign-symbols/README.md create mode 100644 js/node_modules/assign-symbols/index.js create mode 100644 js/node_modules/assign-symbols/package.json create mode 100644 js/node_modules/async-each/.npmignore create mode 100644 js/node_modules/async-each/CHANGELOG.md create mode 100644 js/node_modules/async-each/README.md create mode 100644 js/node_modules/async-each/index.js create mode 100644 js/node_modules/async-each/package.json create mode 100644 js/node_modules/atob/LICENSE create mode 100644 js/node_modules/atob/LICENSE.DOCS create mode 100644 js/node_modules/atob/README.md create mode 100644 js/node_modules/atob/bower.json create mode 100644 js/node_modules/atob/browser-atob.js create mode 100644 js/node_modules/atob/node-atob.js create mode 100644 js/node_modules/atob/package.json create mode 100644 js/node_modules/atob/test.js create mode 100644 js/node_modules/balanced-match/.npmignore create mode 100644 js/node_modules/balanced-match/LICENSE.md create mode 100644 js/node_modules/balanced-match/README.md create mode 100644 js/node_modules/balanced-match/index.js create mode 100644 js/node_modules/balanced-match/package.json create mode 100644 js/node_modules/base/LICENSE create mode 100644 js/node_modules/base/README.md create mode 100644 js/node_modules/base/index.js create mode 100644 js/node_modules/base/node_modules/define-property/LICENSE create mode 100644 js/node_modules/base/node_modules/define-property/README.md create mode 100644 js/node_modules/base/node_modules/define-property/index.js create mode 100644 js/node_modules/base/node_modules/define-property/package.json create mode 100644 js/node_modules/base/node_modules/is-accessor-descriptor/LICENSE create mode 100644 js/node_modules/base/node_modules/is-accessor-descriptor/README.md create mode 100644 js/node_modules/base/node_modules/is-accessor-descriptor/index.js create mode 100644 js/node_modules/base/node_modules/is-accessor-descriptor/package.json create mode 100644 js/node_modules/base/node_modules/is-data-descriptor/LICENSE create mode 100644 js/node_modules/base/node_modules/is-data-descriptor/README.md create mode 100644 js/node_modules/base/node_modules/is-data-descriptor/index.js create mode 100644 js/node_modules/base/node_modules/is-data-descriptor/package.json create mode 100644 js/node_modules/base/node_modules/is-descriptor/LICENSE create mode 100644 js/node_modules/base/node_modules/is-descriptor/README.md create mode 100644 js/node_modules/base/node_modules/is-descriptor/index.js create mode 100644 js/node_modules/base/node_modules/is-descriptor/package.json create mode 100644 js/node_modules/base/node_modules/isobject/LICENSE create mode 100644 js/node_modules/base/node_modules/isobject/README.md create mode 100644 js/node_modules/base/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/base/node_modules/isobject/index.js create mode 100644 js/node_modules/base/node_modules/isobject/package.json create mode 100644 js/node_modules/base/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/base/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/base/node_modules/kind-of/README.md create mode 100644 js/node_modules/base/node_modules/kind-of/index.js create mode 100644 js/node_modules/base/node_modules/kind-of/package.json create mode 100644 js/node_modules/base/package.json create mode 100644 js/node_modules/binary-extensions/binary-extensions.json create mode 100644 js/node_modules/binary-extensions/license create mode 100644 js/node_modules/binary-extensions/package.json create mode 100644 js/node_modules/binary-extensions/readme.md create mode 100644 js/node_modules/brace-expansion/LICENSE create mode 100644 js/node_modules/brace-expansion/README.md create mode 100644 js/node_modules/brace-expansion/index.js create mode 100644 js/node_modules/brace-expansion/package.json create mode 100644 js/node_modules/braces/LICENSE create mode 100644 js/node_modules/braces/README.md create mode 100644 js/node_modules/braces/index.js create mode 100644 js/node_modules/braces/package.json create mode 100644 js/node_modules/cache-base/LICENSE create mode 100644 js/node_modules/cache-base/README.md create mode 100644 js/node_modules/cache-base/index.js create mode 100644 js/node_modules/cache-base/node_modules/isobject/LICENSE create mode 100644 js/node_modules/cache-base/node_modules/isobject/README.md create mode 100644 js/node_modules/cache-base/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/cache-base/node_modules/isobject/index.js create mode 100644 js/node_modules/cache-base/node_modules/isobject/package.json create mode 100644 js/node_modules/cache-base/package.json create mode 100644 js/node_modules/chokidar/CHANGELOG.md create mode 100644 js/node_modules/chokidar/README.md create mode 100644 js/node_modules/chokidar/index.js create mode 100644 js/node_modules/chokidar/lib/fsevents-handler.js create mode 100644 js/node_modules/chokidar/lib/nodefs-handler.js create mode 100644 js/node_modules/chokidar/package.json create mode 100644 js/node_modules/class-utils/LICENSE create mode 100644 js/node_modules/class-utils/README.md create mode 100644 js/node_modules/class-utils/index.js create mode 100644 js/node_modules/class-utils/node_modules/define-property/LICENSE create mode 100644 js/node_modules/class-utils/node_modules/define-property/README.md create mode 100644 js/node_modules/class-utils/node_modules/define-property/index.js create mode 100644 js/node_modules/class-utils/node_modules/define-property/package.json create mode 100644 js/node_modules/class-utils/node_modules/isobject/LICENSE create mode 100644 js/node_modules/class-utils/node_modules/isobject/README.md create mode 100644 js/node_modules/class-utils/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/class-utils/node_modules/isobject/index.js create mode 100644 js/node_modules/class-utils/node_modules/isobject/package.json create mode 100644 js/node_modules/class-utils/package.json create mode 100644 js/node_modules/collection-visit/LICENSE create mode 100644 js/node_modules/collection-visit/README.md create mode 100644 js/node_modules/collection-visit/index.js create mode 100644 js/node_modules/collection-visit/package.json create mode 100644 js/node_modules/commander/CHANGELOG.md create mode 100644 js/node_modules/commander/LICENSE create mode 100644 js/node_modules/commander/Readme.md create mode 100644 js/node_modules/commander/index.js create mode 100644 js/node_modules/commander/package.json create mode 100644 js/node_modules/commander/typings/index.d.ts create mode 100644 js/node_modules/component-emitter/History.md create mode 100644 js/node_modules/component-emitter/LICENSE create mode 100644 js/node_modules/component-emitter/Readme.md create mode 100644 js/node_modules/component-emitter/index.js create mode 100644 js/node_modules/component-emitter/package.json create mode 100644 js/node_modules/concat-map/.travis.yml create mode 100644 js/node_modules/concat-map/LICENSE create mode 100644 js/node_modules/concat-map/README.markdown create mode 100644 js/node_modules/concat-map/example/map.js create mode 100644 js/node_modules/concat-map/index.js create mode 100644 js/node_modules/concat-map/package.json create mode 100644 js/node_modules/concat-map/test/map.js create mode 100644 js/node_modules/copy-descriptor/LICENSE create mode 100644 js/node_modules/copy-descriptor/index.js create mode 100644 js/node_modules/copy-descriptor/package.json create mode 100644 js/node_modules/core-util-is/LICENSE create mode 100644 js/node_modules/core-util-is/README.md create mode 100644 js/node_modules/core-util-is/float.patch create mode 100644 js/node_modules/core-util-is/lib/util.js create mode 100644 js/node_modules/core-util-is/package.json create mode 100644 js/node_modules/core-util-is/test.js create mode 100644 js/node_modules/debug/.coveralls.yml create mode 100644 js/node_modules/debug/.eslintrc create mode 100644 js/node_modules/debug/.npmignore create mode 100644 js/node_modules/debug/.travis.yml create mode 100644 js/node_modules/debug/CHANGELOG.md create mode 100644 js/node_modules/debug/LICENSE create mode 100644 js/node_modules/debug/Makefile create mode 100644 js/node_modules/debug/README.md create mode 100644 js/node_modules/debug/component.json create mode 100644 js/node_modules/debug/karma.conf.js create mode 100644 js/node_modules/debug/node.js create mode 100644 js/node_modules/debug/package.json create mode 100644 js/node_modules/debug/src/browser.js create mode 100644 js/node_modules/debug/src/debug.js create mode 100644 js/node_modules/debug/src/index.js create mode 100644 js/node_modules/debug/src/inspector-log.js create mode 100644 js/node_modules/debug/src/node.js create mode 100644 js/node_modules/decode-uri-component/index.js create mode 100644 js/node_modules/decode-uri-component/license create mode 100644 js/node_modules/decode-uri-component/package.json create mode 100644 js/node_modules/decode-uri-component/readme.md create mode 100644 js/node_modules/define-property/CHANGELOG.md create mode 100644 js/node_modules/define-property/LICENSE create mode 100644 js/node_modules/define-property/README.md create mode 100644 js/node_modules/define-property/index.js create mode 100644 js/node_modules/define-property/node_modules/is-accessor-descriptor/LICENSE create mode 100644 js/node_modules/define-property/node_modules/is-accessor-descriptor/README.md create mode 100644 js/node_modules/define-property/node_modules/is-accessor-descriptor/index.js create mode 100644 js/node_modules/define-property/node_modules/is-accessor-descriptor/package.json create mode 100644 js/node_modules/define-property/node_modules/is-data-descriptor/LICENSE create mode 100644 js/node_modules/define-property/node_modules/is-data-descriptor/README.md create mode 100644 js/node_modules/define-property/node_modules/is-data-descriptor/index.js create mode 100644 js/node_modules/define-property/node_modules/is-data-descriptor/package.json create mode 100644 js/node_modules/define-property/node_modules/is-descriptor/LICENSE create mode 100644 js/node_modules/define-property/node_modules/is-descriptor/README.md create mode 100644 js/node_modules/define-property/node_modules/is-descriptor/index.js create mode 100644 js/node_modules/define-property/node_modules/is-descriptor/package.json create mode 100644 js/node_modules/define-property/node_modules/isobject/LICENSE create mode 100644 js/node_modules/define-property/node_modules/isobject/README.md create mode 100644 js/node_modules/define-property/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/define-property/node_modules/isobject/index.js create mode 100644 js/node_modules/define-property/node_modules/isobject/package.json create mode 100644 js/node_modules/define-property/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/define-property/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/define-property/node_modules/kind-of/README.md create mode 100644 js/node_modules/define-property/node_modules/kind-of/index.js create mode 100644 js/node_modules/define-property/node_modules/kind-of/package.json create mode 100644 js/node_modules/define-property/package.json create mode 100644 js/node_modules/detect-file/LICENSE create mode 100644 js/node_modules/detect-file/README.md create mode 100644 js/node_modules/detect-file/index.js create mode 100644 js/node_modules/detect-file/package.json create mode 100644 js/node_modules/ensure-posix-path/README.md create mode 100644 js/node_modules/ensure-posix-path/index.js create mode 100644 js/node_modules/ensure-posix-path/package.json create mode 100644 js/node_modules/exists-stat/.npmignore create mode 100644 js/node_modules/exists-stat/.travis.yml create mode 100644 js/node_modules/exists-stat/README.md create mode 100644 js/node_modules/exists-stat/index.js create mode 100644 js/node_modules/exists-stat/package.json create mode 100644 js/node_modules/exists-stat/test.js create mode 100644 js/node_modules/expand-brackets/LICENSE create mode 100644 js/node_modules/expand-brackets/README.md create mode 100644 js/node_modules/expand-brackets/index.js create mode 100644 js/node_modules/expand-brackets/package.json create mode 100644 js/node_modules/expand-range/LICENSE create mode 100644 js/node_modules/expand-range/README.md create mode 100644 js/node_modules/expand-range/index.js create mode 100644 js/node_modules/expand-range/package.json create mode 100644 js/node_modules/expand-tilde/LICENSE create mode 100644 js/node_modules/expand-tilde/README.md create mode 100644 js/node_modules/expand-tilde/index.js create mode 100644 js/node_modules/expand-tilde/package.json create mode 100644 js/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/extend-shallow/node_modules/is-extendable/LICENSE create mode 100644 js/node_modules/extend-shallow/node_modules/is-extendable/README.md create mode 100644 js/node_modules/extend-shallow/node_modules/is-extendable/index.d.ts create mode 100644 js/node_modules/extend-shallow/node_modules/is-extendable/index.js create mode 100644 js/node_modules/extend-shallow/node_modules/is-extendable/package.json create mode 100644 js/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/extglob/LICENSE create mode 100644 js/node_modules/extglob/README.md create mode 100644 js/node_modules/extglob/index.js create mode 100644 js/node_modules/extglob/package.json create mode 100644 js/node_modules/filename-regex/LICENSE create mode 100644 js/node_modules/filename-regex/README.md create mode 100644 js/node_modules/filename-regex/index.js create mode 100644 js/node_modules/filename-regex/package.json create mode 100644 js/node_modules/fill-range/LICENSE create mode 100644 js/node_modules/fill-range/README.md create mode 100644 js/node_modules/fill-range/index.js create mode 100644 js/node_modules/fill-range/package.json create mode 100644 js/node_modules/findup-sync/README.md create mode 100644 js/node_modules/findup-sync/index.js create mode 100755 js/node_modules/findup-sync/node_modules/arr-diff/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/arr-diff/README.md create mode 100644 js/node_modules/findup-sync/node_modules/arr-diff/index.js create mode 100644 js/node_modules/findup-sync/node_modules/arr-diff/package.json create mode 100755 js/node_modules/findup-sync/node_modules/array-unique/LICENSE create mode 100755 js/node_modules/findup-sync/node_modules/array-unique/README.md create mode 100644 js/node_modules/findup-sync/node_modules/array-unique/index.js create mode 100644 js/node_modules/findup-sync/node_modules/array-unique/package.json create mode 100644 js/node_modules/findup-sync/node_modules/braces/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/braces/README.md create mode 100644 js/node_modules/findup-sync/node_modules/braces/index.js create mode 100644 js/node_modules/findup-sync/node_modules/braces/lib/braces.js create mode 100644 js/node_modules/findup-sync/node_modules/braces/lib/compilers.js create mode 100644 js/node_modules/findup-sync/node_modules/braces/lib/parsers.js create mode 100644 js/node_modules/findup-sync/node_modules/braces/lib/utils.js create mode 100644 js/node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/findup-sync/node_modules/braces/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/changelog.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/lib/compilers.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/lib/parsers.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/lib/utils.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/define-property/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/define-property/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/define-property/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/define-property/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-accessor-descriptor/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-data-descriptor/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-descriptor/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-descriptor/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-descriptor/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/is-descriptor/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/kind-of/README.md create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/kind-of/index.js create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/node_modules/kind-of/package.json create mode 100644 js/node_modules/findup-sync/node_modules/expand-brackets/package.json create mode 100644 js/node_modules/findup-sync/node_modules/extglob/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/extglob/README.md create mode 100644 js/node_modules/findup-sync/node_modules/extglob/changelog.md create mode 100644 js/node_modules/findup-sync/node_modules/extglob/index.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/lib/compilers.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/lib/extglob.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/lib/parsers.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/lib/utils.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/define-property/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/define-property/README.md create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/define-property/index.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/define-property/package.json create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/findup-sync/node_modules/extglob/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/findup-sync/node_modules/extglob/package.json create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/README.md create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/index.js create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/findup-sync/node_modules/fill-range/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-accessor-descriptor/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-accessor-descriptor/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-accessor-descriptor/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-accessor-descriptor/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-data-descriptor/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-data-descriptor/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-data-descriptor/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-data-descriptor/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-descriptor/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-descriptor/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-descriptor/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-descriptor/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-extglob/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-extglob/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-extglob/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-extglob/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-glob/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-glob/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-glob/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-glob/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-number/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-number/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-number/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-number/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/is-number/node_modules/kind-of/README.md create mode 100644 js/node_modules/findup-sync/node_modules/is-number/node_modules/kind-of/index.js create mode 100644 js/node_modules/findup-sync/node_modules/is-number/node_modules/kind-of/package.json create mode 100644 js/node_modules/findup-sync/node_modules/is-number/package.json create mode 100644 js/node_modules/findup-sync/node_modules/isobject/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/isobject/README.md create mode 100644 js/node_modules/findup-sync/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/findup-sync/node_modules/isobject/index.js create mode 100644 js/node_modules/findup-sync/node_modules/isobject/package.json create mode 100644 js/node_modules/findup-sync/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/findup-sync/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/kind-of/README.md create mode 100644 js/node_modules/findup-sync/node_modules/kind-of/index.js create mode 100644 js/node_modules/findup-sync/node_modules/kind-of/package.json create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/CHANGELOG.md create mode 100755 js/node_modules/findup-sync/node_modules/micromatch/LICENSE create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/README.md create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/index.js create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/lib/cache.js create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/lib/compilers.js create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/lib/parsers.js create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/lib/utils.js create mode 100644 js/node_modules/findup-sync/node_modules/micromatch/package.json create mode 100644 js/node_modules/findup-sync/package.json create mode 100644 js/node_modules/for-in/LICENSE create mode 100644 js/node_modules/for-in/README.md create mode 100644 js/node_modules/for-in/index.js create mode 100644 js/node_modules/for-in/package.json create mode 100644 js/node_modules/for-own/LICENSE create mode 100644 js/node_modules/for-own/README.md create mode 100644 js/node_modules/for-own/index.js create mode 100644 js/node_modules/for-own/package.json create mode 100644 js/node_modules/fragment-cache/LICENSE create mode 100644 js/node_modules/fragment-cache/README.md create mode 100644 js/node_modules/fragment-cache/index.js create mode 100644 js/node_modules/fragment-cache/package.json create mode 100644 js/node_modules/fsevents/.npmignore create mode 100644 js/node_modules/fsevents/.travis.yml create mode 100644 js/node_modules/fsevents/ISSUE_TEMPLATE.md create mode 100644 js/node_modules/fsevents/LICENSE create mode 100644 js/node_modules/fsevents/Readme.md create mode 100644 js/node_modules/fsevents/binding.gyp create mode 100644 js/node_modules/fsevents/fsevents.cc create mode 100644 js/node_modules/fsevents/fsevents.js create mode 100644 js/node_modules/fsevents/install.js create mode 100755 js/node_modules/fsevents/lib/binding/Release/node-v11-darwin-x64/fse.node create mode 100755 js/node_modules/fsevents/lib/binding/Release/node-v46-darwin-x64/fse.node create mode 100755 js/node_modules/fsevents/lib/binding/Release/node-v47-darwin-x64/fse.node create mode 100755 js/node_modules/fsevents/lib/binding/Release/node-v48-darwin-x64/fse.node create mode 100755 js/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node create mode 120000 js/node_modules/fsevents/node_modules/.bin/detect-libc create mode 120000 js/node_modules/fsevents/node_modules/.bin/mkdirp create mode 120000 js/node_modules/fsevents/node_modules/.bin/needle create mode 120000 js/node_modules/fsevents/node_modules/.bin/node-pre-gyp create mode 120000 js/node_modules/fsevents/node_modules/.bin/nopt create mode 120000 js/node_modules/fsevents/node_modules/.bin/rc create mode 120000 js/node_modules/fsevents/node_modules/.bin/rimraf create mode 120000 js/node_modules/fsevents/node_modules/.bin/semver create mode 100644 js/node_modules/fsevents/node_modules/abbrev/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/abbrev/README.md create mode 100644 js/node_modules/fsevents/node_modules/abbrev/abbrev.js create mode 100644 js/node_modules/fsevents/node_modules/abbrev/package.json create mode 100644 js/node_modules/fsevents/node_modules/ansi-regex/index.js create mode 100644 js/node_modules/fsevents/node_modules/ansi-regex/license create mode 100644 js/node_modules/fsevents/node_modules/ansi-regex/package.json create mode 100644 js/node_modules/fsevents/node_modules/ansi-regex/readme.md create mode 100644 js/node_modules/fsevents/node_modules/aproba/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/aproba/README.md create mode 100644 js/node_modules/fsevents/node_modules/aproba/index.js create mode 100644 js/node_modules/fsevents/node_modules/aproba/package.json create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/CHANGES.md create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/README.md create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/index.js create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/package.json create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/tracker-base.js create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/tracker-group.js create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/tracker-stream.js create mode 100644 js/node_modules/fsevents/node_modules/are-we-there-yet/tracker.js create mode 100644 js/node_modules/fsevents/node_modules/balanced-match/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/balanced-match/LICENSE.md create mode 100644 js/node_modules/fsevents/node_modules/balanced-match/README.md create mode 100644 js/node_modules/fsevents/node_modules/balanced-match/index.js create mode 100644 js/node_modules/fsevents/node_modules/balanced-match/package.json create mode 100644 js/node_modules/fsevents/node_modules/brace-expansion/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/brace-expansion/README.md create mode 100644 js/node_modules/fsevents/node_modules/brace-expansion/index.js create mode 100644 js/node_modules/fsevents/node_modules/brace-expansion/package.json create mode 100644 js/node_modules/fsevents/node_modules/chownr/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/chownr/README.md create mode 100644 js/node_modules/fsevents/node_modules/chownr/chownr.js create mode 100644 js/node_modules/fsevents/node_modules/chownr/package.json create mode 100644 js/node_modules/fsevents/node_modules/code-point-at/index.js create mode 100644 js/node_modules/fsevents/node_modules/code-point-at/license create mode 100644 js/node_modules/fsevents/node_modules/code-point-at/package.json create mode 100644 js/node_modules/fsevents/node_modules/code-point-at/readme.md create mode 100644 js/node_modules/fsevents/node_modules/concat-map/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/concat-map/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/concat-map/README.markdown create mode 100644 js/node_modules/fsevents/node_modules/concat-map/example/map.js create mode 100644 js/node_modules/fsevents/node_modules/concat-map/index.js create mode 100644 js/node_modules/fsevents/node_modules/concat-map/package.json create mode 100644 js/node_modules/fsevents/node_modules/concat-map/test/map.js create mode 100644 js/node_modules/fsevents/node_modules/console-control-strings/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/console-control-strings/README.md create mode 100644 js/node_modules/fsevents/node_modules/console-control-strings/index.js create mode 100644 js/node_modules/fsevents/node_modules/console-control-strings/package.json create mode 100644 js/node_modules/fsevents/node_modules/core-util-is/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/core-util-is/README.md create mode 100644 js/node_modules/fsevents/node_modules/core-util-is/float.patch create mode 100644 js/node_modules/fsevents/node_modules/core-util-is/lib/util.js create mode 100644 js/node_modules/fsevents/node_modules/core-util-is/package.json create mode 100644 js/node_modules/fsevents/node_modules/core-util-is/test.js create mode 100644 js/node_modules/fsevents/node_modules/debug/.coveralls.yml create mode 100644 js/node_modules/fsevents/node_modules/debug/.eslintrc create mode 100644 js/node_modules/fsevents/node_modules/debug/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/debug/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/debug/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/debug/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/debug/Makefile create mode 100644 js/node_modules/fsevents/node_modules/debug/README.md create mode 100644 js/node_modules/fsevents/node_modules/debug/component.json create mode 100644 js/node_modules/fsevents/node_modules/debug/karma.conf.js create mode 100644 js/node_modules/fsevents/node_modules/debug/node.js create mode 100644 js/node_modules/fsevents/node_modules/debug/package.json create mode 100644 js/node_modules/fsevents/node_modules/debug/src/browser.js create mode 100644 js/node_modules/fsevents/node_modules/debug/src/debug.js create mode 100644 js/node_modules/fsevents/node_modules/debug/src/index.js create mode 100644 js/node_modules/fsevents/node_modules/debug/src/inspector-log.js create mode 100644 js/node_modules/fsevents/node_modules/debug/src/node.js create mode 100644 js/node_modules/fsevents/node_modules/deep-extend/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/deep-extend/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/deep-extend/README.md create mode 100644 js/node_modules/fsevents/node_modules/deep-extend/index.js create mode 100644 js/node_modules/fsevents/node_modules/deep-extend/lib/deep-extend.js create mode 100644 js/node_modules/fsevents/node_modules/deep-extend/package.json create mode 100644 js/node_modules/fsevents/node_modules/delegates/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/delegates/History.md create mode 100644 js/node_modules/fsevents/node_modules/delegates/License create mode 100644 js/node_modules/fsevents/node_modules/delegates/Makefile create mode 100644 js/node_modules/fsevents/node_modules/delegates/Readme.md create mode 100644 js/node_modules/fsevents/node_modules/delegates/index.js create mode 100644 js/node_modules/fsevents/node_modules/delegates/package.json create mode 100644 js/node_modules/fsevents/node_modules/delegates/test/index.js create mode 100644 js/node_modules/fsevents/node_modules/detect-libc/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/detect-libc/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/detect-libc/README.md create mode 100644 js/node_modules/fsevents/node_modules/detect-libc/lib/detect-libc.js create mode 100644 js/node_modules/fsevents/node_modules/detect-libc/package.json create mode 100644 js/node_modules/fsevents/node_modules/fs-minipass/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/fs-minipass/README.md create mode 100644 js/node_modules/fsevents/node_modules/fs-minipass/index.js create mode 100644 js/node_modules/fsevents/node_modules/fs-minipass/package.json create mode 100644 js/node_modules/fsevents/node_modules/fs.realpath/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/fs.realpath/README.md create mode 100644 js/node_modules/fsevents/node_modules/fs.realpath/index.js create mode 100644 js/node_modules/fsevents/node_modules/fs.realpath/old.js create mode 100644 js/node_modules/fsevents/node_modules/fs.realpath/package.json create mode 100644 js/node_modules/fsevents/node_modules/gauge/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/gauge/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/gauge/README.md create mode 100644 js/node_modules/fsevents/node_modules/gauge/base-theme.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/error.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/has-color.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/index.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/package.json create mode 100644 js/node_modules/fsevents/node_modules/gauge/plumbing.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/process.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/progress-bar.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/render-template.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/set-immediate.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/set-interval.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/spin.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/template-item.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/theme-set.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/themes.js create mode 100644 js/node_modules/fsevents/node_modules/gauge/wide-truncate.js create mode 100644 js/node_modules/fsevents/node_modules/glob/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/glob/README.md create mode 100644 js/node_modules/fsevents/node_modules/glob/changelog.md create mode 100644 js/node_modules/fsevents/node_modules/glob/common.js create mode 100644 js/node_modules/fsevents/node_modules/glob/glob.js create mode 100644 js/node_modules/fsevents/node_modules/glob/package.json create mode 100644 js/node_modules/fsevents/node_modules/glob/sync.js create mode 100644 js/node_modules/fsevents/node_modules/has-unicode/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/has-unicode/README.md create mode 100644 js/node_modules/fsevents/node_modules/has-unicode/index.js create mode 100644 js/node_modules/fsevents/node_modules/has-unicode/package.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/Changelog.md create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/README.md create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/dbcs-codec.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/dbcs-data.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/index.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/internal.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/sbcs-codec.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/sbcs-data-generated.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/sbcs-data.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/big5-added.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/cp936.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/cp949.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/cp950.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/eucjp.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/gbk-added.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/tables/shiftjis.json create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/utf16.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/encodings/utf7.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/lib/bom-handling.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/lib/extend-node.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/lib/index.d.ts create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/lib/index.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/lib/streams.js create mode 100644 js/node_modules/fsevents/node_modules/iconv-lite/package.json create mode 100644 js/node_modules/fsevents/node_modules/ignore-walk/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/ignore-walk/README.md create mode 100644 js/node_modules/fsevents/node_modules/ignore-walk/index.js create mode 100644 js/node_modules/fsevents/node_modules/ignore-walk/package.json create mode 100644 js/node_modules/fsevents/node_modules/inflight/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/inflight/README.md create mode 100644 js/node_modules/fsevents/node_modules/inflight/inflight.js create mode 100644 js/node_modules/fsevents/node_modules/inflight/package.json create mode 100644 js/node_modules/fsevents/node_modules/inherits/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/inherits/README.md create mode 100644 js/node_modules/fsevents/node_modules/inherits/inherits.js create mode 100644 js/node_modules/fsevents/node_modules/inherits/inherits_browser.js create mode 100644 js/node_modules/fsevents/node_modules/inherits/package.json create mode 100644 js/node_modules/fsevents/node_modules/ini/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/ini/README.md create mode 100644 js/node_modules/fsevents/node_modules/ini/ini.js create mode 100644 js/node_modules/fsevents/node_modules/ini/package.json create mode 100644 js/node_modules/fsevents/node_modules/is-fullwidth-code-point/index.js create mode 100644 js/node_modules/fsevents/node_modules/is-fullwidth-code-point/license create mode 100644 js/node_modules/fsevents/node_modules/is-fullwidth-code-point/package.json create mode 100644 js/node_modules/fsevents/node_modules/is-fullwidth-code-point/readme.md create mode 100644 js/node_modules/fsevents/node_modules/isarray/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/isarray/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/isarray/Makefile create mode 100644 js/node_modules/fsevents/node_modules/isarray/README.md create mode 100644 js/node_modules/fsevents/node_modules/isarray/component.json create mode 100644 js/node_modules/fsevents/node_modules/isarray/index.js create mode 100644 js/node_modules/fsevents/node_modules/isarray/package.json create mode 100644 js/node_modules/fsevents/node_modules/isarray/test.js create mode 100644 js/node_modules/fsevents/node_modules/minimatch/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/minimatch/README.md create mode 100644 js/node_modules/fsevents/node_modules/minimatch/minimatch.js create mode 100644 js/node_modules/fsevents/node_modules/minimatch/package.json create mode 100644 js/node_modules/fsevents/node_modules/minimist/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/minimist/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/minimist/example/parse.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/index.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/package.json create mode 100644 js/node_modules/fsevents/node_modules/minimist/readme.markdown create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/dash.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/default_bool.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/dotted.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/long.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/parse.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/parse_modified.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/short.js create mode 100644 js/node_modules/fsevents/node_modules/minimist/test/whitespace.js create mode 100644 js/node_modules/fsevents/node_modules/minipass/README.md create mode 100644 js/node_modules/fsevents/node_modules/minipass/index.js create mode 100644 js/node_modules/fsevents/node_modules/minipass/package.json create mode 100644 js/node_modules/fsevents/node_modules/minizlib/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/minizlib/README.md create mode 100644 js/node_modules/fsevents/node_modules/minizlib/constants.js create mode 100644 js/node_modules/fsevents/node_modules/minizlib/index.js create mode 100644 js/node_modules/fsevents/node_modules/minizlib/package.json create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/examples/pow.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/index.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/package.json create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/readme.markdown create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/chmod.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/clobber.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/mkdirp.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/opts_fs.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/opts_fs_sync.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/perm.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/perm_sync.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/race.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/rel.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/return.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/return_sync.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/root.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/sync.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/umask.js create mode 100644 js/node_modules/fsevents/node_modules/mkdirp/test/umask_sync.js create mode 100644 js/node_modules/fsevents/node_modules/ms/index.js create mode 100644 js/node_modules/fsevents/node_modules/ms/license.md create mode 100644 js/node_modules/fsevents/node_modules/ms/package.json create mode 100644 js/node_modules/fsevents/node_modules/ms/readme.md create mode 100644 js/node_modules/fsevents/node_modules/needle/README.md create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/deflated-stream.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/digest-auth.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/download-to-file.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/multipart-stream.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/parsed-stream.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/parsed-stream2.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/stream-events.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/stream-to-file.js create mode 100644 js/node_modules/fsevents/node_modules/needle/examples/upload-image.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/auth.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/cookies.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/decoder.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/multipart.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/needle.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/parsers.js create mode 100644 js/node_modules/fsevents/node_modules/needle/lib/querystring.js create mode 100644 js/node_modules/fsevents/node_modules/needle/license.txt create mode 100644 js/node_modules/fsevents/node_modules/needle/package.json create mode 100644 js/node_modules/fsevents/node_modules/needle/test/basic_auth_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/compression_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/cookies_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/decoder_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/errors_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/headers_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/helpers.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/long_string_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/output_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/parsing_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/post_data_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/proxy_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/querystring_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/redirect_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/redirect_with_timeout.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/request_stream_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/response_stream_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/socket_pool_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/url_spec.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/utils/formidable.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/utils/proxy.js create mode 100644 js/node_modules/fsevents/node_modules/needle/test/utils/test.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/README.md create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/appveyor.yml create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/contributing.md create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/build.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/clean.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/configure.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/info.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/install.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/node-pre-gyp.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/package.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/pre-binding.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/publish.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/rebuild.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/reinstall.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/reveal.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/testbinary.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/testpackage.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/unpublish.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/abi_crosswalk.json create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/compile.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/handle_gyp_opts.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/napi.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/s3_setup.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/versioning.js create mode 100644 js/node_modules/fsevents/node_modules/node-pre-gyp/package.json create mode 100644 js/node_modules/fsevents/node_modules/nopt/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/nopt/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/nopt/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/nopt/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/nopt/README.md create mode 100755 js/node_modules/fsevents/node_modules/nopt/examples/my-program.js create mode 100644 js/node_modules/fsevents/node_modules/nopt/lib/nopt.js create mode 100644 js/node_modules/fsevents/node_modules/nopt/package.json create mode 100644 js/node_modules/fsevents/node_modules/nopt/test/basic.js create mode 100644 js/node_modules/fsevents/node_modules/npm-bundled/README.md create mode 100644 js/node_modules/fsevents/node_modules/npm-bundled/index.js create mode 100644 js/node_modules/fsevents/node_modules/npm-bundled/package.json create mode 100644 js/node_modules/fsevents/node_modules/npm-packlist/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/npm-packlist/README.md create mode 100644 js/node_modules/fsevents/node_modules/npm-packlist/index.js create mode 100644 js/node_modules/fsevents/node_modules/npm-packlist/package.json create mode 100644 js/node_modules/fsevents/node_modules/npmlog/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/npmlog/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/npmlog/README.md create mode 100644 js/node_modules/fsevents/node_modules/npmlog/log.js create mode 100644 js/node_modules/fsevents/node_modules/npmlog/package.json create mode 100644 js/node_modules/fsevents/node_modules/number-is-nan/index.js create mode 100644 js/node_modules/fsevents/node_modules/number-is-nan/license create mode 100644 js/node_modules/fsevents/node_modules/number-is-nan/package.json create mode 100644 js/node_modules/fsevents/node_modules/number-is-nan/readme.md create mode 100644 js/node_modules/fsevents/node_modules/object-assign/index.js create mode 100644 js/node_modules/fsevents/node_modules/object-assign/license create mode 100644 js/node_modules/fsevents/node_modules/object-assign/package.json create mode 100644 js/node_modules/fsevents/node_modules/object-assign/readme.md create mode 100644 js/node_modules/fsevents/node_modules/once/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/once/README.md create mode 100644 js/node_modules/fsevents/node_modules/once/once.js create mode 100644 js/node_modules/fsevents/node_modules/once/package.json create mode 100644 js/node_modules/fsevents/node_modules/os-homedir/index.js create mode 100644 js/node_modules/fsevents/node_modules/os-homedir/license create mode 100644 js/node_modules/fsevents/node_modules/os-homedir/package.json create mode 100644 js/node_modules/fsevents/node_modules/os-homedir/readme.md create mode 100644 js/node_modules/fsevents/node_modules/os-tmpdir/index.js create mode 100644 js/node_modules/fsevents/node_modules/os-tmpdir/license create mode 100644 js/node_modules/fsevents/node_modules/os-tmpdir/package.json create mode 100644 js/node_modules/fsevents/node_modules/os-tmpdir/readme.md create mode 100644 js/node_modules/fsevents/node_modules/osenv/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/osenv/README.md create mode 100644 js/node_modules/fsevents/node_modules/osenv/osenv.js create mode 100644 js/node_modules/fsevents/node_modules/osenv/package.json create mode 100644 js/node_modules/fsevents/node_modules/path-is-absolute/index.js create mode 100644 js/node_modules/fsevents/node_modules/path-is-absolute/license create mode 100644 js/node_modules/fsevents/node_modules/path-is-absolute/package.json create mode 100644 js/node_modules/fsevents/node_modules/path-is-absolute/readme.md create mode 100644 js/node_modules/fsevents/node_modules/process-nextick-args/index.js create mode 100644 js/node_modules/fsevents/node_modules/process-nextick-args/license.md create mode 100644 js/node_modules/fsevents/node_modules/process-nextick-args/package.json create mode 100644 js/node_modules/fsevents/node_modules/process-nextick-args/readme.md create mode 100644 js/node_modules/fsevents/node_modules/rc/.npmignore create mode 100644 js/node_modules/fsevents/node_modules/rc/LICENSE.APACHE2 create mode 100644 js/node_modules/fsevents/node_modules/rc/LICENSE.BSD create mode 100644 js/node_modules/fsevents/node_modules/rc/LICENSE.MIT create mode 100644 js/node_modules/fsevents/node_modules/rc/README.md create mode 100644 js/node_modules/fsevents/node_modules/rc/browser.js create mode 100755 js/node_modules/fsevents/node_modules/rc/cli.js create mode 100755 js/node_modules/fsevents/node_modules/rc/index.js create mode 100644 js/node_modules/fsevents/node_modules/rc/lib/utils.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/example/parse.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/index.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/package.json create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/readme.markdown create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/all_bool.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/bool.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dash.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/default_bool.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dotted.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/kv_short.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/long.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/num.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse_modified.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/short.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/stop_early.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/unknown.js create mode 100644 js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/whitespace.js create mode 100644 js/node_modules/fsevents/node_modules/rc/package.json create mode 100644 js/node_modules/fsevents/node_modules/rc/test/ini.js create mode 100644 js/node_modules/fsevents/node_modules/rc/test/nested-env-vars.js create mode 100644 js/node_modules/fsevents/node_modules/rc/test/test.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/CONTRIBUTING.md create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/GOVERNANCE.md create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/README.md create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/duplex-browser.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/duplex.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_duplex.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_passthrough.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_readable.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_transform.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_writable.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/BufferList.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/destroy.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream-browser.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/package.json create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/passthrough.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/readable-browser.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/readable.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/transform.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/writable-browser.js create mode 100644 js/node_modules/fsevents/node_modules/readable-stream/writable.js create mode 100644 js/node_modules/fsevents/node_modules/rimraf/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/rimraf/README.md create mode 100755 js/node_modules/fsevents/node_modules/rimraf/bin.js create mode 100644 js/node_modules/fsevents/node_modules/rimraf/package.json create mode 100644 js/node_modules/fsevents/node_modules/rimraf/rimraf.js create mode 100644 js/node_modules/fsevents/node_modules/safe-buffer/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/safe-buffer/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/safe-buffer/README.md create mode 100644 js/node_modules/fsevents/node_modules/safe-buffer/index.js create mode 100644 js/node_modules/fsevents/node_modules/safe-buffer/package.json create mode 100644 js/node_modules/fsevents/node_modules/safe-buffer/test.js create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/Porting-Buffer.md create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/Readme.md create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/dangerous.js create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/package.json create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/safer.js create mode 100644 js/node_modules/fsevents/node_modules/safer-buffer/tests.js create mode 100644 js/node_modules/fsevents/node_modules/sax/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/sax/README.md create mode 100644 js/node_modules/fsevents/node_modules/sax/lib/sax.js create mode 100644 js/node_modules/fsevents/node_modules/sax/package.json create mode 100644 js/node_modules/fsevents/node_modules/semver/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/semver/README.md create mode 100644 js/node_modules/fsevents/node_modules/semver/package.json create mode 100644 js/node_modules/fsevents/node_modules/semver/range.bnf create mode 100644 js/node_modules/fsevents/node_modules/semver/semver.js create mode 100644 js/node_modules/fsevents/node_modules/set-blocking/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/set-blocking/LICENSE.txt create mode 100644 js/node_modules/fsevents/node_modules/set-blocking/README.md create mode 100644 js/node_modules/fsevents/node_modules/set-blocking/index.js create mode 100644 js/node_modules/fsevents/node_modules/set-blocking/package.json create mode 100644 js/node_modules/fsevents/node_modules/signal-exit/CHANGELOG.md create mode 100644 js/node_modules/fsevents/node_modules/signal-exit/LICENSE.txt create mode 100644 js/node_modules/fsevents/node_modules/signal-exit/README.md create mode 100644 js/node_modules/fsevents/node_modules/signal-exit/index.js create mode 100644 js/node_modules/fsevents/node_modules/signal-exit/package.json create mode 100644 js/node_modules/fsevents/node_modules/signal-exit/signals.js create mode 100644 js/node_modules/fsevents/node_modules/string-width/index.js create mode 100644 js/node_modules/fsevents/node_modules/string-width/license create mode 100644 js/node_modules/fsevents/node_modules/string-width/package.json create mode 100644 js/node_modules/fsevents/node_modules/string-width/readme.md create mode 100644 js/node_modules/fsevents/node_modules/string_decoder/.travis.yml create mode 100644 js/node_modules/fsevents/node_modules/string_decoder/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/string_decoder/README.md create mode 100644 js/node_modules/fsevents/node_modules/string_decoder/lib/string_decoder.js create mode 100644 js/node_modules/fsevents/node_modules/string_decoder/package.json create mode 100644 js/node_modules/fsevents/node_modules/strip-ansi/index.js create mode 100644 js/node_modules/fsevents/node_modules/strip-ansi/license create mode 100644 js/node_modules/fsevents/node_modules/strip-ansi/package.json create mode 100644 js/node_modules/fsevents/node_modules/strip-ansi/readme.md create mode 100644 js/node_modules/fsevents/node_modules/strip-json-comments/index.js create mode 100644 js/node_modules/fsevents/node_modules/strip-json-comments/license create mode 100644 js/node_modules/fsevents/node_modules/strip-json-comments/package.json create mode 100644 js/node_modules/fsevents/node_modules/strip-json-comments/readme.md create mode 100644 js/node_modules/fsevents/node_modules/tar/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/tar/README.md create mode 100644 js/node_modules/fsevents/node_modules/tar/index.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/buffer.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/create.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/extract.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/header.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/high-level-opt.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/large-numbers.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/list.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/mkdir.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/pack.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/parse.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/pax.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/read-entry.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/replace.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/types.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/unpack.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/update.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/warn-mixin.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/winchars.js create mode 100644 js/node_modules/fsevents/node_modules/tar/lib/write-entry.js create mode 100644 js/node_modules/fsevents/node_modules/tar/package.json create mode 100644 js/node_modules/fsevents/node_modules/util-deprecate/History.md create mode 100644 js/node_modules/fsevents/node_modules/util-deprecate/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/util-deprecate/README.md create mode 100644 js/node_modules/fsevents/node_modules/util-deprecate/browser.js create mode 100644 js/node_modules/fsevents/node_modules/util-deprecate/node.js create mode 100644 js/node_modules/fsevents/node_modules/util-deprecate/package.json create mode 100644 js/node_modules/fsevents/node_modules/wide-align/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/wide-align/README.md create mode 100644 js/node_modules/fsevents/node_modules/wide-align/align.js create mode 100644 js/node_modules/fsevents/node_modules/wide-align/package.json create mode 100644 js/node_modules/fsevents/node_modules/wrappy/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/wrappy/README.md create mode 100644 js/node_modules/fsevents/node_modules/wrappy/package.json create mode 100644 js/node_modules/fsevents/node_modules/wrappy/wrappy.js create mode 100644 js/node_modules/fsevents/node_modules/yallist/LICENSE create mode 100644 js/node_modules/fsevents/node_modules/yallist/README.md create mode 100644 js/node_modules/fsevents/node_modules/yallist/iterator.js create mode 100644 js/node_modules/fsevents/node_modules/yallist/package.json create mode 100644 js/node_modules/fsevents/node_modules/yallist/yallist.js create mode 100644 js/node_modules/fsevents/package.json create mode 100644 js/node_modules/fsevents/src/async.cc create mode 100644 js/node_modules/fsevents/src/constants.cc create mode 100644 js/node_modules/fsevents/src/locking.cc create mode 100644 js/node_modules/fsevents/src/methods.cc create mode 100644 js/node_modules/fsevents/src/storage.cc create mode 100644 js/node_modules/fsevents/src/thread.cc create mode 100644 js/node_modules/get-value/LICENSE create mode 100644 js/node_modules/get-value/index.js create mode 100644 js/node_modules/get-value/package.json create mode 100644 js/node_modules/glob-base/LICENSE create mode 100644 js/node_modules/glob-base/README.md create mode 100644 js/node_modules/glob-base/index.js create mode 100644 js/node_modules/glob-base/package.json create mode 100644 js/node_modules/glob-parent/.npmignore create mode 100644 js/node_modules/glob-parent/.travis.yml create mode 100644 js/node_modules/glob-parent/LICENSE create mode 100644 js/node_modules/glob-parent/README.md create mode 100644 js/node_modules/glob-parent/index.js create mode 100644 js/node_modules/glob-parent/package.json create mode 100644 js/node_modules/glob-parent/test.js create mode 100644 js/node_modules/global-modules/LICENSE create mode 100644 js/node_modules/global-modules/README.md create mode 100644 js/node_modules/global-modules/index.js create mode 100644 js/node_modules/global-modules/package.json create mode 100644 js/node_modules/global-prefix/LICENSE create mode 100644 js/node_modules/global-prefix/README.md create mode 100644 js/node_modules/global-prefix/index.js create mode 100644 js/node_modules/global-prefix/package.json create mode 100644 js/node_modules/graceful-fs/LICENSE create mode 100644 js/node_modules/graceful-fs/README.md create mode 100644 js/node_modules/graceful-fs/fs.js create mode 100644 js/node_modules/graceful-fs/graceful-fs.js create mode 100644 js/node_modules/graceful-fs/legacy-streams.js create mode 100644 js/node_modules/graceful-fs/package.json create mode 100644 js/node_modules/graceful-fs/polyfills.js create mode 100644 js/node_modules/has-value/LICENSE create mode 100644 js/node_modules/has-value/README.md create mode 100644 js/node_modules/has-value/index.js create mode 100644 js/node_modules/has-value/node_modules/isobject/LICENSE create mode 100644 js/node_modules/has-value/node_modules/isobject/README.md create mode 100644 js/node_modules/has-value/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/has-value/node_modules/isobject/index.js create mode 100644 js/node_modules/has-value/node_modules/isobject/package.json create mode 100644 js/node_modules/has-value/package.json create mode 100644 js/node_modules/has-values/LICENSE create mode 100644 js/node_modules/has-values/README.md create mode 100644 js/node_modules/has-values/index.js create mode 100644 js/node_modules/has-values/node_modules/is-number/LICENSE create mode 100644 js/node_modules/has-values/node_modules/is-number/README.md create mode 100644 js/node_modules/has-values/node_modules/is-number/index.js create mode 100644 js/node_modules/has-values/node_modules/is-number/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/has-values/node_modules/is-number/node_modules/kind-of/README.md create mode 100644 js/node_modules/has-values/node_modules/is-number/node_modules/kind-of/index.js create mode 100644 js/node_modules/has-values/node_modules/is-number/node_modules/kind-of/package.json create mode 100644 js/node_modules/has-values/node_modules/is-number/package.json create mode 100644 js/node_modules/has-values/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/has-values/node_modules/kind-of/README.md create mode 100644 js/node_modules/has-values/node_modules/kind-of/index.js create mode 100644 js/node_modules/has-values/node_modules/kind-of/package.json create mode 100644 js/node_modules/has-values/package.json create mode 100644 js/node_modules/homedir-polyfill/LICENSE create mode 100644 js/node_modules/homedir-polyfill/README.md create mode 100644 js/node_modules/homedir-polyfill/index.js create mode 100644 js/node_modules/homedir-polyfill/package.json create mode 100644 js/node_modules/inherits/LICENSE create mode 100644 js/node_modules/inherits/README.md create mode 100644 js/node_modules/inherits/inherits.js create mode 100644 js/node_modules/inherits/inherits_browser.js create mode 100644 js/node_modules/inherits/package.json create mode 100644 js/node_modules/ini/LICENSE create mode 100644 js/node_modules/ini/README.md create mode 100644 js/node_modules/ini/ini.js create mode 100644 js/node_modules/ini/package.json create mode 100644 js/node_modules/is-accessor-descriptor/LICENSE create mode 100644 js/node_modules/is-accessor-descriptor/README.md create mode 100644 js/node_modules/is-accessor-descriptor/index.js create mode 100644 js/node_modules/is-accessor-descriptor/package.json create mode 100644 js/node_modules/is-binary-path/index.js create mode 100644 js/node_modules/is-binary-path/license create mode 100644 js/node_modules/is-binary-path/package.json create mode 100644 js/node_modules/is-binary-path/readme.md create mode 100644 js/node_modules/is-buffer/LICENSE create mode 100644 js/node_modules/is-buffer/README.md create mode 100644 js/node_modules/is-buffer/index.js create mode 100644 js/node_modules/is-buffer/package.json create mode 100644 js/node_modules/is-buffer/test/basic.js create mode 100644 js/node_modules/is-data-descriptor/LICENSE create mode 100644 js/node_modules/is-data-descriptor/README.md create mode 100644 js/node_modules/is-data-descriptor/index.js create mode 100644 js/node_modules/is-data-descriptor/package.json create mode 100644 js/node_modules/is-descriptor/LICENSE create mode 100644 js/node_modules/is-descriptor/README.md create mode 100644 js/node_modules/is-descriptor/index.js create mode 100644 js/node_modules/is-descriptor/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/is-descriptor/node_modules/kind-of/README.md create mode 100644 js/node_modules/is-descriptor/node_modules/kind-of/index.js create mode 100644 js/node_modules/is-descriptor/node_modules/kind-of/package.json create mode 100644 js/node_modules/is-descriptor/package.json create mode 100644 js/node_modules/is-dotfile/LICENSE create mode 100644 js/node_modules/is-dotfile/README.md create mode 100644 js/node_modules/is-dotfile/index.js create mode 100644 js/node_modules/is-dotfile/package.json create mode 100644 js/node_modules/is-equal-shallow/LICENSE create mode 100644 js/node_modules/is-equal-shallow/README.md create mode 100644 js/node_modules/is-equal-shallow/index.js create mode 100644 js/node_modules/is-equal-shallow/package.json create mode 100644 js/node_modules/is-extendable/LICENSE create mode 100644 js/node_modules/is-extendable/README.md create mode 100644 js/node_modules/is-extendable/index.js create mode 100644 js/node_modules/is-extendable/package.json create mode 100644 js/node_modules/is-extglob/LICENSE create mode 100644 js/node_modules/is-extglob/README.md create mode 100644 js/node_modules/is-extglob/index.js create mode 100644 js/node_modules/is-extglob/package.json create mode 100644 js/node_modules/is-glob/LICENSE create mode 100644 js/node_modules/is-glob/README.md create mode 100644 js/node_modules/is-glob/index.js create mode 100644 js/node_modules/is-glob/package.json create mode 100644 js/node_modules/is-number/LICENSE create mode 100644 js/node_modules/is-number/README.md create mode 100644 js/node_modules/is-number/index.js create mode 100644 js/node_modules/is-number/package.json create mode 100644 js/node_modules/is-odd/LICENSE create mode 100644 js/node_modules/is-odd/README.md create mode 100644 js/node_modules/is-odd/index.js create mode 100644 js/node_modules/is-odd/node_modules/is-number/LICENSE create mode 100644 js/node_modules/is-odd/node_modules/is-number/README.md create mode 100644 js/node_modules/is-odd/node_modules/is-number/index.js create mode 100644 js/node_modules/is-odd/node_modules/is-number/package.json create mode 100644 js/node_modules/is-odd/package.json create mode 100644 js/node_modules/is-plain-object/LICENSE create mode 100644 js/node_modules/is-plain-object/README.md create mode 100644 js/node_modules/is-plain-object/index.d.ts create mode 100644 js/node_modules/is-plain-object/index.js create mode 100644 js/node_modules/is-plain-object/node_modules/isobject/LICENSE create mode 100644 js/node_modules/is-plain-object/node_modules/isobject/README.md create mode 100644 js/node_modules/is-plain-object/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/is-plain-object/node_modules/isobject/index.js create mode 100644 js/node_modules/is-plain-object/node_modules/isobject/package.json create mode 100644 js/node_modules/is-plain-object/package.json create mode 100644 js/node_modules/is-posix-bracket/LICENSE create mode 100644 js/node_modules/is-posix-bracket/README.md create mode 100644 js/node_modules/is-posix-bracket/index.js create mode 100644 js/node_modules/is-posix-bracket/package.json create mode 100644 js/node_modules/is-primitive/LICENSE create mode 100644 js/node_modules/is-primitive/README.md create mode 100644 js/node_modules/is-primitive/index.js create mode 100644 js/node_modules/is-primitive/package.json create mode 100644 js/node_modules/is-windows/LICENSE create mode 100644 js/node_modules/is-windows/README.md create mode 100644 js/node_modules/is-windows/index.js create mode 100644 js/node_modules/is-windows/package.json create mode 100644 js/node_modules/isarray/.npmignore create mode 100644 js/node_modules/isarray/.travis.yml create mode 100644 js/node_modules/isarray/Makefile create mode 100644 js/node_modules/isarray/README.md create mode 100644 js/node_modules/isarray/component.json create mode 100644 js/node_modules/isarray/index.js create mode 100644 js/node_modules/isarray/package.json create mode 100644 js/node_modules/isarray/test.js create mode 100644 js/node_modules/isexe/.npmignore create mode 100644 js/node_modules/isexe/LICENSE create mode 100644 js/node_modules/isexe/README.md create mode 100644 js/node_modules/isexe/index.js create mode 100644 js/node_modules/isexe/mode.js create mode 100644 js/node_modules/isexe/package.json create mode 100644 js/node_modules/isexe/test/basic.js create mode 100644 js/node_modules/isexe/windows.js create mode 100644 js/node_modules/isobject/LICENSE create mode 100644 js/node_modules/isobject/README.md create mode 100644 js/node_modules/isobject/index.js create mode 100644 js/node_modules/isobject/package.json create mode 100644 js/node_modules/js-reporters/.babelrc create mode 100644 js/node_modules/js-reporters/CHANGELOG.md create mode 100644 js/node_modules/js-reporters/LICENSE create mode 100644 js/node_modules/js-reporters/README.md create mode 100644 js/node_modules/js-reporters/RELEASE.md create mode 100644 js/node_modules/js-reporters/dist/js-reporters.js create mode 100644 js/node_modules/js-reporters/docs/example.md create mode 100644 js/node_modules/js-reporters/docs/frameworks.md create mode 100644 js/node_modules/js-reporters/img/situation-expected.png create mode 100644 js/node_modules/js-reporters/img/situation-now.png create mode 100644 js/node_modules/js-reporters/index.js create mode 100644 js/node_modules/js-reporters/karma.conf.js create mode 100644 js/node_modules/js-reporters/lib/Data.js create mode 100644 js/node_modules/js-reporters/lib/adapters/JasmineAdapter.js create mode 100644 js/node_modules/js-reporters/lib/adapters/MochaAdapter.js create mode 100644 js/node_modules/js-reporters/lib/adapters/QUnitAdapter.js create mode 100644 js/node_modules/js-reporters/lib/helpers.js create mode 100644 js/node_modules/js-reporters/lib/reporters/ConsoleReporter.js create mode 100644 js/node_modules/js-reporters/lib/reporters/TapReporter.js create mode 100644 js/node_modules/js-reporters/license-header create mode 100644 js/node_modules/js-reporters/package.json create mode 100644 js/node_modules/js-reporters/rollup.config.js create mode 100644 js/node_modules/js-reporters/test/fixtures/jasmine.js create mode 100644 js/node_modules/js-reporters/test/fixtures/mocha.js create mode 100644 js/node_modules/js-reporters/test/fixtures/qunit.js create mode 100644 js/node_modules/js-reporters/test/integration/adapters-run.js create mode 100644 js/node_modules/js-reporters/test/integration/adapters.js create mode 100644 js/node_modules/js-reporters/test/integration/reference-data.js create mode 100644 js/node_modules/js-reporters/test/unit/data.js create mode 100644 js/node_modules/js-reporters/test/unit/helpers.js create mode 100644 js/node_modules/js-reporters/test/unit/tap-reporter.js create mode 100644 js/node_modules/js-reporters/test/versions/failing-versions.js create mode 100644 js/node_modules/js-reporters/test/versions/versions-reporting.js create mode 100644 js/node_modules/js-reporters/test/versions/versions.js create mode 100644 js/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/kind-of/README.md create mode 100644 js/node_modules/kind-of/index.js create mode 100644 js/node_modules/kind-of/package.json create mode 100644 js/node_modules/map-cache/LICENSE create mode 100644 js/node_modules/map-cache/README.md create mode 100644 js/node_modules/map-cache/index.js create mode 100644 js/node_modules/map-cache/package.json create mode 100644 js/node_modules/map-visit/LICENSE create mode 100644 js/node_modules/map-visit/README.md create mode 100644 js/node_modules/map-visit/index.js create mode 100644 js/node_modules/map-visit/package.json create mode 100644 js/node_modules/matcher-collection/README.md create mode 100644 js/node_modules/matcher-collection/index.js create mode 100644 js/node_modules/matcher-collection/package.json create mode 100644 js/node_modules/math-random/.npmignore create mode 100644 js/node_modules/math-random/.travis.yml create mode 100644 js/node_modules/math-random/browser.js create mode 100644 js/node_modules/math-random/node.js create mode 100644 js/node_modules/math-random/package.json create mode 100644 js/node_modules/math-random/readme.md create mode 100644 js/node_modules/math-random/test.js create mode 100755 js/node_modules/micromatch/LICENSE create mode 100644 js/node_modules/micromatch/README.md create mode 100755 js/node_modules/micromatch/index.js create mode 100644 js/node_modules/micromatch/lib/chars.js create mode 100644 js/node_modules/micromatch/lib/expand.js create mode 100644 js/node_modules/micromatch/lib/glob.js create mode 100644 js/node_modules/micromatch/lib/utils.js create mode 100644 js/node_modules/micromatch/package.json create mode 100644 js/node_modules/minimatch/LICENSE create mode 100644 js/node_modules/minimatch/README.md create mode 100644 js/node_modules/minimatch/minimatch.js create mode 100644 js/node_modules/minimatch/package.json create mode 100644 js/node_modules/mixin-deep/LICENSE create mode 100644 js/node_modules/mixin-deep/README.md create mode 100644 js/node_modules/mixin-deep/index.js create mode 100644 js/node_modules/mixin-deep/node_modules/is-extendable/LICENSE create mode 100644 js/node_modules/mixin-deep/node_modules/is-extendable/README.md create mode 100644 js/node_modules/mixin-deep/node_modules/is-extendable/index.d.ts create mode 100644 js/node_modules/mixin-deep/node_modules/is-extendable/index.js create mode 100644 js/node_modules/mixin-deep/node_modules/is-extendable/package.json create mode 100644 js/node_modules/mixin-deep/package.json create mode 100644 js/node_modules/ms/index.js create mode 100644 js/node_modules/ms/license.md create mode 100644 js/node_modules/ms/package.json create mode 100644 js/node_modules/ms/readme.md create mode 100644 js/node_modules/nan/CHANGELOG.md create mode 100644 js/node_modules/nan/LICENSE.md create mode 100644 js/node_modules/nan/README.md create mode 100644 js/node_modules/nan/doc/asyncworker.md create mode 100644 js/node_modules/nan/doc/buffers.md create mode 100644 js/node_modules/nan/doc/callback.md create mode 100644 js/node_modules/nan/doc/converters.md create mode 100644 js/node_modules/nan/doc/errors.md create mode 100644 js/node_modules/nan/doc/json.md create mode 100644 js/node_modules/nan/doc/maybe_types.md create mode 100644 js/node_modules/nan/doc/methods.md create mode 100644 js/node_modules/nan/doc/new.md create mode 100644 js/node_modules/nan/doc/node_misc.md create mode 100644 js/node_modules/nan/doc/object_wrappers.md create mode 100644 js/node_modules/nan/doc/persistent.md create mode 100644 js/node_modules/nan/doc/scopes.md create mode 100644 js/node_modules/nan/doc/script.md create mode 100644 js/node_modules/nan/doc/string_bytes.md create mode 100644 js/node_modules/nan/doc/v8_internals.md create mode 100644 js/node_modules/nan/doc/v8_misc.md create mode 100644 js/node_modules/nan/include_dirs.js create mode 100644 js/node_modules/nan/nan.h create mode 100644 js/node_modules/nan/nan_callbacks.h create mode 100644 js/node_modules/nan/nan_callbacks_12_inl.h create mode 100644 js/node_modules/nan/nan_callbacks_pre_12_inl.h create mode 100644 js/node_modules/nan/nan_converters.h create mode 100644 js/node_modules/nan/nan_converters_43_inl.h create mode 100644 js/node_modules/nan/nan_converters_pre_43_inl.h create mode 100644 js/node_modules/nan/nan_define_own_property_helper.h create mode 100644 js/node_modules/nan/nan_implementation_12_inl.h create mode 100644 js/node_modules/nan/nan_implementation_pre_12_inl.h create mode 100644 js/node_modules/nan/nan_json.h create mode 100644 js/node_modules/nan/nan_maybe_43_inl.h create mode 100644 js/node_modules/nan/nan_maybe_pre_43_inl.h create mode 100644 js/node_modules/nan/nan_new.h create mode 100644 js/node_modules/nan/nan_object_wrap.h create mode 100644 js/node_modules/nan/nan_persistent_12_inl.h create mode 100644 js/node_modules/nan/nan_persistent_pre_12_inl.h create mode 100644 js/node_modules/nan/nan_private.h create mode 100644 js/node_modules/nan/nan_string_bytes.h create mode 100644 js/node_modules/nan/nan_typedarray_contents.h create mode 100644 js/node_modules/nan/nan_weak.h create mode 100644 js/node_modules/nan/package.json create mode 100755 js/node_modules/nan/tools/1to2.js create mode 100644 js/node_modules/nan/tools/README.md create mode 100644 js/node_modules/nan/tools/package.json create mode 100644 js/node_modules/nanomatch/CHANGELOG.md create mode 100644 js/node_modules/nanomatch/LICENSE create mode 100644 js/node_modules/nanomatch/README.md create mode 100644 js/node_modules/nanomatch/index.js create mode 100644 js/node_modules/nanomatch/lib/cache.js create mode 100644 js/node_modules/nanomatch/lib/compiler2.js create mode 100644 js/node_modules/nanomatch/lib/compilers.js create mode 100644 js/node_modules/nanomatch/lib/parsers.js create mode 100644 js/node_modules/nanomatch/lib/utils.js create mode 100755 js/node_modules/nanomatch/node_modules/arr-diff/LICENSE create mode 100644 js/node_modules/nanomatch/node_modules/arr-diff/README.md create mode 100644 js/node_modules/nanomatch/node_modules/arr-diff/index.js create mode 100644 js/node_modules/nanomatch/node_modules/arr-diff/package.json create mode 100755 js/node_modules/nanomatch/node_modules/array-unique/LICENSE create mode 100755 js/node_modules/nanomatch/node_modules/array-unique/README.md create mode 100644 js/node_modules/nanomatch/node_modules/array-unique/index.js create mode 100644 js/node_modules/nanomatch/node_modules/array-unique/package.json create mode 100644 js/node_modules/nanomatch/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/nanomatch/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/nanomatch/node_modules/kind-of/README.md create mode 100644 js/node_modules/nanomatch/node_modules/kind-of/index.js create mode 100644 js/node_modules/nanomatch/node_modules/kind-of/package.json create mode 100644 js/node_modules/nanomatch/package.json create mode 100644 js/node_modules/normalize-path/LICENSE create mode 100644 js/node_modules/normalize-path/README.md create mode 100644 js/node_modules/normalize-path/index.js create mode 100644 js/node_modules/normalize-path/package.json create mode 100644 js/node_modules/object-copy/LICENSE create mode 100644 js/node_modules/object-copy/index.js create mode 100644 js/node_modules/object-copy/node_modules/define-property/LICENSE create mode 100644 js/node_modules/object-copy/node_modules/define-property/README.md create mode 100644 js/node_modules/object-copy/node_modules/define-property/index.js create mode 100644 js/node_modules/object-copy/node_modules/define-property/package.json create mode 100644 js/node_modules/object-copy/package.json create mode 100644 js/node_modules/object-visit/LICENSE create mode 100644 js/node_modules/object-visit/README.md create mode 100644 js/node_modules/object-visit/index.js create mode 100644 js/node_modules/object-visit/node_modules/isobject/LICENSE create mode 100644 js/node_modules/object-visit/node_modules/isobject/README.md create mode 100644 js/node_modules/object-visit/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/object-visit/node_modules/isobject/index.js create mode 100644 js/node_modules/object-visit/node_modules/isobject/package.json create mode 100644 js/node_modules/object-visit/package.json create mode 100644 js/node_modules/object.omit/LICENSE create mode 100644 js/node_modules/object.omit/README.md create mode 100644 js/node_modules/object.omit/index.js create mode 100644 js/node_modules/object.omit/package.json create mode 100644 js/node_modules/object.pick/LICENSE create mode 100644 js/node_modules/object.pick/README.md create mode 100644 js/node_modules/object.pick/index.js create mode 100644 js/node_modules/object.pick/node_modules/isobject/LICENSE create mode 100644 js/node_modules/object.pick/node_modules/isobject/README.md create mode 100644 js/node_modules/object.pick/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/object.pick/node_modules/isobject/index.js create mode 100644 js/node_modules/object.pick/node_modules/isobject/package.json create mode 100644 js/node_modules/object.pick/package.json create mode 100644 js/node_modules/parse-glob/LICENSE create mode 100644 js/node_modules/parse-glob/README.md create mode 100644 js/node_modules/parse-glob/index.js create mode 100644 js/node_modules/parse-glob/package.json create mode 100644 js/node_modules/parse-passwd/LICENSE create mode 100644 js/node_modules/parse-passwd/README.md create mode 100644 js/node_modules/parse-passwd/index.js create mode 100644 js/node_modules/parse-passwd/package.json create mode 100644 js/node_modules/pascalcase/LICENSE create mode 100644 js/node_modules/pascalcase/README.md create mode 100644 js/node_modules/pascalcase/index.js create mode 100644 js/node_modules/pascalcase/package.json create mode 100644 js/node_modules/path-is-absolute/index.js create mode 100644 js/node_modules/path-is-absolute/license create mode 100644 js/node_modules/path-is-absolute/package.json create mode 100644 js/node_modules/path-is-absolute/readme.md create mode 100644 js/node_modules/path-parse/.travis.yml create mode 100644 js/node_modules/path-parse/README.md create mode 100644 js/node_modules/path-parse/index.js create mode 100644 js/node_modules/path-parse/index.min.js create mode 100644 js/node_modules/path-parse/package.json create mode 100644 js/node_modules/path-parse/test.js create mode 100644 js/node_modules/path-parse/test.min.js create mode 100644 js/node_modules/posix-character-classes/LICENSE create mode 100644 js/node_modules/posix-character-classes/README.md create mode 100644 js/node_modules/posix-character-classes/index.js create mode 100644 js/node_modules/posix-character-classes/package.json create mode 100644 js/node_modules/preserve/.gitattributes create mode 100644 js/node_modules/preserve/.jshintrc create mode 100644 js/node_modules/preserve/.npmignore create mode 100644 js/node_modules/preserve/.travis.yml create mode 100644 js/node_modules/preserve/.verb.md create mode 100644 js/node_modules/preserve/LICENSE create mode 100644 js/node_modules/preserve/README.md create mode 100644 js/node_modules/preserve/index.js create mode 100644 js/node_modules/preserve/package.json create mode 100644 js/node_modules/preserve/test.js create mode 100644 js/node_modules/process-nextick-args/index.js create mode 100644 js/node_modules/process-nextick-args/license.md create mode 100644 js/node_modules/process-nextick-args/package.json create mode 100644 js/node_modules/process-nextick-args/readme.md create mode 100644 js/node_modules/qunit/History.md create mode 100644 js/node_modules/qunit/LICENSE.txt create mode 100644 js/node_modules/qunit/README.md create mode 100644 js/node_modules/qunit/package.json create mode 100644 js/node_modules/qunit/qunit/qunit.css create mode 100644 js/node_modules/qunit/qunit/qunit.js create mode 100755 js/node_modules/randomatic/LICENSE create mode 100644 js/node_modules/randomatic/README.md create mode 100644 js/node_modules/randomatic/index.js create mode 100644 js/node_modules/randomatic/node_modules/is-number/LICENSE create mode 100644 js/node_modules/randomatic/node_modules/is-number/README.md create mode 100644 js/node_modules/randomatic/node_modules/is-number/index.js create mode 100644 js/node_modules/randomatic/node_modules/is-number/package.json create mode 100644 js/node_modules/randomatic/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/randomatic/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/randomatic/node_modules/kind-of/README.md create mode 100644 js/node_modules/randomatic/node_modules/kind-of/index.js create mode 100644 js/node_modules/randomatic/node_modules/kind-of/package.json create mode 100644 js/node_modules/randomatic/package.json create mode 100644 js/node_modules/readable-stream/.travis.yml create mode 100644 js/node_modules/readable-stream/CONTRIBUTING.md create mode 100644 js/node_modules/readable-stream/GOVERNANCE.md create mode 100644 js/node_modules/readable-stream/LICENSE create mode 100644 js/node_modules/readable-stream/README.md create mode 100644 js/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md create mode 100644 js/node_modules/readable-stream/duplex-browser.js create mode 100644 js/node_modules/readable-stream/duplex.js create mode 100644 js/node_modules/readable-stream/lib/_stream_duplex.js create mode 100644 js/node_modules/readable-stream/lib/_stream_passthrough.js create mode 100644 js/node_modules/readable-stream/lib/_stream_readable.js create mode 100644 js/node_modules/readable-stream/lib/_stream_transform.js create mode 100644 js/node_modules/readable-stream/lib/_stream_writable.js create mode 100644 js/node_modules/readable-stream/lib/internal/streams/BufferList.js create mode 100644 js/node_modules/readable-stream/lib/internal/streams/destroy.js create mode 100644 js/node_modules/readable-stream/lib/internal/streams/stream-browser.js create mode 100644 js/node_modules/readable-stream/lib/internal/streams/stream.js create mode 100644 js/node_modules/readable-stream/package.json create mode 100644 js/node_modules/readable-stream/passthrough.js create mode 100644 js/node_modules/readable-stream/readable-browser.js create mode 100644 js/node_modules/readable-stream/readable.js create mode 100644 js/node_modules/readable-stream/transform.js create mode 100644 js/node_modules/readable-stream/writable-browser.js create mode 100644 js/node_modules/readable-stream/writable.js create mode 100644 js/node_modules/readdirp/.npmignore create mode 100644 js/node_modules/readdirp/.travis.yml create mode 100644 js/node_modules/readdirp/LICENSE create mode 100644 js/node_modules/readdirp/README.md create mode 100644 js/node_modules/readdirp/examples/Readme.md create mode 100644 js/node_modules/readdirp/examples/callback-api.js create mode 100644 js/node_modules/readdirp/examples/grep.js create mode 100644 js/node_modules/readdirp/examples/package.json create mode 100644 js/node_modules/readdirp/examples/stream-api-pipe.js create mode 100644 js/node_modules/readdirp/examples/stream-api.js create mode 100644 js/node_modules/readdirp/package.json create mode 100644 js/node_modules/readdirp/readdirp.js create mode 100644 js/node_modules/readdirp/stream-api.js create mode 100644 js/node_modules/readdirp/test/bed/root_dir1/root_dir1_file1.ext1 create mode 100644 js/node_modules/readdirp/test/bed/root_dir1/root_dir1_file2.ext2 create mode 100644 js/node_modules/readdirp/test/bed/root_dir1/root_dir1_file3.ext3 create mode 100644 js/node_modules/readdirp/test/bed/root_dir1/root_dir1_subdir1/root1_dir1_subdir1_file1.ext1 create mode 100644 js/node_modules/readdirp/test/bed/root_dir2/root_dir2_file1.ext1 create mode 100644 js/node_modules/readdirp/test/bed/root_dir2/root_dir2_file2.ext2 create mode 100644 js/node_modules/readdirp/test/bed/root_file1.ext1 create mode 100644 js/node_modules/readdirp/test/bed/root_file2.ext2 create mode 100644 js/node_modules/readdirp/test/bed/root_file3.ext3 create mode 100644 js/node_modules/readdirp/test/readdirp-stream.js create mode 100644 js/node_modules/readdirp/test/readdirp.js create mode 100644 js/node_modules/regex-cache/LICENSE create mode 100644 js/node_modules/regex-cache/README.md create mode 100644 js/node_modules/regex-cache/index.js create mode 100644 js/node_modules/regex-cache/package.json create mode 100644 js/node_modules/regex-not/LICENSE create mode 100644 js/node_modules/regex-not/README.md create mode 100644 js/node_modules/regex-not/index.js create mode 100644 js/node_modules/regex-not/package.json create mode 100644 js/node_modules/remove-trailing-separator/history.md create mode 100644 js/node_modules/remove-trailing-separator/index.js create mode 100644 js/node_modules/remove-trailing-separator/license create mode 100644 js/node_modules/remove-trailing-separator/package.json create mode 100644 js/node_modules/remove-trailing-separator/readme.md create mode 100644 js/node_modules/repeat-element/LICENSE create mode 100644 js/node_modules/repeat-element/README.md create mode 100644 js/node_modules/repeat-element/index.js create mode 100644 js/node_modules/repeat-element/package.json create mode 100644 js/node_modules/repeat-string/LICENSE create mode 100644 js/node_modules/repeat-string/README.md create mode 100644 js/node_modules/repeat-string/index.js create mode 100644 js/node_modules/repeat-string/package.json create mode 100644 js/node_modules/resolve-dir/LICENSE create mode 100644 js/node_modules/resolve-dir/README.md create mode 100644 js/node_modules/resolve-dir/index.js create mode 100644 js/node_modules/resolve-dir/package.json create mode 100644 js/node_modules/resolve-url/.jshintrc create mode 100644 js/node_modules/resolve-url/LICENSE create mode 100644 js/node_modules/resolve-url/bower.json create mode 100644 js/node_modules/resolve-url/changelog.md create mode 100644 js/node_modules/resolve-url/component.json create mode 100644 js/node_modules/resolve-url/package.json create mode 100644 js/node_modules/resolve-url/readme.md create mode 100644 js/node_modules/resolve-url/resolve-url.js create mode 100644 js/node_modules/resolve-url/test/resolve-url.js create mode 100644 js/node_modules/resolve/.editorconfig create mode 100644 js/node_modules/resolve/.eslintignore create mode 100644 js/node_modules/resolve/.eslintrc create mode 100644 js/node_modules/resolve/.travis.yml create mode 100644 js/node_modules/resolve/LICENSE create mode 100644 js/node_modules/resolve/appveyor.yml create mode 100644 js/node_modules/resolve/example/async.js create mode 100644 js/node_modules/resolve/example/sync.js create mode 100644 js/node_modules/resolve/index.js create mode 100644 js/node_modules/resolve/lib/async.js create mode 100644 js/node_modules/resolve/lib/caller.js create mode 100644 js/node_modules/resolve/lib/core.js create mode 100644 js/node_modules/resolve/lib/core.json create mode 100644 js/node_modules/resolve/lib/node-modules-paths.js create mode 100644 js/node_modules/resolve/lib/sync.js create mode 100644 js/node_modules/resolve/package.json create mode 100644 js/node_modules/resolve/readme.markdown create mode 100644 js/node_modules/resolve/test/core.js create mode 100644 js/node_modules/resolve/test/dotdot.js create mode 100644 js/node_modules/resolve/test/dotdot/abc/index.js create mode 100644 js/node_modules/resolve/test/dotdot/index.js create mode 100644 js/node_modules/resolve/test/faulty_basedir.js create mode 100644 js/node_modules/resolve/test/filter.js create mode 100644 js/node_modules/resolve/test/filter_sync.js create mode 100644 js/node_modules/resolve/test/mock.js create mode 100644 js/node_modules/resolve/test/mock_sync.js create mode 100644 js/node_modules/resolve/test/module_dir.js create mode 100644 js/node_modules/resolve/test/module_dir/xmodules/aaa/index.js create mode 100644 js/node_modules/resolve/test/module_dir/ymodules/aaa/index.js create mode 100644 js/node_modules/resolve/test/module_dir/zmodules/bbb/main.js create mode 100644 js/node_modules/resolve/test/module_dir/zmodules/bbb/package.json create mode 100644 js/node_modules/resolve/test/node-modules-paths.js create mode 100644 js/node_modules/resolve/test/node_path.js create mode 100644 js/node_modules/resolve/test/node_path/x/aaa/index.js create mode 100644 js/node_modules/resolve/test/node_path/x/ccc/index.js create mode 100644 js/node_modules/resolve/test/node_path/y/bbb/index.js create mode 100644 js/node_modules/resolve/test/node_path/y/ccc/index.js create mode 100644 js/node_modules/resolve/test/nonstring.js create mode 100644 js/node_modules/resolve/test/pathfilter.js create mode 100644 js/node_modules/resolve/test/pathfilter/deep_ref/main.js create mode 100644 js/node_modules/resolve/test/precedence.js create mode 100644 js/node_modules/resolve/test/precedence/aaa.js create mode 100644 js/node_modules/resolve/test/precedence/aaa/index.js create mode 100644 js/node_modules/resolve/test/precedence/aaa/main.js create mode 100644 js/node_modules/resolve/test/precedence/bbb.js create mode 100644 js/node_modules/resolve/test/precedence/bbb/main.js create mode 100644 js/node_modules/resolve/test/resolver.js create mode 100644 js/node_modules/resolve/test/resolver/baz/doom.js create mode 100644 js/node_modules/resolve/test/resolver/baz/package.json create mode 100644 js/node_modules/resolve/test/resolver/baz/quux.js create mode 100644 js/node_modules/resolve/test/resolver/cup.coffee create mode 100644 js/node_modules/resolve/test/resolver/dot_main/index.js create mode 100644 js/node_modules/resolve/test/resolver/dot_main/package.json create mode 100644 js/node_modules/resolve/test/resolver/dot_slash_main/index.js create mode 100644 js/node_modules/resolve/test/resolver/dot_slash_main/package.json create mode 100644 js/node_modules/resolve/test/resolver/foo.js create mode 100644 js/node_modules/resolve/test/resolver/incorrect_main/index.js create mode 100644 js/node_modules/resolve/test/resolver/incorrect_main/package.json create mode 100644 js/node_modules/resolve/test/resolver/mug.coffee create mode 100644 js/node_modules/resolve/test/resolver/mug.js create mode 100644 js/node_modules/resolve/test/resolver/other_path/lib/other-lib.js create mode 100644 js/node_modules/resolve/test/resolver/other_path/root.js create mode 100644 js/node_modules/resolve/test/resolver/quux/foo/index.js create mode 100644 js/node_modules/resolve/test/resolver/same_names/foo.js create mode 100644 js/node_modules/resolve/test/resolver/same_names/foo/index.js create mode 100644 js/node_modules/resolve/test/resolver/symlinked/_/symlink_target/.gitkeep create mode 100644 js/node_modules/resolve/test/resolver/without_basedir/main.js create mode 100644 js/node_modules/resolve/test/resolver_sync.js create mode 100644 js/node_modules/resolve/test/subdirs.js create mode 100644 js/node_modules/resolve/test/symlinks.js create mode 100644 js/node_modules/ret/LICENSE create mode 100644 js/node_modules/ret/README.md create mode 100644 js/node_modules/ret/lib/index.js create mode 100644 js/node_modules/ret/lib/positions.js create mode 100644 js/node_modules/ret/lib/sets.js create mode 100644 js/node_modules/ret/lib/types.js create mode 100644 js/node_modules/ret/lib/util.js create mode 100644 js/node_modules/ret/package.json create mode 100644 js/node_modules/safe-buffer/LICENSE create mode 100644 js/node_modules/safe-buffer/README.md create mode 100644 js/node_modules/safe-buffer/index.d.ts create mode 100644 js/node_modules/safe-buffer/index.js create mode 100644 js/node_modules/safe-buffer/package.json create mode 100644 js/node_modules/safe-regex/.travis.yml create mode 100644 js/node_modules/safe-regex/LICENSE create mode 100644 js/node_modules/safe-regex/example/safe.js create mode 100644 js/node_modules/safe-regex/index.js create mode 100644 js/node_modules/safe-regex/package.json create mode 100644 js/node_modules/safe-regex/readme.markdown create mode 100644 js/node_modules/safe-regex/test/regex.js create mode 100644 js/node_modules/set-immediate-shim/index.js create mode 100644 js/node_modules/set-immediate-shim/package.json create mode 100644 js/node_modules/set-immediate-shim/readme.md create mode 100644 js/node_modules/set-value/LICENSE create mode 100644 js/node_modules/set-value/README.md create mode 100644 js/node_modules/set-value/index.js create mode 100644 js/node_modules/set-value/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/set-value/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/set-value/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/set-value/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/set-value/package.json create mode 100644 js/node_modules/snapdragon-node/LICENSE create mode 100644 js/node_modules/snapdragon-node/README.md create mode 100644 js/node_modules/snapdragon-node/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/define-property/LICENSE create mode 100644 js/node_modules/snapdragon-node/node_modules/define-property/README.md create mode 100644 js/node_modules/snapdragon-node/node_modules/define-property/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/define-property/package.json create mode 100644 js/node_modules/snapdragon-node/node_modules/is-accessor-descriptor/LICENSE create mode 100644 js/node_modules/snapdragon-node/node_modules/is-accessor-descriptor/README.md create mode 100644 js/node_modules/snapdragon-node/node_modules/is-accessor-descriptor/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/is-accessor-descriptor/package.json create mode 100644 js/node_modules/snapdragon-node/node_modules/is-data-descriptor/LICENSE create mode 100644 js/node_modules/snapdragon-node/node_modules/is-data-descriptor/README.md create mode 100644 js/node_modules/snapdragon-node/node_modules/is-data-descriptor/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/is-data-descriptor/package.json create mode 100644 js/node_modules/snapdragon-node/node_modules/is-descriptor/LICENSE create mode 100644 js/node_modules/snapdragon-node/node_modules/is-descriptor/README.md create mode 100644 js/node_modules/snapdragon-node/node_modules/is-descriptor/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/is-descriptor/package.json create mode 100644 js/node_modules/snapdragon-node/node_modules/isobject/LICENSE create mode 100644 js/node_modules/snapdragon-node/node_modules/isobject/README.md create mode 100644 js/node_modules/snapdragon-node/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/snapdragon-node/node_modules/isobject/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/isobject/package.json create mode 100644 js/node_modules/snapdragon-node/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/snapdragon-node/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/snapdragon-node/node_modules/kind-of/README.md create mode 100644 js/node_modules/snapdragon-node/node_modules/kind-of/index.js create mode 100644 js/node_modules/snapdragon-node/node_modules/kind-of/package.json create mode 100644 js/node_modules/snapdragon-node/package.json create mode 100644 js/node_modules/snapdragon-util/LICENSE create mode 100644 js/node_modules/snapdragon-util/README.md create mode 100644 js/node_modules/snapdragon-util/index.js create mode 100644 js/node_modules/snapdragon-util/package.json create mode 100644 js/node_modules/snapdragon/LICENSE create mode 100644 js/node_modules/snapdragon/README.md create mode 100644 js/node_modules/snapdragon/index.js create mode 100644 js/node_modules/snapdragon/lib/compiler.js create mode 100644 js/node_modules/snapdragon/lib/parser.js create mode 100644 js/node_modules/snapdragon/lib/position.js create mode 100644 js/node_modules/snapdragon/lib/source-maps.js create mode 100644 js/node_modules/snapdragon/lib/utils.js create mode 100644 js/node_modules/snapdragon/node_modules/define-property/LICENSE create mode 100644 js/node_modules/snapdragon/node_modules/define-property/README.md create mode 100644 js/node_modules/snapdragon/node_modules/define-property/index.js create mode 100644 js/node_modules/snapdragon/node_modules/define-property/package.json create mode 100644 js/node_modules/snapdragon/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/snapdragon/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/snapdragon/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/snapdragon/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/snapdragon/package.json create mode 100644 js/node_modules/source-map-resolve/.jshintrc create mode 100644 js/node_modules/source-map-resolve/.travis.yml create mode 100644 js/node_modules/source-map-resolve/LICENSE create mode 100644 js/node_modules/source-map-resolve/bower.json create mode 100644 js/node_modules/source-map-resolve/changelog.md create mode 100644 js/node_modules/source-map-resolve/component.json create mode 100644 js/node_modules/source-map-resolve/generate-source-map-resolve.js create mode 100644 js/node_modules/source-map-resolve/lib/decode-uri-component.js create mode 100644 js/node_modules/source-map-resolve/lib/resolve-url.js create mode 100644 js/node_modules/source-map-resolve/lib/source-map-resolve-node.js create mode 100644 js/node_modules/source-map-resolve/package.json create mode 100644 js/node_modules/source-map-resolve/readme.md create mode 100644 js/node_modules/source-map-resolve/source-map-resolve.js create mode 100644 js/node_modules/source-map-resolve/source-map-resolve.js.template create mode 100644 js/node_modules/source-map-resolve/test/common.js create mode 100644 js/node_modules/source-map-resolve/test/read.js create mode 100644 js/node_modules/source-map-resolve/test/source-map-resolve.js create mode 100644 js/node_modules/source-map-resolve/test/windows.js create mode 100644 js/node_modules/source-map-resolve/x-package.json5 create mode 100644 js/node_modules/source-map-url/.jshintrc create mode 100644 js/node_modules/source-map-url/LICENSE create mode 100644 js/node_modules/source-map-url/bower.json create mode 100644 js/node_modules/source-map-url/changelog.md create mode 100644 js/node_modules/source-map-url/component.json create mode 100644 js/node_modules/source-map-url/package.json create mode 100644 js/node_modules/source-map-url/readme.md create mode 100644 js/node_modules/source-map-url/source-map-url.js create mode 100644 js/node_modules/source-map-url/test/source-map-url.js create mode 100644 js/node_modules/source-map-url/x-package.json5 create mode 100644 js/node_modules/source-map/CHANGELOG.md create mode 100644 js/node_modules/source-map/LICENSE create mode 100644 js/node_modules/source-map/README.md create mode 100644 js/node_modules/source-map/dist/source-map.debug.js create mode 100644 js/node_modules/source-map/dist/source-map.js create mode 100644 js/node_modules/source-map/dist/source-map.min.js create mode 100644 js/node_modules/source-map/dist/source-map.min.js.map create mode 100644 js/node_modules/source-map/lib/array-set.js create mode 100644 js/node_modules/source-map/lib/base64-vlq.js create mode 100644 js/node_modules/source-map/lib/base64.js create mode 100644 js/node_modules/source-map/lib/binary-search.js create mode 100644 js/node_modules/source-map/lib/mapping-list.js create mode 100644 js/node_modules/source-map/lib/quick-sort.js create mode 100644 js/node_modules/source-map/lib/source-map-consumer.js create mode 100644 js/node_modules/source-map/lib/source-map-generator.js create mode 100644 js/node_modules/source-map/lib/source-node.js create mode 100644 js/node_modules/source-map/lib/util.js create mode 100644 js/node_modules/source-map/package.json create mode 100644 js/node_modules/source-map/source-map.js create mode 100644 js/node_modules/split-string/LICENSE create mode 100644 js/node_modules/split-string/README.md create mode 100644 js/node_modules/split-string/index.js create mode 100644 js/node_modules/split-string/package.json create mode 100644 js/node_modules/static-extend/LICENSE create mode 100644 js/node_modules/static-extend/index.js create mode 100644 js/node_modules/static-extend/node_modules/define-property/LICENSE create mode 100644 js/node_modules/static-extend/node_modules/define-property/README.md create mode 100644 js/node_modules/static-extend/node_modules/define-property/index.js create mode 100644 js/node_modules/static-extend/node_modules/define-property/package.json create mode 100644 js/node_modules/static-extend/package.json create mode 100644 js/node_modules/string_decoder/.travis.yml create mode 100644 js/node_modules/string_decoder/LICENSE create mode 100644 js/node_modules/string_decoder/README.md create mode 100644 js/node_modules/string_decoder/lib/string_decoder.js create mode 100644 js/node_modules/string_decoder/package.json create mode 100644 js/node_modules/to-object-path/LICENSE create mode 100644 js/node_modules/to-object-path/README.md create mode 100644 js/node_modules/to-object-path/index.js create mode 100644 js/node_modules/to-object-path/package.json create mode 100644 js/node_modules/to-regex-range/LICENSE create mode 100644 js/node_modules/to-regex-range/README.md create mode 100644 js/node_modules/to-regex-range/index.js create mode 100644 js/node_modules/to-regex-range/node_modules/is-number/LICENSE create mode 100644 js/node_modules/to-regex-range/node_modules/is-number/README.md create mode 100644 js/node_modules/to-regex-range/node_modules/is-number/index.js create mode 100644 js/node_modules/to-regex-range/node_modules/is-number/package.json create mode 100644 js/node_modules/to-regex-range/package.json create mode 100644 js/node_modules/to-regex/LICENSE create mode 100644 js/node_modules/to-regex/README.md create mode 100644 js/node_modules/to-regex/index.js create mode 100644 js/node_modules/to-regex/package.json create mode 100644 js/node_modules/union-value/LICENSE create mode 100644 js/node_modules/union-value/README.md create mode 100644 js/node_modules/union-value/index.js create mode 100644 js/node_modules/union-value/node_modules/extend-shallow/LICENSE create mode 100644 js/node_modules/union-value/node_modules/extend-shallow/README.md create mode 100644 js/node_modules/union-value/node_modules/extend-shallow/index.js create mode 100644 js/node_modules/union-value/node_modules/extend-shallow/package.json create mode 100644 js/node_modules/union-value/node_modules/set-value/LICENSE create mode 100644 js/node_modules/union-value/node_modules/set-value/README.md create mode 100644 js/node_modules/union-value/node_modules/set-value/index.js create mode 100644 js/node_modules/union-value/node_modules/set-value/package.json create mode 100644 js/node_modules/union-value/package.json create mode 100644 js/node_modules/unset-value/LICENSE create mode 100644 js/node_modules/unset-value/README.md create mode 100644 js/node_modules/unset-value/index.js create mode 100644 js/node_modules/unset-value/node_modules/has-value/LICENSE create mode 100644 js/node_modules/unset-value/node_modules/has-value/README.md create mode 100644 js/node_modules/unset-value/node_modules/has-value/index.js create mode 100644 js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/LICENSE create mode 100644 js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/README.md create mode 100644 js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/index.js create mode 100644 js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/package.json create mode 100644 js/node_modules/unset-value/node_modules/has-value/package.json create mode 100644 js/node_modules/unset-value/node_modules/has-values/LICENSE create mode 100644 js/node_modules/unset-value/node_modules/has-values/README.md create mode 100644 js/node_modules/unset-value/node_modules/has-values/index.js create mode 100644 js/node_modules/unset-value/node_modules/has-values/package.json create mode 100644 js/node_modules/unset-value/node_modules/isobject/LICENSE create mode 100644 js/node_modules/unset-value/node_modules/isobject/README.md create mode 100644 js/node_modules/unset-value/node_modules/isobject/index.d.ts create mode 100644 js/node_modules/unset-value/node_modules/isobject/index.js create mode 100644 js/node_modules/unset-value/node_modules/isobject/package.json create mode 100644 js/node_modules/unset-value/package.json create mode 100644 js/node_modules/urix/.jshintrc create mode 100644 js/node_modules/urix/LICENSE create mode 100644 js/node_modules/urix/index.js create mode 100644 js/node_modules/urix/package.json create mode 100644 js/node_modules/urix/readme.md create mode 100644 js/node_modules/urix/test/index.js create mode 100644 js/node_modules/use/LICENSE create mode 100644 js/node_modules/use/README.md create mode 100644 js/node_modules/use/index.js create mode 100644 js/node_modules/use/node_modules/kind-of/CHANGELOG.md create mode 100644 js/node_modules/use/node_modules/kind-of/LICENSE create mode 100644 js/node_modules/use/node_modules/kind-of/README.md create mode 100644 js/node_modules/use/node_modules/kind-of/index.js create mode 100644 js/node_modules/use/node_modules/kind-of/package.json create mode 100644 js/node_modules/use/package.json create mode 100644 js/node_modules/util-deprecate/History.md create mode 100644 js/node_modules/util-deprecate/LICENSE create mode 100644 js/node_modules/util-deprecate/README.md create mode 100644 js/node_modules/util-deprecate/browser.js create mode 100644 js/node_modules/util-deprecate/node.js create mode 100644 js/node_modules/util-deprecate/package.json create mode 100644 js/node_modules/walk-sync/CHANGELOG.md create mode 100644 js/node_modules/walk-sync/LICENSE create mode 100644 js/node_modules/walk-sync/README.md create mode 100644 js/node_modules/walk-sync/index.js create mode 100644 js/node_modules/walk-sync/package.json create mode 100644 js/node_modules/which/CHANGELOG.md create mode 100644 js/node_modules/which/LICENSE create mode 100644 js/node_modules/which/README.md create mode 100644 js/node_modules/which/package.json create mode 100644 js/node_modules/which/which.js create mode 100644 js/package-lock.json create mode 100644 js/src/main/kotlin/actions/expected/BuiltinFrameworks.kt create mode 100644 js/src/main/kotlin/actions/expected/Expected.kt create mode 100644 js/src/main/kotlin/actions/expected/OAuth2Client.kt create mode 100644 js/src/main/kotlin/actions/expected/Serializer.kt create mode 100644 js/src/main/kotlin/actions/expected/deserialize.kt create mode 100644 js/src/main/kotlin/actions/expected/log.kt create mode 100644 jvm-app/build.gradle create mode 100644 jvm-app/src/main/kotlin/jvm/ActionsSdkSample.kt create mode 100644 jvm-app/src/main/kotlin/jvm/AogMockFactory.kt create mode 100644 jvm-app/src/main/kotlin/jvm/AogSample.kt create mode 100644 jvm-app/src/main/kotlin/jvm/DelegationServletInputStream.kt create mode 100644 jvm-app/src/main/kotlin/jvm/DfSampleTransactions.kt create mode 100644 jvm-app/src/main/kotlin/jvm/DialogflowSample.kt create mode 100644 jvm-app/src/main/kotlin/jvm/JvmApp.kt create mode 100644 jvm-app/src/main/kotlin/jvm/Requests.kt rename {sdk-gson-servlet => jvm}/build.gradle (77%) create mode 100644 jvm/src/main/java/actions/expected/BuiltinFrameworks.kt create mode 100644 jvm/src/main/java/actions/expected/Expected.kt create mode 100644 jvm/src/main/java/actions/expected/OAuth2Client.kt create mode 100644 jvm/src/main/java/actions/expected/Serializer.kt create mode 100644 jvm/src/main/java/actions/expected/ServletUtils.java rename sdk-gson-servlet/src/main/java/com/tmsdurham/actions/OrderUpdateSerializer.kt => jvm/src/main/java/actions/expected/TypeAdapters.kt (50%) create mode 100644 jvm/src/main/java/actions/expected/deserialize.kt create mode 100644 jvm/src/main/java/actions/expected/framework/ServletFramework.kt create mode 100644 jvm/src/main/java/actions/expected/framework/TestHttpServlet.kt create mode 100644 jvm/src/main/java/actions/expected/log.kt create mode 100644 sample-gae-jvm/build.gradle create mode 100644 sample-gae-jvm/src/main/java/jvm/DfTransactionsWebhook.kt create mode 100644 sample-gae-jvm/src/main/java/jvm/DialogflowWebhook.kt create mode 100644 sample-gae-jvm/src/main/java/jvm/SampleWebhook.kt rename {dialogflow-samples => sample-gae-jvm}/src/main/webapp/WEB-INF/appengine-web.xml (51%) rename {action-sdk-samples => sample-gae-jvm}/src/main/webapp/WEB-INF/logging.properties (100%) create mode 100644 sample-gae-jvm/src/main/webapp/WEB-INF/web.xml delete mode 100644 sdk-gson-servlet/README.md delete mode 100644 sdk-gson-servlet/src/main/java/com/tmsdurham/actions/Actions.kt delete mode 100644 sdk/.gitignore delete mode 100644 sdk/build.gradle delete mode 100644 sdk/build.gradle.kts.bak delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/ActionsApp.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/AssistantApp.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/DialogflowApp.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/DialogflowRequest.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/DialogflowResponse.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/GoogleData.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/RequestExtractor.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/RequestWrapper.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/ResponseBuilder.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/ResponseWrapper.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/Transactions.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/actions/ActionRequest.kt delete mode 100644 sdk/src/main/java/com/tmsdurham/actions/actions/ActionResponse.kt delete mode 100644 sdk/src/test/java/com/tmsdurham/actions/ActionsSdkTest.kt delete mode 100644 sdk/src/test/java/com/tmsdurham/actions/DialogflowTest.kt delete mode 100644 sdk/src/test/java/com/tmsdurham/actions/ResponseBuilderTest.kt delete mode 100644 sdk/src/test/java/com/tmsdurham/actions/TransactionsTest.kt diff --git a/README.md b/README.md index b64ce9b..c1f3bb3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Actions On Google Client Library + + + ![](https://storage.googleapis.com/kotlin-actions-sdk.appspot.com/actions-kotlin-java.png) This is a port of the [official Node.js SDK](https://github.com/actions-on-google/actions-on-google-nodejs) to Kotlin. This can also be used from Java and any JVM language. @@ -15,25 +18,41 @@ __Quick Facts__ * Conversation Components & Transaction Sample ported * Supports v2 of Actions on Google API (if v1 is needed, make an issue please) -## Setup Instructions + +## V2 Support + +The V2 release is available by using: + + compile 'com.tmsdurham.actions:actions-on-google:2.0.1' + +The V2 is mostly complete, but may have a few bugs and missing features. All Conversation components and Transaction API are working. Dialogflow & ActionSDK has been tested and working. The API matches the official node.js API very closely. The sample in this repo is a good place to get started. The setup and samples in this readme have not been updated yet. There are a few differerences and additions: + + * use action name from Dialogflow instead of intent name. The official library changed from using the action field, to using the intent name. There is a PR open on the official SDK for support for action. If/when this is merged, this library will be updated to match. + * middleware not supported. Same functionality can be implemented without lib support by wrapping handlers in fuctions. + +__V2 notes__: +A common module was used with the intent on targeting multiple platforms (JS & possibly native). These other platforms are purely experimental at this time. A single code base for JVM and JS would be more efficient. + +## Setup Instructions(V1 - see sample for V2 setup and use) This library is available on jCenter. If your using gradle simply add the dependency as follows: __Gradle:__ repositories { - jcenter() + jCenter() + } } dependencies { - compile 'com.tmsdurham.actions:actions-on-google:1.6.3' + compile 'com.tmsdurham.actions:actions-on-google:1.6.0' } __Maven:__ com.tmsdurham.actions actions-on-google - 1.6.3 + 1.6.0 pom @@ -41,14 +60,14 @@ The above artifact should fit the needs of most developers, however, if you are __Gradle:__ - compile 'com.tmsdurham.actions:actions-on-google-core:1.6.3'. //only if not using Servlets + compile 'com.tmsdurham.actions:actions-on-google-core:1.6.0'. //only if not using Servlets __Maven:__ com.tmsdurham.actions actions-on-google-core //only if not using Servlets - 1.6.3 + 1.6.0 pom diff --git a/action-sdk-samples/action.json b/action-sdk-samples/action.json deleted file mode 100644 index bd5a80f..0000000 --- a/action-sdk-samples/action.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "actions": [ - { - "description": "Launch intent", - "name": "MAIN", - "fulfillment": { - "conversationName": "mainConversation" - }, - "intent": { - "name": "actions.intent.MAIN" - } - } - ], - "conversations": { - "mainConversation": { - "name": "mainConversation", - "url": "https://kotlin-actions-sdk.appspot.com/conversation", - "fulfillmentApiVersion": 2 - } - } -} diff --git a/action-sdk-samples/build.gradle b/action-sdk-samples/build.gradle deleted file mode 100644 index 79a3875..0000000 --- a/action-sdk-samples/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath 'com.google.cloud.tools:appengine-gradle-plugin:+' - // latest App Engine Gradle tasks - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$project.ext.kotlinVersion" - } -} -repositories { - mavenCentral() -} - -apply plugin: 'idea' -apply plugin: 'kotlin' -apply plugin: 'java' -apply plugin: 'war' -apply plugin: 'com.google.cloud.tools.appengine' - -dependencies { - compile('javax.servlet:javax.servlet-api:3.1.0', - 'com.google.appengine:appengine:+', - "com.google.code.gson:gson:$project.ext.gsonVersion", - "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$project.ext.kotlinVersion") - compile project(':sdk-gson-servlet') -} - - -appengine { // App Engine tasks configuration - run { // local (dev_appserver) configuration (standard environments only) - port = 8080 // default - } - - deploy { // deploy configuration - stopPreviousVersion = true // default - stop the current version - promote = true // default - & make this the current version - version = 'prod' - } -} - -sourceCompatibility = "1.8" -targetCompatibility = "1.8" - diff --git a/action-sdk-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt b/action-sdk-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt deleted file mode 100644 index fdbb5e6..0000000 --- a/action-sdk-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt +++ /dev/null @@ -1,234 +0,0 @@ -package com.tmsdurham.actions - -import main.java.com.tmsdurham.dialogflow.sample.ActionsSdkAction -import java.util.logging.Logger -import javax.servlet.annotation.WebServlet -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -// Copyright 2017, Google, Inc. -// Licensed under the Apache License, Version 2.0 (the "License") -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Constants for list and carousel selection -val logger = Logger.getAnonymousLogger() - -val SELECTION_KEY_ONE = "title" -val SELECTION_KEY_GOOGLE_HOME = "googleHome" -val SELECTION_KEY_GOOGLE_PIXEL = "googlePixel" -val SELECTION_KEY_GOOGLE_ALLO = "googleAllo" - -// Constant for image URLs -val IMG_URL_AOG = "https://developers.google.com/actions/images/badges" + - "/XPM_BADGING_GoogleAssistant_VER.png" -val IMG_URL_GOOGLE_HOME = "https://lh3.googleusercontent.com" + - "/Nu3a6F80WfixUqf_ec_vgXy_c0-0r4VLJRXjVFF_X_CIilEu8B9fT35qyTEj_PEsKw" -val IMG_URL_GOOGLE_PIXEL = "https://storage.googleapis.com/madebygoog/v1" + - "/Pixel/Pixel_ColorPicker/Pixel_Device_Angled_Black-720w.png" -val IMG_URL_GOOGLE_ALLO = "https://allo.google.com/images/allo-logo.png" - -// Welcome -fun welcome(app: ActionsSdkApp) = - app.ask(app.buildRichResponse() - .addSimpleResponse(speech = "Hi there!", displayText = "Hello there!") - .addSimpleResponse( - speech = "I can show you basic cards, lists and carousels as well as " + - "suggestions on your phone", - displayText = "I can show you basic cards, lists and carousels as " + - "well as suggestions" - ) - .addSuggestions( - "Basic Card", "List", "Carousel", "Suggestions")) - -fun normalAsk(app: ActionsSdkApp) = - app.ask("Ask me to show you a list, carousel, or basic card") - -// Suggestions -fun suggestions(app: ActionsSdkApp) = - app.ask(app - .buildRichResponse() - .addSimpleResponse("This is a simple response for suggestions") - .addSuggestions("Suggestion Chips") - .addSuggestions("Basic Card", "List", "Carousel") - .addSuggestionLink("Suggestion Link", "https://assistant.google.com/")) - -// Basic card -fun basicCard(app: ActionsSdkApp) { - app.ask(app.buildRichResponse() - .addSimpleResponse("This is the first simple response for a basic card") - .addSuggestions( - "Basic Card", "List", "Carousel", "Suggestions") - // Create a basic card and add it to the rich response - .addBasicCard(app.buildBasicCard(""" This is a basic card . Text in a - basic card can include "quotes" and most other unicode characters - including emoji 📱. Basic cards also support some markdown - formatting like * emphasis * or _italics_, ** strong * * or __bold__, - and * * * bold itallic * * * or ___strong emphasis___ as well as other things - like line \nbreaks """) // Note the two spaces before "\n" required for a - // line break to be rendered in the card - .setSubtitle("This is a subtitle") - .setTitle("Title: this is a title") - .addButton("This is a button", "https://assistant.google.com/") - .setImage(IMG_URL_AOG, "Image alternate text") - ) - .addSimpleResponse( - speech = "This is the second simple response ", - displayText = "This is the 2nd simple response") - ) -} - -// List -fun list(app: ActionsSdkApp) { - app.askWithList(app.buildRichResponse() - .addSimpleResponse("This is a simple response for a list") - .addSuggestions( - "Basic Card", "List", "Carousel", "Suggestions"), - // Build a list - app.buildList("List Title") - // Add the first item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_ONE, - "synonym of title 1", "synonym of title 2", "synonym of title 3") - .setTitle("Title of First List Item") - .setDescription("This is a description of a list item") - .setImage(IMG_URL_AOG, "Image alternate text")) - // Add the second item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_HOME, - "Google Home Assistant", "Assistant on the Google Home") - .setTitle("Google Home") - .setDescription(""" Google Home is a voice - activated speaker powered by - the Google Assistant.""") - .setImage(IMG_URL_GOOGLE_HOME, "Google Home") - ) - // Add third item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_PIXEL, - "Google Pixel XL", "Pixel", "Pixel XL") - .setTitle("Google Pixel") - .setDescription("Pixel. Phone by Google.") - .setImage(IMG_URL_GOOGLE_PIXEL, "Google Pixel") - ) - // Add last item of the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_ALLO) - .setTitle("Google Allo") - .setDescription("Introducing Google Allo, a smart messaging app" + - "that helps you say more and do more.") - .setImage(IMG_URL_GOOGLE_ALLO, "Google Allo Logo") - .addSynonyms("Allo") - ) - ) -} - -// Carousel -fun carousel(app: ActionsSdkApp) { - app.askWithCarousel(app.buildRichResponse() - .addSimpleResponse("This is a simple response for a carousel") - .addSuggestions( - "Basic Card", "List", "Carousel", "Suggestions"), - app.buildCarousel() - // Add the first item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_ONE, - "synonym of title 1", "synonym of title 2", "synonym of title 3") - .setTitle("Title of First List Item") - .setDescription("This is a description of a carousel item") - .setImage(IMG_URL_AOG, "Image alternate text")) - // Add the second item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_HOME, - "Google Home Assistant", "Assistant on the Google Home") - .setTitle("Google Home") - .setDescription(""" Google Home is a voice - activated speaker powered by - the Google Assistant.""") - .setImage(IMG_URL_GOOGLE_HOME, "Google Home") - ) - // Add third item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_PIXEL, - "Google Pixel XL", "Pixel", "Pixel XL") - .setTitle("Google Pixel") - .setDescription("Pixel. Phone by Google.") - .setImage(IMG_URL_GOOGLE_PIXEL, "Google Pixel") - ) - // Add last item of the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_ALLO) - .setTitle("Google Allo") - .setDescription("Introducing Google Allo, a smart messaging app" + - "that helps you say more and do more.") - .setImage(IMG_URL_GOOGLE_ALLO, "Google Allo Logo") - .addSynonyms("Allo") - ) - ) -} - -// React to list or carousel selection -fun itemSelected(app: ActionsSdkApp) { - val param = app.getSelectedOption() - logger.info("USER SELECTED: " + param) - when (param) { - null -> app.ask("You did not select any item from the list or carousel") - SELECTION_KEY_ONE -> app.ask("You selected the first item in the list or carousel") - SELECTION_KEY_GOOGLE_HOME -> app.ask("You selected the Google Home!") - SELECTION_KEY_GOOGLE_PIXEL -> app.ask("You selected the Google Pixel!") - SELECTION_KEY_GOOGLE_ALLO -> app.ask("You selected Google Allo!") - else -> app.ask("You selected an unknown item from the list or carousel") - } -} - -// Leave conversation with card -fun byeCard(app: ActionsSdkApp) { - app.tell(app.buildRichResponse() - .addSimpleResponse("Goodbye, World!") - .addBasicCard(app.buildBasicCard("This is a goodbye card."))) -} - -// Leave conversation with SimpleResponse -fun byeResponse(app: ActionsSdkApp) { - app.tell( - speech = "Okay see you later", - displayText = "OK see you later!" - ) -} - -// Leave conversation -fun normalBye(app: ActionsSdkApp) { - app.tell("Okay see you later!") -} - -fun actionsText(app: ActionsSdkApp) { - val rawInput = app.getRawInput() - logger.info("USER SAID " + rawInput) - when (rawInput) { - "Basic Card", "basic card" -> basicCard(app) - "List", "list" -> list(app) - "Carousel", "carousel" -> carousel(app) - "normal ask" -> normalAsk(app) - "normal bye" -> normalBye(app) - "bye card" -> byeCard(app) - "bye response" -> byeResponse(app) - "Suggestions", "Suggestion Chips", - "suggestions", "suggestions chips" -> - suggestions(app) - else -> - normalAsk(app) - } -} - -@WebServlet("/conversation") -class ConversationComponentsSample : HttpServlet() { - override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { - - val app = ActionsSdkAction(req, resp) - val actionMap = mutableMapOf( - app.app.STANDARD_INTENTS.MAIN to ::welcome, - app.app.STANDARD_INTENTS.TEXT to ::actionsText, - app.app.STANDARD_INTENTS.OPTION to ::itemSelected) - app.handleRequest(actionMap) - } -} - diff --git a/action-sdk-samples/src/main/webapp/WEB-INF/appengine-web.xml b/action-sdk-samples/src/main/webapp/WEB-INF/appengine-web.xml deleted file mode 100644 index e58d6f3..0000000 --- a/action-sdk-samples/src/main/webapp/WEB-INF/appengine-web.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - kotlin-actions-sdk - dev - - java8 - true - - 100ms - 500ms - 30 - - - - - diff --git a/action-sdk-samples/src/main/webapp/WEB-INF/web.xml b/action-sdk-samples/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 9e5b267..0000000 --- a/action-sdk-samples/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8f41dd8..06dd800 100644 --- a/build.gradle +++ b/build.gradle @@ -1,50 +1,69 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. +allprojects { + group 'com.ticketmaster.actions' + version '1-SNAPSHOT' -buildscript { - ext.kotlin_version = '1.2.10' - repositories { - jcenter() + apply plugin: 'idea' + idea { + module { + outputDir file('build/classes/main') + testOutputDir file('build/classes/test') + } } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files + if (project.convention.findPlugin(JavaPluginConvention)) { + // Change the output directory for the main and test source sets back to the old path + sourceSets.main.output.classesDir = new File(buildDir, "classes/main") + sourceSets.test.output.classesDir = new File(buildDir, "classes/test") } } -apply plugin: 'kotlin' +task wrapper(type: Wrapper) { + gradleVersion = '4.7' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" +} + +task cleanOutDir(type: Delete) { + delete 'out' +} repositories { maven { url "http://dl.bintray.com/jetbrains/spek" } } -allprojects { +buildscript { + ext.kotlinVersion = '1.2.51' + repositories { jcenter() + mavenCentral() + maven { url "https://plugins.gradle.org/m2/" } } - project.ext { - kotlinVersion = '1.2.10' - gsonVersion = '2.8.1' - sdkVersion = '1.6.4' //version of deployed artifacts - spekVersion = '1.1.5' + dependencies { + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' + classpath "com.eriwen:gradle-js-plugin:2.14.1" + classpath 'com.moowork.gradle:gradle-node-plugin:1.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" } } -repositories { - mavenCentral() -} -dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" +ext { + sdkVersion = '2.0.2-alpha' //version of deployed artifacts + nodeVersion = '8.11.1' + qunitVersion = '2.6.0' + libraries = [ + junit : "junit:junit:4.12", + kotlin_stdlib : "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion", + kotlin_stdlib_common : "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion", + kotlin_stdlib_js : "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinVersion", + kotlin_test_annotations_common: "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlinVersion", + kotlin_test_common : "org.jetbrains.kotlin:kotlin-test-common:$kotlinVersion", + kotlin_test_js : "org.jetbrains.kotlin:kotlin-test-js:$kotlinVersion", + kotlin_test_junit : "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion", + ] } -compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} -compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" + +subprojects { + repositories { + jcenter() + mavenCentral() } } diff --git a/common-mock/build.gradle b/common-mock/build.gradle new file mode 100644 index 0000000..28d84b3 --- /dev/null +++ b/common-mock/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'kotlin-platform-common' + +archivesBaseName = 'actions-on-google-common-mock' + +dependencies { + compile project(":common") + compile libraries.kotlin_stdlib_common + testCompile libraries.kotlin_test_annotations_common + testCompile libraries.kotlin_test_common +} + +task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.kotlin +} + +artifacts { + archives sourcesJar +} diff --git a/common-mock/src/main/kotlin/actions/AogMockFactory.kt b/common-mock/src/main/kotlin/actions/AogMockFactory.kt new file mode 100644 index 0000000..aafe803 --- /dev/null +++ b/common-mock/src/main/kotlin/actions/AogMockFactory.kt @@ -0,0 +1,7 @@ +package actions + +object AogMockFactory { + fun mockWelcome() { + + } +} \ No newline at end of file diff --git a/common-mock/src/main/kotlin/actions/Requests.kt b/common-mock/src/main/kotlin/actions/Requests.kt new file mode 100644 index 0000000..1083425 --- /dev/null +++ b/common-mock/src/main/kotlin/actions/Requests.kt @@ -0,0 +1,131 @@ +package actions + +object MockResponses { + const val welcome = """{ +"user":{ +"userId":"APhe68EmFG8L689xcinHdNbpSadP", +"locale":"en-US", +"lastSeen":"2018-05-22T01:38:28Z", +"userStorage":"{\"data\":{}}" +}, +"conversation":{ +"conversationId":"1526953174329", +"type":"ACTIVE", +"conversationToken":"{\"data\":{}}" +}, +"inputs":[ +{ +"intent":"actions.intent.TEXT", +"rawInputs":[ +{ +"inputType":"TOUCH", +"query":"Basic Card" +} +], +"arguments":[ +{ +"name":"text", +"rawText":"Basic Card", +"textValue":"Basic Card" +} +] +} +], +"surface":{ +"capabilities":[ +{ +"name":"actions.capability.MEDIA_RESPONSE_AUDIO" +}, +{ +"name":"actions.capability.WEB_BROWSER" +}, +{ +"name":"actions.capability.AUDIO_OUTPUT" +}, +{ +"name":"actions.capability.SCREEN_OUTPUT" +} +] +}, +"isInSandbox":true, +"availableSurfaces":[ +{ +"capabilities":[ +{ +"name":"actions.capability.WEB_BROWSER" +}, +{ +"name":"actions.capability.AUDIO_OUTPUT" +}, +{ +"name":"actions.capability.SCREEN_OUTPUT" +} +] +} +] +}""" + + const val basicCard = """{ + "user":{ + "userId":"APhe68EmFG8L689xcinHdNbpSadP", + "locale":"en-US", + "lastSeen":"2018-05-22T01:38:28Z", + "userStorage":"{\"data\":{}}" + }, + "conversation":{ + "conversationId":"1526953174329", + "type":"ACTIVE", + "conversationToken":"{\"data\":{}}" + }, + "inputs":[ + { + "intent":"actions.intent.TEXT", + "rawInputs":[ + { + "inputType":"TOUCH", + "query":"Basic Card" + } + ], + "arguments":[ + { + "name":"text", + "rawText":"Basic Card", + "textValue":"Basic Card" + } + ] + } + ], + "surface":{ + "capabilities":[ + { + "name":"actions.capability.MEDIA_RESPONSE_AUDIO" + }, + { + "name":"actions.capability.WEB_BROWSER" + }, + { + "name":"actions.capability.AUDIO_OUTPUT" + }, + { + "name":"actions.capability.SCREEN_OUTPUT" + } + ] + }, + "isInSandbox":true, + "availableSurfaces":[ + { + "capabilities":[ + { + "name":"actions.capability.WEB_BROWSER" + }, + { + "name":"actions.capability.AUDIO_OUTPUT" + }, + { + "name":"actions.capability.SCREEN_OUTPUT" + } + ] + } + ] +}""" +} diff --git a/common-mock/src/test/kotlin/actions/ActionsSdkTest.kt b/common-mock/src/test/kotlin/actions/ActionsSdkTest.kt new file mode 100644 index 0000000..8b0d06d --- /dev/null +++ b/common-mock/src/test/kotlin/actions/ActionsSdkTest.kt @@ -0,0 +1,96 @@ +package actions + +import actions.expected.Serializer +import actions.expected.deserialize +import actions.framework.Headers +import actions.service.actionssdk.actionssdk +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +/** + * Test setup for Tests. + * Other solutions - 1) use official javascipt tests against the javascript version of this lib + * 2) Use Spek library once v2 & multiplatform support lands and test common module + */ +class ActionsSdkTest { + data class TestConvData(var ct: Int? = null) + data class TestUserStorage(var name: String? = null) + + @Test + fun returnEmptyConvData() { + val app = actionssdk({}) + app.intent("test") { conv -> + conv.data["ct"] = 5 + conv.ask("This is a test") + } + + val result = app(deserialize(testWelcomeRequestStr)!!) + } +} + + +val testWelcomeRequestStr = """{ +"user":{ +"userId":"APhe68EmFG8L689xcinHdNbpSadP", +"locale":"en-US", +"lastSeen":"2018-05-22T01:38:28Z", +"userStorage":"{\"data\":{}}" +}, +"conversation":{ +"conversationId":"1526953174329", +"type":"ACTIVE", +"conversationToken":"{\"data\":{}}" +}, +"inputs":[ +{ +"intent":"actions.intent.TEXT", +"rawInputs":[ +{ +"inputType":"TOUCH", +"query":"Basic Card" +} +], +"arguments":[ +{ +"name":"text", +"rawText":"Basic Card", +"textValue":"Basic Card" +} +] +} +], +"surface":{ +"capabilities":[ +{ +"name":"actions.capability.MEDIA_RESPONSE_AUDIO" +}, +{ +"name":"actions.capability.WEB_BROWSER" +}, +{ +"name":"actions.capability.AUDIO_OUTPUT" +}, +{ +"name":"actions.capability.SCREEN_OUTPUT" +} +] +}, +"isInSandbox":true, +"availableSurfaces":[ +{ +"capabilities":[ +{ +"name":"actions.capability.WEB_BROWSER" +}, +{ +"name":"actions.capability.AUDIO_OUTPUT" +}, +{ +"name":"actions.capability.SCREEN_OUTPUT" +} +] +} +] +}""" \ No newline at end of file diff --git a/common-mock/src/test/resources/conversation_sample_basic_card_request.json b/common-mock/src/test/resources/conversation_sample_basic_card_request.json new file mode 100644 index 0000000..891d561 --- /dev/null +++ b/common-mock/src/test/resources/conversation_sample_basic_card_request.json @@ -0,0 +1,63 @@ +{ + "user":{ + "userId":"APhe68EmFG8L689xcinHdNbpSadP", + "locale":"en-US", + "lastSeen":"2018-05-22T01:38:28Z", + "userStorage":"{\"data\":{}}" + }, + "conversation":{ + "conversationId":"1526953174329", + "type":"ACTIVE", + "conversationToken":"{\"data\":{}}" + }, + "inputs":[ + { + "intent":"actions.intent.TEXT", + "rawInputs":[ + { + "inputType":"TOUCH", + "query":"Basic Card" + } + ], + "arguments":[ + { + "name":"text", + "rawText":"Basic Card", + "textValue":"Basic Card" + } + ] + } + ], + "surface":{ + "capabilities":[ + { + "name":"actions.capability.MEDIA_RESPONSE_AUDIO" + }, + { + "name":"actions.capability.WEB_BROWSER" + }, + { + "name":"actions.capability.AUDIO_OUTPUT" + }, + { + "name":"actions.capability.SCREEN_OUTPUT" + } + ] + }, + "isInSandbox":true, + "availableSurfaces":[ + { + "capabilities":[ + { + "name":"actions.capability.WEB_BROWSER" + }, + { + "name":"actions.capability.AUDIO_OUTPUT" + }, + { + "name":"actions.capability.SCREEN_OUTPUT" + } + ] + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/conversation_sample_basic_card_response.json b/common-mock/src/test/resources/conversation_sample_basic_card_response.json new file mode 100644 index 0000000..ac39457 --- /dev/null +++ b/common-mock/src/test/resources/conversation_sample_basic_card_response.json @@ -0,0 +1,76 @@ +{ + "status": 200, + "headers": { + "content-type": "application/json; charset=utf-8" + }, + "body": { + "expectUserResponse": true, + "expectedInputs": [ + { + "inputPrompt": { + "richInitialPrompt": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is the first simple response for a basic card." + } + }, + { + "basicCard": { + "title": "Title: this is a title", + "subtitle": "This is a subtitle", + "formattedText": "This is a basic card. Text in a basic card can include \"quotes\" and\n most other unicode characters including emoji 📱. Basic cards also support\n some markdown formatting like *emphasis* or _italics_, **strong** or\n __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n things like line \nbreaks", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Image alternate text" + }, + "buttons": [ + { + "title": "This is a button", + "openUrlAction": { + "url": "https://assistant.google.com/" + } + } + ] + } + }, + { + "simpleResponse": { + "textToSpeech": "This is the second simple response.", + "displayText": "This is the 2nd simple response." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + } + ] + } + }, + "possibleIntents": [ + { + "intent": "actions.intent.TEXT" + } + ] + } + ], + "conversationToken": "{\"data\":{}}", + "userStorage": "{\"data\":{}}" + } +} \ No newline at end of file diff --git a/common-mock/src/test/resources/conversation_sample_welcome_request.json b/common-mock/src/test/resources/conversation_sample_welcome_request.json new file mode 100644 index 0000000..37ca887 --- /dev/null +++ b/common-mock/src/test/resources/conversation_sample_welcome_request.json @@ -0,0 +1,113 @@ +{ + "responses": [], + "expectUserResponse": true, + "digested": false, + "_responded": false, + "request": null, + "headers": null, + "sandbox": true, + "input": { + "raw": "Talk to conversation components", + "type": "KEYBOARD" + }, + "surface": { + "capabilities": { + "list": [ + { + "name": "actions.capability.AUDIO_OUTPUT" + }, + { + "name": "actions.capability.SCREEN_OUTPUT" + }, + { + "name": "actions.capability.MEDIA_RESPONSE_AUDIO" + }, + { + "name": "actions.capability.WEB_BROWSER" + } + ] + } + }, + "available": { + "surfaces": { + "list": [ + { + "capabilities": { + "list": [ + { + "name": "actions.capability.AUDIO_OUTPUT" + }, + { + "name": "actions.capability.SCREEN_OUTPUT" + }, + { + "name": "actions.capability.WEB_BROWSER" + } + ] + } + } + ], + "capabilities": { + "surfaces": [ + { + "capabilities": { + "list": [ + { + "name": "actions.capability.AUDIO_OUTPUT" + }, + { + "name": "actions.capability.SCREEN_OUTPUT" + }, + { + "name": "actions.capability.WEB_BROWSER" + } + ] + } + } + ] + } + } + }, + "user": { + "raw": { + "userId": "APhe68EmFG8L689xcinHdNbpSadP", + "locale": "en-US", + "lastSeen": "2018-05-21T15:10:52Z", + "userStorage": "{\"data\":{}}" + }, + "storage": {}, + "id": "APhe68EmFG8L689xcinHdNbpSadP", + "locale": "en-US", + "permissions": [], + "last": { + "seen": "2018-05-21T15:10:52.000Z" + }, + "name": {}, + "entitlements": [], + "access": {}, + "profile": {} + }, + "arguments": { + "parsed": { + "input": {}, + "list": [] + }, + "status": { + "input": {}, + "list": [] + }, + "raw": { + "list": [], + "input": {} + } + }, + "device": {}, + "id": "1526915488535", + "type": "NEW", + "screen": true, + "body": null, + "intent": "actions.intent.MAIN", + "data": {}, + "hasScreen": true, + "hasAudioPlayback": true +} \ No newline at end of file diff --git a/common-mock/src/test/resources/conversation_sample_welcome_response.json b/common-mock/src/test/resources/conversation_sample_welcome_response.json new file mode 100644 index 0000000..18dacfe --- /dev/null +++ b/common-mock/src/test/resources/conversation_sample_welcome_response.json @@ -0,0 +1,58 @@ +{ + "status": 200, + "headers": { + "content-type": "application/json; charset=utf-8" + }, + "body": { + "expectUserResponse": true, + "expectedInputs": [ + { + "inputPrompt": { + "richInitialPrompt": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "Hi there!", + "displayText": "Hello there!" + } + }, + { + "simpleResponse": { + "textToSpeech": "I can show you basic cards, lists and carousels as well as suggestions on your phone.", + "displayText": "I can show you basic cards, lists and carousels as well as suggestions." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + } + ] + } + }, + "possibleIntents": [ + { + "intent": "actions.intent.TEXT" + } + ] + } + ], + "conversationToken": "{\"data\":{}}", + "userStorage": "{\"data\":{}}" + } +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_basic_card_response.json b/common-mock/src/test/resources/df_sample_basic_card_response.json new file mode 100644 index 0000000..ff8cb6c --- /dev/null +++ b/common-mock/src/test/resources/df_sample_basic_card_response.json @@ -0,0 +1,77 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is the first simple response for a basic card." + } + }, + { + "basicCard": { + "title": "Title: this is a title", + "subtitle": "This is a subtitle", + "formattedText": "This is a basic card. Text in a basic card can include \"quotes\" and\n most other unicode characters including emoji 📱. Basic cards also support\n some markdown formatting like *emphasis* or _italics_, **strong** or\n __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n things like line \nbreaks", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Image alternate text" + }, + "buttons": [ + { + "title": "This is a button", + "openUrlAction": { + "url": "https://assistant.google.com/" + } + } + ] + } + }, + { + "simpleResponse": { + "textToSpeech": "This is the second simple response.", + "displayText": "This is the 2nd simple response." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1530842303910/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} diff --git a/common-mock/src/test/resources/df_sample_browse_carousel_response.json b/common-mock/src/test/resources/df_sample_browse_carousel_response.json new file mode 100644 index 0000000..16eaa79 --- /dev/null +++ b/common-mock/src/test/resources/df_sample_browse_carousel_response.json @@ -0,0 +1,82 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is an example of a \"Browse Carousel\"" + } + }, + { + "carouselBrowse": { + "items": [ + { + "title": "Title of item 1", + "openUrlAction": { + "url": "https://google.com" + }, + "description": "Description of item 1", + "footer": "Item 1 footer", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Google Assistant Bubbles" + } + }, + { + "title": "Title of item 2", + "openUrlAction": { + "url": "https://google.com" + }, + "description": "Description of item 2", + "footer": "Item 2 footer", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Google Assistant Bubbles" + } + } + ] + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1531012494339/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_carousel_response.json b/common-mock/src/test/resources/df_sample_carousel_response.json new file mode 100644 index 0000000..ed293fa --- /dev/null +++ b/common-mock/src/test/resources/df_sample_carousel_response.json @@ -0,0 +1,123 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is a simple response for a carousel." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}", + "systemIntent": { + "intent": "actions.intent.OPTION", + "data": { + "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec", + "carouselSelect": { + "items": [ + { + "optionInfo": { + "key": "title", + "synonyms": [ + "synonym of title 1", + "synonym of title 2", + "synonym of title 3" + ] + }, + "description": "This is a description of a carousel item.", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Image alternate text" + }, + "title": "Title of First Carousel Item" + }, + { + "optionInfo": { + "key": "googleHome", + "synonyms": [ + "Google Home Assistant", + "Assistant on the Google Home" + ] + }, + "description": "Google Home is a voice-activated speaker powered by the Google Assistant.", + "image": { + "url": "https://lh3.googleusercontent.com/Nu3a6F80WfixUqf_ec_vgXy_c0-0r4VLJRXjVFF_X_CIilEu8B9fT35qyTEj_PEsKw", + "accessibilityText": "Google Home" + }, + "title": "Google Home" + }, + { + "optionInfo": { + "key": "googlePixel", + "synonyms": [ + "Google Pixel XL", + "Pixel", + "Pixel XL" + ] + }, + "description": "Pixel. Phone by Google.", + "image": { + "url": "https://storage.googleapis.com/madebygoog/v1/Pixel/Pixel_ColorPicker/Pixel_Device_Angled_Black-720w.png", + "accessibilityText": "Google Pixel" + }, + "title": "Google Pixel" + }, + { + "optionInfo": { + "key": "googleAllo", + "synonyms": [ + "Allo" + ] + }, + "description": "Introducing Google Allo, a smart messaging app that helps you say more and do more.", + "image": { + "url": "https://allo.google.com/images/allo-logo.png", + "accessibilityText": "Google Allo Logo" + }, + "title": "Google Allo" + } + ] + } + } + } + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1531012494339/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_list_response.json b/common-mock/src/test/resources/df_sample_list_response.json new file mode 100644 index 0000000..2ba4ddb --- /dev/null +++ b/common-mock/src/test/resources/df_sample_list_response.json @@ -0,0 +1,124 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is a simple response for a list." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}", + "systemIntent": { + "intent": "actions.intent.OPTION", + "data": { + "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec", + "listSelect": { + "title": "List Title", + "items": [ + { + "optionInfo": { + "key": "title", + "synonyms": [ + "synonym of title 1", + "synonym of title 2", + "synonym of title 3" + ] + }, + "description": "This is a description of a list item.", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Image alternate text" + }, + "title": "Title of First List Item" + }, + { + "optionInfo": { + "key": "googleHome", + "synonyms": [ + "Google Home Assistant", + "Assistant on the Google Home" + ] + }, + "description": "Google Home is a voice-activated speaker powered by the Google Assistant.", + "image": { + "url": "https://lh3.googleusercontent.com/Nu3a6F80WfixUqf_ec_vgXy_c0-0r4VLJRXjVFF_X_CIilEu8B9fT35qyTEj_PEsKw", + "accessibilityText": "Google Home" + }, + "title": "Google Home" + }, + { + "optionInfo": { + "key": "googlePixel", + "synonyms": [ + "Google Pixel XL", + "Pixel", + "Pixel XL" + ] + }, + "description": "Pixel. Phone by Google.", + "image": { + "url": "https://storage.googleapis.com/madebygoog/v1/Pixel/Pixel_ColorPicker/Pixel_Device_Angled_Black-720w.png", + "accessibilityText": "Google Pixel" + }, + "title": "Google Pixel" + }, + { + "optionInfo": { + "key": "googleAllo", + "synonyms": [ + "Allo" + ] + }, + "description": "Introducing Google Allo, a smart messaging app that helps you say more and do more.", + "image": { + "url": "https://allo.google.com/images/allo-logo.png", + "accessibilityText": "Google Allo Logo" + }, + "title": "Google Allo" + } + ] + } + } + } + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1531012494339/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_media_response.json b/common-mock/src/test/resources/df_sample_media_response.json new file mode 100644 index 0000000..8177e10 --- /dev/null +++ b/common-mock/src/test/resources/df_sample_media_response.json @@ -0,0 +1,68 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is the first simple response for a media response" + } + }, + { + "mediaResponse": { + "mediaType": "AUDIO", + "mediaObjects": [ + { + "contentUrl": "http://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3", + "description": "A funky Jazz tune", + "icon": { + "url": "http://storage.googleapis.com/automotive-media/album_art.jpg", + "accessibilityText": "Media icon" + }, + "name": "Jazz in Paris" + } + ] + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1531012494339/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_suggestions_response.json b/common-mock/src/test/resources/df_sample_suggestions_response.json new file mode 100644 index 0000000..f364213 --- /dev/null +++ b/common-mock/src/test/resources/df_sample_suggestions_response.json @@ -0,0 +1,59 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is a simple response for suggestions." + } + } + ], + "suggestions": [ + { + "title": "Suggestion Chips" + }, + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ], + "linkOutSuggestion": { + "destinationName": "Suggestion Link", + "url": "https://assistant.google.com/" + } + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1531013042496/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_table_response.json b/common-mock/src/test/resources/df_sample_table_response.json new file mode 100644 index 0000000..e46ac7e --- /dev/null +++ b/common-mock/src/test/resources/df_sample_table_response.json @@ -0,0 +1,71 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "You can include table data like this" + } + }, + { + "tableCard": { + "rows": [ + { + "cells": [ + { + "text": "row 1 item 1" + }, + { + "text": "row 1 item 2" + }, + { + "text": "row 1 item 3" + } + ], + "dividerAfter": true + }, + { + "cells": [ + { + "text": "row 2 item 1" + }, + { + "text": "row 2 item 2" + }, + { + "text": "row 2 item 3" + } + ], + "dividerAfter": true + } + ], + "columnProperties": [ + { + "header": "header 1" + }, + { + "header": "header 2" + }, + { + "header": "header 3" + } + ] + } + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1531013042496/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_test_response.json b/common-mock/src/test/resources/df_sample_test_response.json new file mode 100644 index 0000000..62916e7 --- /dev/null +++ b/common-mock/src/test/resources/df_sample_test_response.json @@ -0,0 +1,77 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "This is the first simple response for a basic card." + } + }, + { + "basicCard": { + "title": "Title: this is a title", + "subtitle": "This is a subtitle", + "formattedText": "This is a basic card. Text in a basic card can include \"quotes\" and\n most other unicode characters including emoji 📱. Basic cards also support\n some markdown formatting like *emphasis* or _italics_, **strong** or\n __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n things like line \nbreaks", + "image": { + "url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png", + "accessibilityText": "Image alternate text" + }, + "buttons": [ + { + "title": "This is a button", + "openUrlAction": { + "url": "https://assistant.google.com/" + } + } + ] + } + }, + { + "simpleResponse": { + "textToSpeech": "This is the second simple response.", + "displayText": "This is the 2nd simple response." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1530842303910/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_sample_welcome_response.json b/common-mock/src/test/resources/df_sample_welcome_response.json new file mode 100644 index 0000000..8b48c96 --- /dev/null +++ b/common-mock/src/test/resources/df_sample_welcome_response.json @@ -0,0 +1,59 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "Hi there!", + "displayText": "Hello there!" + } + }, + { + "simpleResponse": { + "textToSpeech": "I can show you basic cards, lists and carousels as well as suggestions on your phone.", + "displayText": "I can show you basic cards, lists and carousels as well as suggestions." + } + } + ], + "suggestions": [ + { + "title": "Basic Card" + }, + { + "title": "Browse Carousel" + }, + { + "title": "Carousel" + }, + { + "title": "List" + }, + { + "title": "Media" + }, + { + "title": "Suggestions" + }, + { + "title": "Table" + }, + { + "title": "Test" + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-sample-v2/agent/sessions/1530842303910/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{}" + } + } + ] +} diff --git a/common-mock/src/test/resources/df_transaction_got_address.json b/common-mock/src/test/resources/df_transaction_got_address.json new file mode 100644 index 0000000..42d6c4a --- /dev/null +++ b/common-mock/src/test/resources/df_transaction_got_address.json @@ -0,0 +1,26 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "Great, got your address! Now say \"confirm transaction\"." + } + } + ] + }, + "userStorage": "{\"data\":{}}" + } + }, + "outputContexts": [ + { + "name": "projects/df-v2-transactions/agent/sessions/1531419984314/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{\"deliveryAddress\":{\"zipCode\":\"27525\",\"postalAddress\":{\"regionCode\":\"US\",\"recipients\":[\"Patrick Jackson\"],\"postalCode\":\"27525\",\"locality\":\"FRANKLINTON\",\"addressLines\":[\"165 SUTHERLAND DR\"],\"administrativeArea\":\"NC\"},\"phoneNumber\":\"9196076160\",\"city\":\"FRANKLINTON\",\"coordinates\":{\"latitude\":36.080033,\"longitude\":-78.507623}}}" + } + } + ] +} \ No newline at end of file diff --git a/common-mock/src/test/resources/df_transactions_confirm_transaction.json b/common-mock/src/test/resources/df_transactions_confirm_transaction.json new file mode 100644 index 0000000..db81017 --- /dev/null +++ b/common-mock/src/test/resources/df_transactions_confirm_transaction.json @@ -0,0 +1,201 @@ +{ + "payload": { + "google": { + "expectUserResponse": true, + "richResponse": { + "items": [ + { + "simpleResponse": { + "textToSpeech": "PLACEHOLDER" + } + } + ] + }, + "userStorage": "{\"data\":{}}", + "systemIntent": { + "intent": "actions.intent.TRANSACTION_DECISION", + "data": { + "@type": "type.googleapis.com/google.actions.v2.TransactionDecisionValueSpec", + "orderOptions": { + "requestDeliveryAddress": true + }, + "paymentOptions": { + "actionProvidedOptions": { + "paymentType": "PAYMENT_CARD", + "displayName": "VISA-1234" + } + }, + "proposedOrder": { + "id": "", + "cart": { + "merchant": { + "id": "book_store_1", + "name": "Book Store" + }, + "lineItems": [ + { + "name": "My Memoirs", + "id": "memoirs_1", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 990000000, + "units": 3 + }, + "type": "ACTUAL" + }, + "quantity": 1, + "subLines": [ + { + "note": "Note from the author" + } + ], + "type": "REGULAR" + }, + { + "name": "Memoirs of a person", + "id": "memoirs_2", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 990000000, + "units": 5 + }, + "type": "ACTUAL" + }, + "quantity": 1, + "subLines": [ + { + "note": "Special introduction by author" + } + ], + "type": "REGULAR" + }, + { + "name": "Their memoirs", + "id": "memoirs_3", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 750000000, + "units": 15 + }, + "type": "ACTUAL" + }, + "quantity": 1, + "subLines": [ + { + "lineItem": { + "name": "Special memoir epilogue", + "id": "memoirs_epilogue", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 990000000, + "units": 3 + }, + "type": "ACTUAL" + }, + "quantity": 1, + "type": "REGULAR" + } + } + ], + "type": "REGULAR" + }, + { + "name": "Our memoirs", + "id": "memoirs_4", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 490000000, + "units": 6 + }, + "type": "ACTUAL" + }, + "quantity": 1, + "subLines": [ + { + "note": "Special introduction by author" + } + ], + "type": "REGULAR" + } + ], + "notes": "The Memoir collection", + "otherItems": [ + { + "name": "Subtotal", + "id": "subtotal", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 220000000, + "units": 32 + }, + "type": "ESTIMATE" + }, + "type": "SUBTOTAL" + }, + { + "name": "Tax", + "id": "tax", + "price": { + "amount": { + "currencyCode": "USD", + "nanos": 780000000, + "units": 2 + }, + "type": "ESTIMATE" + }, + "type": "TAX" + } + ] + }, + "otherItems": [], + "totalPrice": { + "amount": { + "currencyCode": "USD", + "nanos": 0, + "units": 35 + }, + "type": "ESTIMATE" + }, + "extension": { + "@type": "type.googleapis.com/google.actions.v2.orders.GenericExtension", + "locations": [ + { + "type": "DELIVERY", + "location": { + "postalAddress": { + "regionCode": "US", + "recipients": [ + "Patrick Jackson" + ], + "postalCode": "27525", + "locality": "FRANKLINTON", + "addressLines": [ + "165 SUTHERLAND DR" + ], + "administrativeArea": "NC" + } + } + } + ] + } + } + } + } + } + }, + "outputContexts": [ + { + "name": "projects/df-v2-transactions/agent/sessions/1531419984314/contexts/_actions_on_google", + "lifespanCount": 99, + "parameters": { + "data": "{\"deliveryAddress\":{\"zipCode\":\"27525\",\"postalAddress\":{\"regionCode\":\"US\",\"recipients\":[\"Patrick Jackson\"],\"postalCode\":\"27525\",\"locality\":\"FRANKLINTON\",\"addressLines\":[\"165 SUTHERLAND DR\"],\"administrativeArea\":\"NC\"},\"phoneNumber\":\"9196076160\",\"city\":\"FRANKLINTON\",\"coordinates\":{\"latitude\":36.080033,\"longitude\":-78.507623}}}" + } + } + ] +} \ No newline at end of file diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 0000000..2281f43 --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'kotlin-platform-common' + +archivesBaseName = 'actions-on-google-common' + +configurations { + testArtifacts +} + +task testJar (type: Jar) { + baseName = "$project.name}-test" + from sourceSets.test.output +} + +artifacts { + testArtifacts testJar +} + +dependencies { + compile libraries.kotlin_stdlib_common + testCompile libraries.kotlin_test_annotations_common + testCompile libraries.kotlin_test_common +} + +task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.kotlin +} + +artifacts { + archives sourcesJar +} diff --git a/common/src/main/kotlin/actions/Assistant.kt b/common/src/main/kotlin/actions/Assistant.kt new file mode 100644 index 0000000..7771e68 --- /dev/null +++ b/common/src/main/kotlin/actions/Assistant.kt @@ -0,0 +1,158 @@ +package actions + +import actions.framework.* +import actions.expected.BuiltinFrameworks +import actions.expected.Serializer +import actions.expected.log +import actions.service.actionssdk.ActionsSdk +import actions.service.actionssdk.ActionsSdkIntentHandler4 +import actions.service.actionssdk.conversation.Conversation +import actions.service.dialogflow.DialogflowIntentHandler4 + + +abstract class AppHandler: BaseApp() + +interface AppOptions { + var debug: Boolean? +} + +abstract class ServiceBaseApp { + operator fun invoke(vararg args: Any) { + omni?.handle(*args) + } + + var omni: OmniHandler? = null + + abstract var handler: StandardHandler +} + +//interface Plugin, PluginResult> { +// (app: AppHandler & TService & TApp): (AppHandler & TService & TApp & TPlugin) | void +//} + +data class SerivcePlugin(val service: TService, + val pluging: TPlugin) + +data class BaseAppPlugin(val baseApp: BaseApp, + val pluging: TPlugin) + + +typealias Plugin = ((PluginApp) -> PluginResult) + +data class PluginApp(val app: AppHandler, + val service: TService, + val tApp: TApp) + +data class PluginResult(val app: AppHandler, + val service: TService, + val tApp: TApp, + val plugin: TPlugin) + +abstract class BaseApp: ServiceBaseApp() { + abstract var frameworks: BuiltinFrameworks + + + abstract fun use(plugin: Plugin): BaseAppPlugin + + abstract var debug: Boolean +} + +fun create(options: AppOptions? = null): BaseApp { +// BaseApp( +// frameworks: Object. assign ({}, builtin), +// handler: () => Promise.reject(new Error('StandardHandler not set')), +// use(plugin) { +// return plugin(this) || this +// }, +// debug:!!(options && options.debug)) + return object: BaseApp() { + override var handler: StandardHandler + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + set(value) {} + override var frameworks: BuiltinFrameworks + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + set(value) {} + + override fun use(plugin: Plugin): BaseAppPlugin { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override var debug: Boolean + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + set(value) {} + + } +} + +//equivalent of (AppHandler & TService) mixin +data class AttachedAppHandlerService(val handler: AppHandler, + val service: TService) + +data class AttachedBaseAppService(val baseApp: BaseApp, + val service: TService) + +data class AttachResult( + val baseApp: BaseApp, + val handler: StandardHandler, + val service: TService) + +abstract class AppResult: BaseApp(), StandardHandler { + +} + +fun , TUserStorage> attach( + service: ActionsSdk, + options: AppOptions? = null): AppResult { + + val baseApp = create(options) + val omni = object: OmniHandler { + override fun handle(vararg args: Any): Any { + for (framework in baseApp.frameworks) { + if(framework.check(args)) { + return framework.handle(baseApp.handler).handle(args) + } + } + return baseApp.handler.handle(args[0] as Conversation, args[1] as Headers) + } + } + + var handler = baseApp.handler + val standard = object: StandardHandler { + override fun handle(body: Any, headers: Headers, overrideHandler: DialogflowIntentHandler4?, aogOverrideHandler: ActionsSdkIntentHandler4?): StandardResponse { + log("Request", Serializer.serialize(body)) + log("Headers", Serializer.serialize(headers)) + val response = /* await */ handler.handle(body, headers) + response.headers?.get("content-type")?.add("application/json; charset=utf-8") + log("Response", Serializer.serialize(response)) + return response + } + } + baseApp.omni = omni + baseApp.handler = standard + +// var appResult = object: OmniHandler by omni, actions.BaseApp by baseApp, actions.framework.StandardHandler by standardHandler, actions.ServiceBaseApp by service { +// +// } + +// var attachedResult = AttachResult( +// baseApp = baseApp, +// service = service, +// omni = omni, +// handler = standardHandler) + + return object: AppResult() { + override var handler: StandardHandler + get() = standard + set(value) {handler = value} + + override fun use(plugin: Plugin): BaseAppPlugin { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun handle(body: Any, headers: Headers, overrideHandler: DialogflowIntentHandler4?, aogOverrideHandler: ActionsSdkIntentHandler4?): StandardResponse = standard.handle(body, headers) + + override var frameworks: BuiltinFrameworks = baseApp.frameworks + + override var debug: Boolean = baseApp.debug + } +} diff --git a/common/src/main/kotlin/actions/Common.kt b/common/src/main/kotlin/actions/Common.kt new file mode 100644 index 0000000..c7b4588 --- /dev/null +++ b/common/src/main/kotlin/actions/Common.kt @@ -0,0 +1,69 @@ +package actions + +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.SurfaceCapability + +const val name = "actions-on-google" + + +///** @hidden */ +//const values = (o: { [key: string]: T }) => Object.keys(o).map(k => o[k]) + + +/** + * All possible fields are here, though only one spec used at any given time. + * To create a ProtoAny use _data(Spec.Type) { } + */ +data class ProtoAny(var `@type`: String? = null, + var dialogSpec: DialogSpecData? = null, + var optContext: String? = null, + var permissions: MutableList? = null, + var updatePermissionValueSpec: GoogleActionsV2UpdatePermissionValueSpec? = null, + var capabilities: MutableList? = null, + var context: String? = null, + var notificationTitle: String? = null, + var arguments: MutableList? = null, + var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? = null, + var triggerContext: GoogleActionsV2TriggerContext? = null, + var addressOptions: GoogleActionsV2DeliveryAddressValueSpecAddressOptions? = null, + var checkResult: MutableList? = null, + var deliveryAddress: GoogleActionsV2Location? = null, + var order: GoogleActionsV2OrdersOrder? = null, + var presentationOptions: GoogleActionsV2OrdersPresentationOptions? = null, + var proposedOrder: GoogleActionsV2OrdersProposedOrder? = null, + var userDecision: GoogleActionsV2TransactionDecisionValueUserDecision? = null, + var orderOptions: GoogleActionsV2OrdersOrderOptions? = null, + var paymentOptions: GoogleActionsV2OrdersPaymentOptions? = null, + var listSelect: GoogleActionsV2UiElementsListSelect? = null, + var carouselSelect: GoogleActionsV2UiElementsCarouselSelect? = null, + var locations: MutableList? = null, + var time: Time? = null) { + + fun dialogSpec(init: DialogSpecData.() -> Unit) { + + } + + fun locations(vararg init: GoogleActionsV2OrdersOrderLocation.() -> Unit) { + this.locations = init.map { + val location = GoogleActionsV2OrdersOrderLocation() + location.it() + location + }.toMutableList() + } +} + +data class Time(var type: GoogleActionsV2OrdersTimeType? = null, var time_iso8601: String? = null) + +data class DialogSpecData(var `@type`: String? = null, + var permissionContext: String? = null, + var requestPrompt: String? = null, + var destinationName: String? = null, + var requestLinkReason: String? = null, + var requestDatetimeText: String? = null, + var requestDateText: String? = null, + var requestTimeText: String? = null, + var requestConfirmationText: String? = null) + + +/** @hidden */ +class ApiClientObjectMap : MutableMap by mutableMapOf() diff --git a/common/src/main/kotlin/actions/expected/BuiltInFrameworks.kt b/common/src/main/kotlin/actions/expected/BuiltInFrameworks.kt new file mode 100644 index 0000000..8158bf8 --- /dev/null +++ b/common/src/main/kotlin/actions/expected/BuiltInFrameworks.kt @@ -0,0 +1,17 @@ +package actions.expected +import actions.framework.Frameworks + + +expect class BuiltinFrameworks() :Frameworks { + /** + * Plug and play web framework support for express using body-parser + * @public + */ +// var express: Express + + /** + * Plug and play web framework support for lambda API gateway + * @public + */ +// var lambda: Lambda +} \ No newline at end of file diff --git a/common/src/main/kotlin/actions/expected/Expected.kt b/common/src/main/kotlin/actions/expected/Expected.kt new file mode 100644 index 0000000..c892d66 --- /dev/null +++ b/common/src/main/kotlin/actions/expected/Expected.kt @@ -0,0 +1,64 @@ +package actions.expected + +import actions.service.actionssdk.api.GoogleActionsV2Location + +/* + Classes that must have platform specific implementations. May need refactoring into separate files + */ + +expect class Date(timeStamp: String? = null) { + fun toISOString(): String? + +} + + +data class TokenPayload(val accessToken: String? = null, + val email: String? = null) + +data class LoginTicket(var tokenPayload: TokenPayload? = null) { + fun getPayload(): TokenPayload? { + return null + } +} + +data class IdToken(var idToken: String? = null, + var audience: String? = null) + +expect class OAuth2Client(clientId: String) { + fun verifyIdToken(idToken: IdToken): LoginTicket +} + + +expect fun deserialize(json: String?): T? + + +expect fun log(message: String, vararg optionalParameters: Any?) + +fun info(message: String) { + +} + +fun warn(message: String) { + +} + +fun error(message: String, exception: Exception) { +} + + +data class ConversationTokenData(var data: Any? = null) + + +expect object Serializer { + fun stringifyConversationToken(data: Any?): ConversationTokenData + fun serialize(any: Any?): String? + fun deserializeMap(json: String): MutableMap +} + + +expect val MutableMap.deliveryAddress: GoogleActionsV2Location? +val Test.delivery: GoogleActionsV2Location? + get() = null + +typealias Test = MutableMap + diff --git a/common/src/main/kotlin/actions/expected/GoogleAuthLib.kt b/common/src/main/kotlin/actions/expected/GoogleAuthLib.kt new file mode 100644 index 0000000..b2c9baa --- /dev/null +++ b/common/src/main/kotlin/actions/expected/GoogleAuthLib.kt @@ -0,0 +1,9 @@ +package actions.expected + + +/** + * + */ +expect class GoogleAuthLib { + fun asyncVerify() +} diff --git a/common/src/main/kotlin/actions/framework/Framework.kt b/common/src/main/kotlin/actions/framework/Framework.kt new file mode 100644 index 0000000..5001e69 --- /dev/null +++ b/common/src/main/kotlin/actions/framework/Framework.kt @@ -0,0 +1,54 @@ +package actions.framework + +import actions.service.actionssdk.ActionsSdkIntentHandler4 +import actions.service.dialogflow.DialogflowIntentHandler4 + +//import kotlinx.coroutines.experimental.Deferred + + +abstract class Frameworks: MutableList> by mutableListOf() { +} + +interface OmniHandler { + fun handle(vararg args: Any): Any +} + +interface Framework { + fun handle(base: StandardHandler): OmniHandler + + // tslint:disable-next-line:no-any detect if it is the correct framework from any parameter type + fun check(vararg args: Any): Boolean +} + +//typealias OmniHandler = StandardHandler/*, ExpressHandler, LambdaHandler*/ //{ + // tslint:disable-next-line:no-any allow any inputs and outputs depending on framework +// (...args: any[]): any +//} + + +///** @hidden */ +//val builtin: BuiltinFrameworks = { +// express, +// lambda, +//} + +data class StandardResponse( + var status: Int? = null, + var body: JsonObject? = null, + var headers: Headers? = null) + +typealias Headers = MutableMap> +//interface Headers { +// /** @public */ +// [header: string]: string | string[] | undefined +//} + +//typealias StandardHandler = (body: JsonObject, headers: Headers) -> StandardResponse //TODO Promise or deferred + +interface StandardHandler { + fun handle(body: Any, headers: Headers, + overrideHandler: DialogflowIntentHandler4? = null, + aogOverrideHandler: ActionsSdkIntentHandler4? = null): StandardResponse //TODO Promise or deferred +} + +typealias JsonObject = Any diff --git a/common/src/main/kotlin/actions/service/actionssdk/ActionsSdk.kt b/common/src/main/kotlin/actions/service/actionssdk/ActionsSdk.kt new file mode 100644 index 0000000..d635805 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/ActionsSdk.kt @@ -0,0 +1,451 @@ +package actions.service.actionssdk + +import actions.* +import actions.expected.* +import actions.framework.* +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import actions.service.actionssdk.api.GoogleActionsV2Argument +import actions.service.actionssdk.api.GoogleRpcStatus +import actions.service.actionssdk.conversation.* +import actions.service.dialogflow.DialogflowIntentHandler4 + +typealias ActionsSdkIntentHandler1 = (conv: ActionsSdkConversation) -> Any +typealias ActionsSdkIntentHandler2 = (conv: ActionsSdkConversation, argument: Any) -> Any +typealias ActionsSdkIntentHandler3 = (conv: ActionsSdkConversation, argument: Any, arg: GoogleActionsV2Argument?) -> Any +typealias ActionsSdkIntentHandler4 = (conv: ActionsSdkConversation, argument: Any, arg: GoogleActionsV2Argument?, status: GoogleRpcStatus?) -> Any + +class ActionSdkIntentHandlers : MutableMap?> by mutableMapOf() + +data class ActionsSdkHandlers( + var intents: ActionSdkIntentHandlers = ActionSdkIntentHandlers(), + var catcher: ExceptionHandler>? = null, //TODO provide defaults for these nulls + var fallback: ActionsSdkIntentHandler4? = null +) + +interface ActionsSdkMiddleware +//< +// TConversationPlugin: ActionsSdkConversation<*, *>> { +// (conv: ActionsSdkConversation<*, *>): (ActionsSdkConversation<*,*> & TConversationPlugin) | void +//} + +/** @public */ +abstract class ActionsSdkApp : ConversationApp() { + /** @hidden */ + abstract var _handlers: ActionsSdkHandlers + + /** + * Sets the IntentHandler to be executed when the fulfillment is called + * with a given Actions SDK intent. + * + * @param intent The Actions SDK intent to match. + * When given an array, sets the IntentHandler for any intent in the array. + * @param handler The IntentHandler to be executed when the intent is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent. + * @public + */ + abstract fun intent(intents: MutableList, handler: ActionsSdkIntentHandler1 /*| Intent,*/): ActionsSdkApp + abstract fun intent(intents: MutableList, handler: ActionsSdkIntentHandler2 /*| Intent,*/): ActionsSdkApp + abstract fun intent(intents: MutableList, handler: ActionsSdkIntentHandler3 /*| Intent,*/): ActionsSdkApp + abstract fun intent(intents: MutableList, handler: ActionsSdkIntentHandler4 /*| Intent,*/): ActionsSdkApp + + /** + * Sets the IntentHandler to be executed when the fulfillment is called + * with a given Actions SDK intent. + * + * @param intent The Actions SDK intent to match. + * When given an array, sets the IntentHandler for any intent in the array. + * @param handler The IntentHandler to be executed when the intent is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent. + * @public + */ + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler1 /*| string,*/): ActionsSdkApp + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler2 /*| string,*/): ActionsSdkApp + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler3 /*| string,*/): ActionsSdkApp + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler4 /*| string,*/): ActionsSdkApp + + /** @public */ + abstract fun catch(catcher: ExceptionHandler>): ActionsSdkApp + + /** @public */ + abstract fun fallback(handler: ActionsSdkIntentHandler3 /*| string,*/): ActionsSdkApp + + /** @hidden */ + abstract var _middlewares: MutableList + + /** @public */ + abstract fun > middleware(middleware: ActionsSdkMiddleware): ActionsSdkApp + + /** @public */ + abstract var verification: ActionsSdkVerification? //| string +} + +abstract class BaseService : ConversationApp() { + /** @hidden */ + abstract var _handlers: THandler// + + /** + * Sets the IntentHandler to be executed when the fulfillment is called + * with a given Actions SDK intent. + * + * @param intent The Actions SDK intent to match. + * When given an array, sets the IntentHandler for any intent in the array. + * @param handler The IntentHandler to be executed when the intent is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent. + * @public + */ + abstract fun intent(intents: MutableList, handler: TIntentHandler): ActionsSdkApp + + /** + * Sets the IntentHandler to be executed when the fulfillment is called + * with a given Actions SDK intent. + * + * @param intent The Actions SDK intent to match. + * When given an array, sets the IntentHandler for any intent in the array. + * @param handler The IntentHandler to be executed when the intent is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent. + * @public + */ + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler1): ActionsSdkApp + + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler2): ActionsSdkApp + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler3): ActionsSdkApp + abstract fun intent(vararg intents: String, handler: ActionsSdkIntentHandler4): ActionsSdkApp + + /** @public */ + abstract fun catch(catcher: ExceptionHandler>): ActionsSdkApp + + /** @public */ + abstract fun fallback(handler: ActionsSdkIntentHandler3 ): ActionsSdkApp + + /** @hidden */ + abstract var _middlewares: MutableList + + /** @public */ + abstract fun > middleware(middleware: ActionsSdkMiddleware): ActionsSdkApp + + /** @public */ + abstract var verification: ActionsSdkVerification? //| string +} + +interface ActionsSdkVerification { + /** + * Google Cloud Project ID for the Assistant app. + * @public + */ + var project: String + + /** + * Custom status code to return on verification error. + * @public + */ + var status: Int? + + /** + * Custom error message as a string or a function that returns a string + * given the original error message set by the library. + * + * The message will get sent back in the JSON top level `error` property. + * @public + */ + var error: String //| ((error: string) => string) +} + +data class ActionsSdkOptions( + /** + * Validates whether request is from Google through signature verification. + * Uses Google-Auth-Library to verify authorization token against given Google Cloud Project ID. + * Auth token is given in request header with key, "authorization". + * + * HTTP Code 403 will be thrown by default on verification error. + * + * @example + * ```javascript + * + * const app = actionssdk({ verification: 'nodejs-cloud-test-project-1234' }) + * ``` + * + * @public + */ + var verification: ActionsSdkVerification? = null, + override var init: (() -> ConversationOptionsInit)? = null, + override var clientId: String? = null, + override var debug: Boolean? = null +) : ConversationAppOptions + +/** + * This is the function that creates the app instance which on new requests, + * creates a way to interact with the conversation API directly from Assistant, + * providing implementation for all the methods available in the API. + * + * Only supports Actions SDK v2. + * + * @example + * ```javascript + * + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask('How are you?') + * }) + * ``` + * + * @public + */ + +fun actionssdk(options: ActionsSdkOptions? = null): ActionsSdk { + return ActionsSdk(options) +} + +fun actionssdk(init: (ActionsSdkOptions.() -> Unit)? = null): ActionsSdk { + val options = ActionsSdkOptions() + options.init?.invoke() + return ActionsSdk(options) +} + +class ActionsSdk(options: ActionsSdkOptions? = null) : ActionsSdkApp() { + + + override lateinit var frameworks: BuiltinFrameworks + + override fun use(plugin: Plugin): BaseAppPlugin { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override var debug: Boolean = false + + + override var _handlers: ActionsSdkHandlers = ActionsSdkHandlers( + intents = ActionSdkIntentHandlers(), + catcher = { conv, e -> throw e } + ) + + override fun intent(intents: MutableList, handler: ActionsSdkIntentHandler1): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent.value] = { conv, status, g, arg -> handler(conv) } + } + return this + } + + override fun intent(intents: MutableList, handler: ActionsSdkIntentHandler2): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent.value] = { conv, status, g, arg -> handler(conv, status) } + } + return this + } + + override fun intent(intents: MutableList, handler: ActionsSdkIntentHandler3): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent.value] = { conv, status, g, arg -> handler(conv, status, g) } + } + return this + } + + override fun intent(intents: MutableList, handler: ActionsSdkIntentHandler4): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent.value] = { conv, status, g, arg -> handler(conv, status, g, arg) } + } + return this + } + + override fun intent(vararg intents: String, handler: ActionsSdkIntentHandler1): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv) } + } + return this + } + + override fun intent(vararg intents: String, handler: ActionsSdkIntentHandler2): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status) } + } + return this + } + + override fun intent(vararg intents: String, handler: ActionsSdkIntentHandler3): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status, g) } + } + return this + } + + override fun intent(vararg intents: String, handler: ActionsSdkIntentHandler4): ActionsSdkApp { + for (intent in intents) { + this._handlers.intents[intent] = handler + } + return this + } + + override fun catch(catcher: ExceptionHandler>): ActionsSdkApp { + this._handlers.catcher = catcher + return this + } + + override fun fallback(handler: ActionsSdkIntentHandler3): ActionsSdkApp { + this._handlers.fallback = { conv, status, g, arg -> handler.invoke(conv, status, g) } + return this + } + + override var _middlewares: MutableList = mutableListOf() + + override fun > middleware(middleware: ActionsSdkMiddleware): ActionsSdkApp { + this._middlewares.push(middleware) + return this + } + + override var verification: ActionsSdkVerification? = options?.verification + + override var init: (() -> ConversationOptionsInit)? = options?.init + + override var auth: OAuth2Config? = if (options?.clientId != null) OAuth2Config(client = OAuth2ConfigClient(id = options.clientId)) else null + + override var _client: OAuth2Client? = if (options?.verification != null || options?.clientId != null) + OAuth2Client(options.clientId!!) else null + + override var handler: StandardHandler = object : StandardHandler { + override fun handle(body: Any, headers: Headers, overrideHandler: DialogflowIntentHandler4?, aogOverrideHandler: ActionsSdkIntentHandler4?): StandardResponse { + val convBody = body as GoogleActionsV2AppRequest + val debug: Boolean = options?.debug ?: false + val init = init + val verification = verification + if (verification != null) { + val project = verification.status + val status = 403 + val error = verification.error + //} = typeof verification === 'string' ? { project: verification } : verification + val token = headers["authorization"]?.firstOrNull() + try { + _client!!.verifyIdToken(IdToken( + idToken = token, + audience = project.toString()) + ) + } catch (e: Exception) { + return StandardResponse( + status = status, + body = WebhookError( + error = error) //typeof error === 'string' ? error : + //error(`ID token verification failed: ${e.stack || e.message || e}`), + ) + } + } + + val conv = ActionsSdkConversation(ActionsSdkConversationOptions( + body = convBody, + headers = headers, + init = init?.invoke(), //init && init (), + debug = debug)) + + if (conv.user.profile?.token != null) { + /*await */ conv.user._verifyProfile(_client!!, auth!!.client?.id!!) + } + for (middleware in _middlewares) { +// conv = (middleware(conv) as ActionsSdkConversation) //| void) || conv + } +// val log = debug ? common.info : common.debug +// log("Conversation", stringify(conv, { +// request: null, +// headers: null, +// body: null, +// })) + val intent = conv.intent + val traversedActionsHandlers: TraversedActionsHandlers = TraversedActionsHandlers() + var handler = aogOverrideHandler ?: _handlers.intents[intent] +// while (typeof handler !== 'function') { + while (false) { + //TODO why is this loop here? handle intents mapped to a string? + if (handler == null) { + if (_handlers.fallback == null) { + throw Error("Actions SDK IntentHandler not found for intent: $intent") + } + handler = _handlers.fallback + break + } + if (traversedActionsHandlers[handler] == true) { + throw Error("Circular intent map detected: $handler traversed twice") + } + traversedActionsHandlers[handler] = true +// handler = _handlers.intents[handler] + } + try { + /* await */ handler?.invoke( + conv, + conv.input.raw ?: "", + conv.arguments.raw?.input?.values?.firstOrNull(), +// conv.arguments.parsed?.list?.firstOrNull(), + conv.arguments.status?.list?.firstOrNull() + ) + } catch (e: Exception) { + //TODO provide default catcher + /*await */ _handlers.catcher?.invoke(conv, e) + + } + return StandardResponse( + status = 200, + headers = mutableMapOf("Content-type" to mutableListOf("application/json; charset=UTF-8")), + body = conv.serialize() + ) + } + } + + init { + frameworks = BuiltinFrameworks() +// val baseApp = create(options) + omni = object : OmniHandler { + override fun handle(vararg args: Any): Any { + log("Args in omniHandler: ${args.map { it.toString() }.joinToString { it }}") + for (framework in frameworks) { + if (framework.check(*args)) { + return framework.handle(handler).handle(*args) + } + } + return handler.handle(args[0] as GoogleActionsV2AppRequest, args[1] as Headers) + } + } + +// var handler = baseApp.handler + val standard = object : StandardHandler { + override fun handle(body: Any, headers: Headers, overrideHandler: DialogflowIntentHandler4?, aogOverrideHandler: ActionsSdkIntentHandler4?): StandardResponse { + val body = body as GoogleActionsV2AppRequest + log("Request", Serializer.serialize(body)) + log("Headers", Serializer.serialize(headers)) + val response = /* await */ handler.handle(body, headers) + response.headers?.get("content-type")?.add("application/json; charset=utf-8") + log("Response", Serializer.serialize(response)) + return response + } + } +// baseApp.omni = omni +// baseApp.handler = standard + +// var appResult = object: OmniHandler by omni, actions.BaseApp by baseApp, actions.framework.StandardHandler by standardHandler, actions.ServiceBaseApp by service { +// +// } + +// var attachedResult = AttachResult( +// baseApp = baseApp, +// service = service, +// omni = omni, +// handler = standardHandler) + +// return object: AppResult() { +// handler = standard + + fun use(plugin: Plugin): BaseAppPlugin { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +// override fun handle(body: JsonObject, headers: Headers): StandardResponse = standard.handle(body, headers) +// +// override var frameworks: BuiltinFrameworks = baseApp.frameworks +// +// override var debug: Boolean = baseApp.debug +// } + } + +} + +data class WebhookError(var error: String? = null) + diff --git a/common/src/main/kotlin/actions/service/actionssdk/CommonExtensions.kt b/common/src/main/kotlin/actions/service/actionssdk/CommonExtensions.kt new file mode 100644 index 0000000..4db66ff --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/CommonExtensions.kt @@ -0,0 +1,28 @@ +package actions.service.actionssdk + +import actions.service.actionssdk.conversation.response.GoogleActionsV2RichResponseItem + +fun MutableList.push(item: T): Unit = + if (size == 0) { + add(item) + Unit + } else { + add(0, item) + } + +fun MutableList.push(vararg items: T): Unit = + items.forEach { + if (size == 0) { + add(it) + Unit + } else { + add(0, it) + } + } + +fun MutableList.push(init: GoogleActionsV2RichResponseItem.() -> Unit): Unit { + val item = GoogleActionsV2RichResponseItem() + item.init() + push(item) +} + diff --git a/common/src/main/kotlin/actions/service/actionssdk/Conv.kt b/common/src/main/kotlin/actions/service/actionssdk/Conv.kt new file mode 100644 index 0000000..51b763c --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/Conv.kt @@ -0,0 +1,111 @@ +package actions.service.actionssdk + +import actions.expected.Serializer +import actions.expected.deserialize +import actions.framework.Headers +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.* + + +data class ActionsSdkConversationOptions< + TUserStorage>(override var headers: Headers?, + var body: GoogleActionsV2AppRequest? = null, + override var init: ConversationOptionsInit? = null, + override var debug: Boolean? = null) : ConversationBaseOptions + + + +class ActionsSdkConversation(options: ActionsSdkConversationOptions) : + Conversation(options = ConversationOptions(request = options.body, headers = options.headers)) { + + var body: GoogleActionsV2AppRequest? + + /** + * Get the current Actions SDK intent. + * + * @example + * ```javascript + * + * app.intent('actions.intent.MAIN', conv => { + * const intent = conv.intent // will be 'actions.intent.MAIN' + * }) + * ``` + * + * @public + */ + var intent: String + + /** + * The session data in JSON format. + * Stored using conversationToken. + * + * @example + * ```javascript + * + * app.intent('actions.intent.MAIN', conv => { + * conv.data.someProperty = 'someValue' + * }) + * ``` + * + * @public + */ + var data: MutableMap = mutableMapOf() + + /** @public */ + init { + this.body = options?.body + + val body = options.body + val init = options + + val inputs = body?.inputs ?: mutableListOf() + val firstInput = inputs.firstOrNull() + + val intent = firstInput?.intent ?: "" + val conversation = body?.conversation + val conversationToken = conversation?.conversationToken + + this.intent = intent + + this.data = if (conversationToken != null) { + deserialize>(conversationToken) ?: mutableMapOf() + } else { + mutableMapOf() +// TODO("Find way to do this in kotlin, or delegate to platform") +// ((init && init.data) || {}) + } + } + + fun serialize(): GoogleActionsV2AppResponse { + if (this._raw != null) { + TODO("Find way to serialize. _raw as a string or JsonObject?") + return this._raw as GoogleActionsV2AppResponse //TODO REMOVE - ONLY HERE TO COMPILE + } + val response = this.response() + + val richResponse = response.richResponse + val expectUserResponse = response.expectUserResponse + val userStorage = response.userStorage + val expectedIntent = response.expectedIntent + + val inputPrompt = GoogleActionsV2InputPrompt(richInitialPrompt = richResponse, + noInputPrompts = response.noInputPrompts) + + val possibleIntents = if (expectedIntent != null) { + mutableListOf(expectedIntent) + } else { + mutableListOf(GoogleActionsV2ExpectedIntentData(intent = IntentEnum.TEXT.value)) + } + val expectedInput = GoogleActionsV2ExpectedInput( + inputPrompt = inputPrompt, + possibleIntents = possibleIntents) + val conversationToken = Serializer.stringifyConversationToken(this.data) + + return GoogleActionsV2AppResponse( + expectUserResponse = expectUserResponse, + expectedInputs = if (expectUserResponse == true) mutableListOf(expectedInput) else null, + finalResponse = if (expectUserResponse == true) null else GoogleActionsV2FinalResponse(richResponse = richResponse), + conversationToken = Serializer.serialize(conversationToken), + userStorage = userStorage) + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/api/V2.kt b/common/src/main/kotlin/actions/service/actionssdk/api/V2.kt new file mode 100644 index 0000000..6f558ac --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/api/V2.kt @@ -0,0 +1,2315 @@ +package actions.service.actionssdk.api + +import actions.ApiClientObjectMap +import actions.ProtoAny +import actions.service.actionssdk.conversation.response.GoogleActionsV2RichResponseItem +import actions.service.actionssdk.conversation.response.Image +import actions.service.actionssdk.conversation.response.OrderUpdate +import actions.service.actionssdk.conversation.response.SimpleResponse +import actions.service.actionssdk.conversation.response.card.Button + + +enum class GoogleActionsV2ConversationType { + TYPE_UNSPECIFIED, + NEW, + ACTIVE +} + + +enum class GoogleActionsV2DeliveryAddressValueUserDecision { UNKNOWN_USER_DECISION, ACCEPTED, REJECTED } + +enum class GoogleActionsV2EntitlementSkuType { TYPE_UNSPECIFIED, IN_APP, SUBSCRIPTION, APP } + +enum class GoogleActionsV2MediaResponseMediaType { MEDIA_TYPE_UNSPECIFIED, AUDIO } + +enum class GoogleActionsV2MediaStatusStatus { STATUS_UNSPECIFIED, FINISHED } + +enum class GoogleActionsV2NewSurfaceValueStatus { NEW_SURFACE_STATUS_UNSPECIFIED, CANCELLED, OK } + +enum class GoogleActionsV2OrdersActionProvidedPaymentOptionsPaymentType { PAYMENT_TYPE_UNSPECIFIED, PAYMENT_CARD, BANK, LOYALTY_PROGRAM, ON_FULFILLMENT, GIFT_CARD } + +enum class GoogleActionsV2OrdersCustomerInfoOptionsCustomerInfoProperties { CUSTOMER_INFO_PROPERTY_UNSPECIFIED, EMAIL } + +enum class GoogleActionsV2OrdersGoogleProvidedPaymentOptionsSupportedCardNetworks { UNSPECIFIED_CARD_NETWORK, AMEX, DISCOVER, MASTERCARD, VISA, JCB } + +enum class GoogleActionsV2OrdersLineItemType { UNSPECIFIED, REGULAR, TAX, DISCOUNT, GRATUITY, DELIVERY, SUBTOTAL, FEE } + +enum class GoogleActionsV2OrdersOrderLocationType { UNKNOWN, DELIVERY, BUSINESS, ORIGIN, DESTINATION, PICK_UP } + +enum class GoogleActionsV2OrdersOrderUpdateActionType { UNKNOWN, VIEW_DETAILS, MODIFY, CANCEL, RETURN, EXCHANGE, EMAIL, CALL, REORDER, REVIEW, CUSTOMER_SERVICE, FIX_ISSUE } + +enum class GoogleActionsV2OrdersPaymentInfoPaymentType { PAYMENT_TYPE_UNSPECIFIED, PAYMENT_CARD, BANK, LOYALTY_PROGRAM, ON_FULFILLMENT, GIFT_CARD } + +enum class GoogleActionsV2OrdersPaymentMethodTokenizationParametersTokenizationType { UNSPECIFIED_TOKENIZATION_TYPE, PAYMENT_GATEWAY, DIRECT } + +enum class GoogleActionsV2OrdersPriceType { UNKNOWN, ESTIMATE, ACTUAL } + +enum class GoogleActionsV2OrdersRejectionInfoType { UNKNOWN, PAYMENT_DECLINED, INELIGIBLE, PROMO_NOT_APPLICABLE, UNAVAILABLE_SLOT } + +enum class GoogleActionsV2OrdersTimeType { UNKNOWN, DELIVERY_DATE, ETA, RESERVATION_SLOT } + +enum class GoogleActionsV2PermissionValueSpecPermissions { UNSPECIFIED_PERMISSION, NAME, DEVICE_PRECISE_LOCATION, DEVICE_COARSE_LOCATION, UPDATE } + +enum class GoogleActionsV2RawInputInputType { UNSPECIFIED_INPUT_TYPE, TOUCH, VOICE, KEYBOARD } + +enum class GoogleActionsV2RegisterUpdateValueStatus { REGISTER_UPDATE_STATUS_UNSPECIFIED, OK, CANCELLED } + +enum class GoogleActionsV2SignInValueStatus { SIGN_IN_STATUS_UNSPECIFIED, OK, CANCELLED, ERROR } + +enum class GoogleActionsV2TransactionDecisionValueUserDecision { UNKNOWN_USER_DECISION, ORDER_ACCEPTED, ORDER_REJECTED, DELIVERY_ADDRESS_UPDATED, CART_CHANGE_REQUESTED } + +enum class GoogleActionsV2TransactionRequirementsCheckResultResultType { RESULT_TYPE_UNSPECIFIED, OK, USER_ACTION_REQUIRED, ASSISTANT_SURFACE_NOT_SUPPORTED, REGION_NOT_SUPPORTED } + +enum class GoogleActionsV2TriggerContextTimeContextFrequency { FREQUENCY_UNSPECIFIED, DAILY, ROUTINES } + +enum class GoogleActionsV2UiElementsBasicCardImageDisplayOptions { DEFAULT, WHITE, CROPPED } + +enum class GoogleActionsV2UiElementsCarouselBrowseImageDisplayOptions { DEFAULT, WHITE, CROPPED } + +enum class GoogleActionsV2UiElementsCarouselSelectImageDisplayOptions { DEFAULT, WHITE, CROPPED } + +enum class GoogleActionsV2UiElementsOpenUrlActionUrlTypeHint { URL_TYPE_HINT_UNSPECIFIED, AMP_CONTENT } + +enum class GoogleActionsV2UiElementsTableCardColumnPropertiesHorizontalAlignment { LEADING, CENTER, TRAILING } + +enum class GoogleActionsV2UserPermissions { UNSPECIFIED_PERMISSION, NAME, DEVICE_PRECISE_LOCATION, DEVICE_COARSE_LOCATION, UPDATE } + + +open class GoogleActionsV2AppRequest { + /** + * Surfaces available for cross surface handoff. + */ + var availableSurfaces: MutableList? = null + /** + * Holds session data like the conversation ID and conversation token. + */ + var conversation: GoogleActionsV2Conversation? = null + /** + * Information about the device the user is using to interact with the app. + */ + var device: GoogleActionsV2Device? = null + /** + * List of inputs corresponding to the expected inputs specified by the app. + * For the initial conversation trigger, the input contains information on + * how the user triggered the conversation. + */ + var inputs: MutableList? = null + /** + * Indicates whether the request should be handled in sandbox mode. + */ + var isInSandbox: Boolean? = null + /** + * Information about the surface the user is interacting with, e.g. whether it + * can output audio or has a screen. + */ + var surface: GoogleActionsV2Surface? = null + /** + * User who initiated the conversation. + */ + var user: GoogleActionsV2User? = null + + var sender: Sender? = null +} + +data class Sender(val id: String? = null) + +data class GoogleActionsV2AppResponse( + /** + * An opaque token that is recirculated to the app every conversation + * turn. + */ + var conversationToken: String? = null, + /** + * Custom Push Message allows developers to send structured data to Google + * for interactions on the Assistant. + */ + var customPushMessage: GoogleActionsV2CustomPushMessage? = null, + /** + * Indicates whether the app is expecting a user response. This is true when + * the conversation is ongoing, false when the conversation is done. + */ + var expectUserResponse: Boolean? = null, + /** + * List of inputs the app expects, each input can be a built-in intent, or an + * input taking list of possible intents. Only one input is supported for now. + */ + var expectedInputs: MutableList? = null, + /** + * Final response when the app does not expect user's input. + */ + var finalResponse: GoogleActionsV2FinalResponse? = null, + /** + * Indicates whether the response should be handled in sandbox mode. This + * bit is needed to push structured data to Google in sandbox mode. + */ + var isInSandbox: Boolean? = null, + /** + * Whether to clear the persisted user_storage. If set to true, then in the + * next interaction with the user, the user_storage field will be empty. + */ + var resetUserStorage: Boolean? = null, + /** + * An opaque token controlled by the application that is persisted across + * conversations for a particular user. If empty or unspecified, the + * existing persisted token will be unchanged. + * The maximum size of the string is 10k bytes. + * If multiple dialogs are occurring concurrently for the same user, then + * updates to this token can overwrite each other unexpectedly. + */ + var userStorage: String? = null) + +/** + * Hold data for TransactionCheckComplete, SignInStatus, TransactionDecision, NewSurfaceResult + */ +data class ArgumentExtension( + val `@type`: String = "", +// val resultType: TransactionValues.ResultType = TransactionValues.ResultType.UNSPECIFIED, + val resultType: String? = null, + var userDecision: String = "", + var status: String = "", + var location: GoogleActionsV2Location? = null, + val order: OrderUpdate? = null) + + +data class GoogleActionsV2Argument( + /** + * Specified when query pattern includes a `$org.schema.type.YesNo` type or + * expected input has a built-in intent: `actions.intent.CONFIRMATION`. + * NOTE: if the boolean value is missing, it represents `false`. + */ + var boolValue: Boolean? = null, + /** + * Specified for the built-in intent: `actions.intent.DATETIME`. + */ + var datetimeValue: GoogleActionsV2DateTime? = null, + /** + * Extension whose type depends on the argument. + * For example, if the argument name is `SIGN_IN` for the + * `actions.intent.SIGN_IN` intent, then this extension will + * contain a SignInValue value. + */ +// var extension: ApiClientObjectMap? = null, + var extension: ArgumentExtension? = null, + /** + * Specified for built-in intent: \"actions.intent.NUMBER\" + */ + var floatValue: Float? = null, + /** + * Specified when query pattern includes a $org.schema.type.Number type or + * expected input has a built-in intent: \"assistant.intent.action.NUMBER\". + */ + var intValue: String? = null, + /** + * Name of the argument being provided for the input. + */ + var name: String? = null, + /** + * Specified when query pattern includes a $org.schema.type.Location type or + * expected input has a built-in intent: \"actions.intent.PLACE\". + */ + var placeValue: GoogleActionsV2Location? = null, + /** + * The raw text, typed or spoken, that provided the value for the argument. + */ + var rawText: String? = null, + /** + * Specified when an error was encountered while computing the argument. For + * example, the built-in intent \"actions.intent.PLACE\" can return an error + * status if the user denied the permission to access their device location. + */ + var status: GoogleRpcStatus? = null, + /** + * Specified when Google needs to pass data value in JSON format. + */ + var structuredValue: ApiClientObjectMap? = null, + /** + * Specified when query pattern includes a `$org.schema.type.Text` type or + * expected input has a built-in intent: `actions.intent.TEXT`, or + * `actions.intent.OPTION`. Note that for the `OPTION` intent, we set the + * `text_value` as option key, the `raw_text` above will indicate the raw + * span in user's query. + */ + var textValue: String? = null, + + /**** ADDED FOR KOTLIN ***/ + var resultType: String? = null, + + var userDecision: String? = null, + + var location: GoogleActionsV2Location? = null, + + var order: GoogleActionsV2OrdersOrder? = null +) + +data class GoogleActionsV2Capability( + /** + * The name of the capability, e.g. `actions.capability.AUDIO_OUTPUT` + */ + var name: String? = null +) + +data class GoogleActionsV2ConfirmationValueSpec( + /** + * Configures dialog that asks for confirmation. + */ + var dialogSpec: GoogleActionsV2ConfirmationValueSpecConfirmationDialogSpec? = null +) + +data class GoogleActionsV2ConfirmationValueSpecConfirmationDialogSpec( + /** + * This is the question asked by confirmation sub-dialog. For example \"Are + * you sure about that?\" + */ + var requestConfirmationText: String? = null +) + +data class GoogleActionsV2Conversation( + /** + * Unique ID for the multi-turn conversation. It's assigned for the first + * turn. After that it remains the same for subsequent conversation turns + * until the conversation is terminated. + */ + var conversationId: String? = null, + /** + * Opaque token specified by the app in the last conversation turn. It can + * be used by an app to track the conversation or to store conversation + * related data. + */ + var conversationToken: String? = null, + /** + * Type indicates the state of the conversation in its life cycle. + */ + var type: GoogleActionsV2ConversationType? = null +) + +data class GoogleActionsV2CustomPushMessage( + /** + * An order update updating orders placed through transaction APIs. + */ + var orderUpdate: GoogleActionsV2OrdersOrderUpdate? = null, + /** + * The specified target for the push request. + */ + var target: GoogleActionsV2CustomPushMessageTarget? = null, + /** + * If specified, displays a notification to the user with specified title + * and text. + */ + var userNotification: GoogleActionsV2UserNotification? = null +) + +data class GoogleActionsV2CustomPushMessageTarget( + /** + * The argument to target for an intent. For V1, only one Argument is + * supported. + */ + var argument: GoogleActionsV2Argument? = null, + /** + * The intent to target. + */ + var intent: String? = null, + /** + * The locale to target. Follows IETF BCP-47 language code. + * Can be used by a multi-lingual app to target a user on a specified + * localized app. If not specified, it will default to en-US. + */ + var locale: String? = null, + /** + * The user to target. + */ + var userId: String? = null +) + +data class GoogleActionsV2DateTime( + /** + * Date value + */ + var date: GoogleTypeDate? = null, + /** + * Time value + */ + var time: GoogleTypeTimeOfDay? = null +) + +data class GoogleActionsV2DateTimeValueSpec( + /** + * Control datetime prompts. + */ + var dialogSpec: GoogleActionsV2DateTimeValueSpecDateTimeDialogSpec? = null +) + +data class GoogleActionsV2DateTimeValueSpecDateTimeDialogSpec( + /** + * This is used to create prompt to ask for date only. + * For example: What date are you looking for? + */ + var requestDateText: String? = null, + /** + * This is used to create initial prompt by datetime sub-dialog. + * Example question: \"What date and time do you want?\" + */ + var requestDatetimeText: String? = null, + /** + * This is used to create prompt to ask for time only. + * For example: What time? + */ + var requestTimeText: String? = null +) + +data class GoogleActionsV2DeliveryAddressValue( + /** + * Contains delivery address only when user agrees to share the delivery + * address. + */ + var location: GoogleActionsV2Location? = null, + /** + * User's decision regarding the request. + */ + var userDecision: GoogleActionsV2DeliveryAddressValueUserDecision? = null +) + +data class GoogleActionsV2DeliveryAddressValueSpec( + /** + * Configuration for delivery address dialog. + */ + var addressOptions: GoogleActionsV2DeliveryAddressValueSpecAddressOptions? = null +) { + fun addressOptions(init: GoogleActionsV2DeliveryAddressValueSpecAddressOptions.() -> Unit) { + this.addressOptions = GoogleActionsV2DeliveryAddressValueSpecAddressOptions() + this.addressOptions?.init() + } +} + +data class GoogleActionsV2DeliveryAddressValueSpecAddressOptions( + /** + * App can optionally pass a short text giving user a hint why delivery + * address is requested. For example, \"Grubhub is asking your address for + * [determining the actions.service area].\", the text in `[]` is the custom TTS + * that should be populated here. + */ + var reason: String? = null +) + +data class GoogleActionsV2Device( + /** + * Represents actual device location such as lat, lng, and formatted address. + * Requires the + * DEVICE_COARSE_LOCATION + * or + * DEVICE_PRECISE_LOCATION + * permission. + */ + var location: GoogleActionsV2Location? = null +) + +data class GoogleActionsV2DevicesAndroidApp( + /** + * Package name + * Package name must be specified when specifing Android Fulfillment. + */ + var packageName: String? = null, + /** + * When multiple filters are specified, any filter match will trigger the app. + */ + var versions: MutableList? = null +) + +data class GoogleActionsV2DevicesAndroidAppVersionFilter( + /** + * Max version code, inclusive. + * The range considered is [min_version:max_version]. + * A null range implies any version. + * Examples: + * To specify a single version use: [target_version:target_version]. + * To specify any version leave min_version and max_version unspecified. + * To specify all versions until max_version, leave min_version unspecified. + * To specify all versions from min_version, leave max_version unspecified. + */ + var maxVersion: Float? = null, + /** + * Min version code or 0, inclusive. + */ + var minVersion: Float? = null +) + +data class GoogleActionsV2DialogSpec( + /** + * Holds helper specific dialog specs if any. For example: + * ConfirmationDialogSpec for confirmation helper. + */ + var extension: ApiClientObjectMap? = null +) + +data class GoogleActionsV2Entitlement( + /** + * Only present for in-app purchase and in-app subs. + */ + var inAppDetails: GoogleActionsV2SignedData? = null, + /** + * Product sku. Package name for paid app, suffix of Finsky docid for + * in-app purchase and in-app subscription. + * Match getSku() in Play InApp Billing API. + */ + var sku: String? = null, + var skuType: GoogleActionsV2EntitlementSkuType? = null +) + +data class GoogleActionsV2ExpectedInput( + /** + * The customized prompt used to ask user for input. + */ + var inputPrompt: GoogleActionsV2InputPrompt? = null, + /** + * List of intents that can be used to fulfill this input. + * To have the Google Assistant just return the raw user input, the app + * should ask for the `actions.intent.TEXT` intent. + */ + var possibleIntents: MutableList? = null, + /** + * List of phrases the app wants Google to use for speech biasing. + * Up to 1000 phrases are allowed. + */ + var speechBiasingHints: MutableList? = null +) + +interface GoogleActionsV2ExpectedIntent { + /** + * Additional configuration data required by a built-in intent. Possible + * values for the built-in intents: `actions.intent.OPTION ->` + * [google.actions.v2.OptionValueSpec], `actions.intent.CONFIRMATION ->` + * [google.actions.v2.ConfirmationValueSpec], + * `actions.intent.TRANSACTION_REQUIREMENTS_CHECK ->` + * [google.actions.v2.TransactionRequirementsCheckSpec], + * `actions.intent.DELIVERY_ADDRESS ->` + * [google.actions.v2.DeliveryAddressValueSpec], + * `actions.intent.TRANSACTION_DECISION ->` + * [google.actions.v2.TransactionDecisionValueSpec], + * `actions.intent.PLACE ->` + * [google.actions.v2.PlaceValueSpec], + * `actions.intent.Link ->` + * [google.actions.v2.LinkValueSpec] + */ + var inputValueData: ProtoAny? + /** + * The built-in intent name, e.g. `actions.intent.TEXT`, or intents + * defined in the action package. If the intent specified is not a built-in + * intent, it is only used for speech biasing and the input provided by the + * Google Assistant will be the `actions.intent.TEXT` intent. + */ + var intent: String? + /** + * Optionally, a parameter of the intent that is being requested. Only valid + * for requested intents. Used for speech biasing. + */ + var parameterName: String? +} + +data class GoogleActionsV2ExpectedIntentData(override var inputValueData: ProtoAny? = null, + override var intent: String? = null, + override var parameterName: String? = null) : GoogleActionsV2ExpectedIntent + +data class GoogleActionsV2FinalResponse( + /** + * Rich response when user is not required to provide an input. + */ + var richResponse: GoogleActionsV2RichResponse? = null, + /** + * Spoken response when user is not required to provide an input. + */ + var speechResponse: GoogleActionsV2SpeechResponse? = null +) + +data class GoogleActionsV2Input( + /** + * A list of provided argument values for the input requested by the app. + */ + var arguments: MutableList? = null, + /** + * Indicates the user's intent. For the first conversation turn, the intent + * will refer to the intent of the action that is being triggered. For + * subsequent conversation turns, the intent will be a built-in intent. + * For example, if the expected input is `actions.intent.OPTION`, then the + * the intent specified here will either be `actions.intent.OPTION` if the + * Google Assistant was able to satisfy that intent, or + * `actions.intent.TEXT` if the user provided other information. + */ + var intent: String? = null, + /** + * Raw input transcription from each turn of conversation that was used to + * provide this input. + * Multiple conversation turns that don't involve the app may be required + * for the assistant to provide some types of input. + */ + var rawInputs: MutableList? = null +) + +data class GoogleActionsV2InputPrompt( + /** + * Initial prompts asking user to provide an input. + * Only a single initial_prompt is supported. + */ + var initialPrompts: MutableList? = null, + /** + * Prompt used to ask user when there is no input from user. + */ + var noInputPrompts: MutableList? = null, + /** + * Prompt payload. + */ + var richInitialPrompt: GoogleActionsV2RichResponse? = null +) + +data class GoogleActionsV2LinkValueSpec( + var dialogSpec: GoogleActionsV2DialogSpec? = null, + /** + * Destination that the app should link to. Could be a web URL, a + * conversational link or an Android intent. A web URL is used to handoff the + * flow to some website. A conversational link is used to provide a deep link + * into another AoG app. An Android intent URI is used to trigger an Android + * intent. This requires the package_name to be specified. + */ + var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? = null +) + +data class GoogleActionsV2LinkValueSpecLinkDialogSpec( + /** + * The name of the app or site this request wishes to linking to. + * The TTS will be created with the title \"Open \". Also + * used during confirmation, \"Can I send you to ?\" If we + * know the actual title of the link that is being handed off to, we will + * ignore this field and use the appropriate title. + * Max 20 chars. + */ + var destinationName: String? = null, + /** + * A string that is added to the end of the confirmation prompt to explain + * why we need to link out. Example: \"navigate to pick up your coffee?\" This + * can be appended to the confirmation prompt like \"Can I send you to Google + * Maps to navigate to pick up your coffee?\" + */ + var requestLinkReason: String? = null +) + +data class GoogleActionsV2Location( + /** + * City. + * Requires the DEVICE_PRECISE_LOCATION or + * DEVICE_COARSE_LOCATION permission. + */ + var city: String? = null, + /** + * Geo coordinates. + * Requires the DEVICE_PRECISE_LOCATION permission. + */ + var coordinates: GoogleTypeLatLng? = null, + /** + * Display address, e.g., \"1600 Amphitheatre Pkwy, Mountain View, CA 94043\". + * Requires the DEVICE_PRECISE_LOCATION permission. + */ + var formattedAddress: String? = null, + /** + * Name of the place. + */ + var name: String? = null, + /** + * Notes about the location. + */ + var notes: String? = null, + /** + * Phone number of the location, e.g. contact number of business location or + * phone number for delivery location. + */ + var phoneNumber: String? = null, + /** + * Postal address. + * Requires the DEVICE_PRECISE_LOCATION or + * DEVICE_COARSE_LOCATION permission. + */ + var postalAddress: GoogleTypePostalAddress? = null, + /** + * Zip code. + * Requires the DEVICE_PRECISE_LOCATION or + * DEVICE_COARSE_LOCATION permission. + */ + var zipCode: String? = null, + + var address: String? = null +) + +interface GoogleActionsV2MediaObject { + /** + * The url pointing to the media content. + */ + var contentUrl: String? + /** + * Description of this media object. + */ + var description: String? + /** + * A small image icon displayed on the right from the title. + * It's resized to 36x36 dp. + */ + var icon: GoogleActionsV2UiElementsImage? + /** + * A large image, such as the cover of the album, etc. + */ + var largeImage: GoogleActionsV2UiElementsImage? + /** + * Name of this media object. + */ + var name: String? +} + +interface GoogleActionsV2MediaResponse { + /** + * The list of media objects. + */ + var mediaObjects: MutableList? + /** + * Type of the media within this response. + */ + var mediaType: GoogleActionsV2MediaResponseMediaType? +} + +data class GoogleActionsV2MediaStatus( + /** + * The status of the media + */ + var status: GoogleActionsV2MediaStatusStatus? = null +) + +data class GoogleActionsV2NewSurfaceValue( + var status: GoogleActionsV2NewSurfaceValueStatus? = null +) + +data class GoogleActionsV2NewSurfaceValueSpec( + /** + * The list of capabilities required from the surface. Eg, + * [\"actions.capability.SCREEN_OUTPUT\"] + */ + var capabilities: MutableList? = null, + /** + * Context describing the content the user will receive on the new surface. + * Eg, \"[Sure, I know of 10 that are really popular. The highest-rated one is + * at Mount Marcy.] Is it okay if I send that to your phone?\" + */ + var context: String? = null, + /** + * Title of the notification which prompts the user to continue on the new + * surface. + */ + var notificationTitle: String? = null +) + +data class GoogleActionsV2OptionInfo( + /** + * A unique key that will be sent back to the agent if this response is given. + */ + var key: String? = null, + /** + * A list of synonyms that can also be used to trigger this item in dialog. + */ + var synonyms: MutableList? = null +) + +data class GoogleActionsV2OptionValueSpec( + /** + * A select with a card carousel GUI + */ + var carouselSelect: GoogleActionsV2UiElementsCarouselSelect? = null, + /** + * A select with a list card GUI + */ + var listSelect: GoogleActionsV2UiElementsListSelect? = null, + /** + * A simple select with no associated GUI + */ + var simpleSelect: GoogleActionsV2SimpleSelect? = null +) + +data class GoogleActionsV2OrdersActionProvidedPaymentOptions( + /** + * Name of the instrument displayed on the receipt. + * Required for action-provided payment info. + * For `PAYMENT_CARD`, this could be \"VISA-1234\". + * For `BANK`, this could be \"Chase Checking-1234\". + * For `LOYALTY_PROGRAM`, this could be \"Starbuck's points\". + * For `ON_FULFILLMENT`, this could be something like \"pay on delivery\". + */ + var displayName: String? = null, + /** + * Type of payment. + * Required. + */ + var paymentType: GoogleActionsV2OrdersActionProvidedPaymentOptionsPaymentType? = null +) + +data class GoogleActionsV2OrdersCancellationInfo( + /** + * Reason for cancellation. + */ + var reason: String? = null +) + +data class GoogleActionsV2OrdersCart( + /** + * Extension to the cart based on the type of order. + */ + var extension: ApiClientObjectMap? = null, + /** + * Optional id for this cart. Included as part of the + * Cart returned back to the integrator at confirmation time. + */ + var id: String? = null, + /** + * The good(s) or actions.service(s) the user is ordering. There must be at least + * one line item. + */ + var lineItems: MutableList? = null, + /** + * Merchant for the cart, if different from the caller. + */ + var merchant: GoogleActionsV2OrdersMerchant? = null, + /** + * Notes about this cart. + */ + var notes: String? = null, + /** + * Adjustments entered by the user, e.g. gratuity. + */ + var otherItems: MutableList? = null, + /** + * Optional. Promotional coupons added to the cart. Eligible promotions will + * be sent back as discount line items in proposed order. + */ + var promotions: MutableList? = null +) { + + fun merchant(init: GoogleActionsV2OrdersMerchant.() -> Unit) { + merchant = GoogleActionsV2OrdersMerchant() + merchant?.init() + } + + fun lineItems(vararg init: GoogleActionsV2OrdersLineItem.() -> Unit) { + this.lineItems = init.map { + val item = GoogleActionsV2OrdersLineItem() + item.it() + item + }.toMutableList() + } + + fun otherItems(vararg init: GoogleActionsV2OrdersLineItem.() -> Unit) { + this.otherItems = init.map { + val item = GoogleActionsV2OrdersLineItem() + item.it() + item + }.toMutableList() + } +} + +data class GoogleActionsV2OrdersCustomerInfo( + /** + * Customer email will be included and returned to the app if + * CustomerInfoProperty.EMAIL specified in CustomerInfoOptions. + */ + var email: String? = null +) + +data class GoogleActionsV2OrdersCustomerInfoOptions( + /** + * List of customer info properties. + */ + var customerInfoProperties: MutableList? = null +) + +data class GoogleActionsV2OrdersFulfillmentInfo( + /** + * When the order will be fulfilled. + */ + var deliveryTime: String? = null +) + +data class GoogleActionsV2OrdersGenericExtension( + /** + * Locations associated with the order. Up to 2 locations. + */ + var locations: MutableList? = null, + /** + * Time indicator associated with the proposed order. + */ + var time: GoogleActionsV2OrdersTime? = null +) + +data class GoogleActionsV2OrdersGoogleProvidedPaymentOptions( + /** + * If true, billing address will be returned. + */ + var billingAddressRequired: Boolean? = null, + /** + * If true, disallow prepaid cards from being used in the transaction. + */ + var prepaidCardDisallowed: Boolean? = null, + /** + * The app allows cards from any card network listed here being used in + * transaction. + * By default, Amex, Visa, MC and Discover are supported. + */ + var supportedCardNetworks: MutableList? = null, + /** + * Required field for requesting Google provided payment instrument. + * These tokenization parameters will be used for generating payment token + * for use in transaction. The app should get these parameters from their + * payment gateway. + */ + var tokenizationParameters: GoogleActionsV2OrdersPaymentMethodTokenizationParameters? = null +) + +data class GoogleActionsV2OrdersInTransitInfo( + /** + * Last updated time for in transit. + */ + var updatedTime: String? = null +) + +data class GoogleActionsV2OrdersLineItem( + /** + * Description of the item. + */ + var description: String? = null, + /** + * Extension to the line item based on its type. + */ + var extension: ApiClientObjectMap? = null, + /** + * Unique id of the line item within the Cart/Order. Required. + */ + var id: String? = null, + /** + * Small image associated with this item. + */ + var image: Image? = null, + /** + * Name of the line item as displayed in the receipt. Required. + */ + var name: String? = null, + /** + * Optional product or offer id for this item. + */ + var offerId: String? = null, + /** + * Each line item should have a price, even if the price is 0. Required. + * This is the total price as displayed on the receipt for this line + * (i.e. unit price * quantity). + */ + var price: GoogleActionsV2OrdersPrice? = null, + /** + * Number of items included. + */ + var quantity: Int? = null, + /** + * Sub-line item(s). Only valid if type is `REGULAR`. + */ + var subLines: MutableList? = null, + /** + * Type of line item. + */ + var type: GoogleActionsV2OrdersLineItemType? = null +) { + fun price(init: GoogleActionsV2OrdersPrice.() -> Unit) { + price = GoogleActionsV2OrdersPrice() + price?.init() + } + + fun subLines(vararg init: GoogleActionsV2OrdersLineItemSubLine.() -> Unit) { + this.subLines = init.map { + val subLine = GoogleActionsV2OrdersLineItemSubLine() + subLine.it() + subLine + }?.toMutableList() + } +} + +data class GoogleActionsV2OrdersLineItemSubLine( + /** + * A generic line item (e.g. add-on). + */ + var lineItem: GoogleActionsV2OrdersLineItem? = null, + /** + * A note associated with the line item. + */ + var note: String? = null +) { + fun lineItem(init: GoogleActionsV2OrdersLineItem.() -> Unit) { + val item = GoogleActionsV2OrdersLineItem() + item.init() + this.lineItem = item + } +} + +data class GoogleActionsV2OrdersLineItemUpdate( + /** + * Update to the line item extension. Type must match the item's + * existing extension type. + */ + var extension: ApiClientObjectMap? = null, + /** + * New line item-level state. + */ + var orderState: GoogleActionsV2OrdersOrderState? = null, + /** + * New price for the line item. + */ + var price: GoogleActionsV2OrdersPrice? = null, + /** + * Reason for the change. Required for price changes. + */ + var reason: String? = null +) + +data class GoogleActionsV2OrdersMerchant( + /** + * Id of the merchant. + */ + var id: String? = null, + /** + * User-visible name of the merchant. Required. + */ + var name: String? = null +) + +data class GoogleActionsV2OrdersOrder( + /** + * User-visible order id. Must be set on the initial synchronous + * OrderUpdate/confirmation. + */ + var actionOrderId: String? = null, + /** + * If requested, customer info e.g. email will be passed back to the app. + */ + var customerInfo: GoogleActionsV2OrdersCustomerInfo? = null, + /** + * Reflect back the proposed order that caused the order. + */ + var finalOrder: GoogleActionsV2OrdersProposedOrder? = null, + /** + * Order id assigned by Google. + */ + var googleOrderId: String? = null, + /** + * Date and time the order was created. + */ + var orderDate: String? = null, + /** + * Payment related info for the order. + */ + var paymentInfo: GoogleActionsV2OrdersPaymentInfo? = null +) + +data class GoogleActionsV2OrdersOrderLocation( + /** + * Contains actual location info. + */ + var location: GoogleActionsV2Location? = null, + /** + * Address type. Determines icon and placement. Required. + */ + var type: GoogleActionsV2OrdersOrderLocationType? = null +) { + fun location(init: GoogleActionsV2Location.() -> Unit) { + this.location = GoogleActionsV2Location() + this.location?.init() + } +} + +data class GoogleActionsV2OrdersOrderOptions( + /** + * The app can request customer info by setting this field. + * If set, the corresponding field will show up in ProposedOrderCard for + * user's confirmation. + */ + var customerInfoOptions: GoogleActionsV2OrdersCustomerInfoOptions? = null, + /** + * If true, delivery address is required for the associated Order. + */ + var requestDeliveryAddress: Boolean? = null +) + +data class GoogleActionsV2OrdersOrderState( + /** + * The user-visible string for the state. Required. + */ + var label: String? = null, + /** + * State can be one of the following values: + * + * `CREATED`: Order was created at integrator's system. + * `REJECTED`: Order was rejected by integrator. + * `CONFIRMED`: Order was confirmed by the integrator and is active. + * `CANCELLED`: User cancelled the order. + * `IN_TRANSIT`: Order is being delivered. + * `RETURNED`: User did a return. + * `FULFILLED`: User received what was ordered. + * 'CHANGE_REQUESTED': User has requested a change to the order, and + * the integrator is processing this change. The + * order should be moved to another state after the + * request is handled. + * + * Required. + */ + var state: String? = null +) + +interface GoogleActionsV2OrdersOrderUpdate { + /** + * Required. + * The canonical order id referencing this order. + * If integrators don't generate the canonical order id in their system, + * they can simply copy over google_order_id included in order. + */ + var actionOrderId: String? + /** + * Information about cancellation state. + */ + var cancellationInfo: GoogleActionsV2OrdersCancellationInfo? + /** + * Information about fulfillment state. + */ + var fulfillmentInfo: GoogleActionsV2OrdersFulfillmentInfo? + /** + * Id of the order is the Google-issued id. + */ + var googleOrderId: String? + /** + * Information about in transit state. + */ + var inTransitInfo: GoogleActionsV2OrdersInTransitInfo? + /** + * Extra data based on a custom order state or in addition to info of a + * standard state. + */ + var infoExtension: ApiClientObjectMap? + /** + * Map of line item-level changes, keyed by item id. Optional. + */ + var lineItemUpdates: ApiClientObjectMap? + /** + * Updated applicable management actions for the order, e.g. manage, modify, + * contact support. + */ + var orderManagementActions: MutableList? + /** + * The new state of the order. + */ + var orderState: GoogleActionsV2OrdersOrderState? + /** + * Receipt for order. + */ + var receipt: GoogleActionsV2OrdersReceipt? + /** + * Information about rejection state. + */ + var rejectionInfo: GoogleActionsV2OrdersRejectionInfo? + /** + * Information about returned state. + */ + var returnInfo: GoogleActionsV2OrdersReturnInfo? + /** + * New total price of the order + */ + var totalPrice: GoogleActionsV2OrdersPrice? + /** + * When the order was updated from the app's perspective. + */ + var updateTime: GoogleTypeTimeOfDay? + /** + * If specified, displays a notification to the user with the specified + * title and text. Specifying a notification is a suggestion to + * notify and is not guaranteed to result in a notification. + */ + var userNotification: GoogleActionsV2OrdersOrderUpdateUserNotification? + + /** + * Added in AoG-Kotlin + */ + var orderDate: String? + + var locale: String? +} + + +data class GoogleActionsV2OrdersOrderUpdateAction( + /** + * Button label and link. + */ + var button: Button? = null, + /** + * Type of action. + */ + var type: GoogleActionsV2OrdersOrderUpdateActionType? = null +) { + fun button(init: GoogleActionsV2UiElementsButton.() -> Unit) { + this.button = Button() + this.button?.init() + } +} + +data class GoogleActionsV2OrdersOrderUpdateUserNotification( + /** + * The contents of the notification. + */ + var text: String? = null, + /** + * The title for the user notification. + */ + var title: String? = null +) + +data class GoogleActionsV2OrdersPaymentInfo( + /** + * Name of the instrument displayed on the receipt. + */ + var displayName: String? = null, + /** + * Google provided payment instrument. + */ + var googleProvidedPaymentInstrument: GoogleActionsV2OrdersPaymentInfoGoogleProvidedPaymentInstrument? = null, + /** + * Type of payment. + * Required. + */ + var paymentType: GoogleActionsV2OrdersPaymentInfoPaymentType? = null +) + +data class GoogleActionsV2OrdersPaymentInfoGoogleProvidedPaymentInstrument( + /** + * If requested by integrator, billing address for the instrument in use + * will be included. + */ + var billingAddress: GoogleTypePostalAddress? = null, + /** + * Google provided payment instrument. + */ + var instrumentToken: String? = null +) + +data class GoogleActionsV2OrdersPaymentMethodTokenizationParameters( + /** + * If tokenization_type is set to `PAYMENT_GATEWAY` then the list of + * parameters should contain payment gateway specific parameters required to + * tokenize payment method as well as parameter with the name \"gateway\" with + * the value set to one of the gateways that we support e.g. \"stripe\" or + * \"braintree\". + * A sample tokenization configuration used for Stripe in JSON format. + * `{ + * \"gateway\" : \"stripe\", + * \"stripe:publishableKey\" : \"pk_1234\", + * \"stripe:version\" : \"1.5\" + * }` + * A sample tokenization configuration used for Braintree in JSON format. + * `{ + * \"gateway\" : \"braintree\", + * \"braintree:merchantId\" : \"abc\" + * \"braintree:sdkVersion\" : \"1.4.0\" + * \"braintree:apiVersion\" : \"v1\" + * \"braintree:clientKey\" : \"production_a12b34\" + * \"braintree:authorizationFingerprint\" : \"production_a12b34\" + * }` + * A sample configuration used for Adyen in JSON format. + * `{ + * \"gateway\" : \"adyen\", + * \"gatewayMerchantId\" : \"gateway-merchant-id\" + * }` + * If tokenization_type is set to DIRECT, integrators must specify a parameter + * named \"publicKey\" which will contain an Elliptic Curve public key using + * the uncompressed point format and base64 encoded. This publicKey will be + * used by Google to encrypt the payment information. + * Example of the parameter in JSON format: + * { + * \"publicKey\": \"base64encoded...\" + * } + */ + var parameters: ApiClientObjectMap? = null, + /** + * Required. + */ + var tokenizationType: GoogleActionsV2OrdersPaymentMethodTokenizationParametersTokenizationType? = null +) + +data class GoogleActionsV2OrdersPaymentOptions( + /** + * Info for an Action-provided payment instrument for display on receipt. + */ + var actionProvidedOptions: GoogleActionsV2OrdersActionProvidedPaymentOptions? = null, + /** + * Requirements for Google provided payment instrument. + */ + var googleProvidedOptions: GoogleActionsV2OrdersGoogleProvidedPaymentOptions? = null +) { + fun actionProvidedOptions(init: GoogleActionsV2OrdersActionProvidedPaymentOptions.() -> Unit) { + this.actionProvidedOptions = GoogleActionsV2OrdersActionProvidedPaymentOptions() + this.actionProvidedOptions?.init() + } + + fun googleProvidedOptions(init: GoogleActionsV2OrdersGoogleProvidedPaymentOptions.() -> Unit) { + this.googleProvidedOptions = GoogleActionsV2OrdersGoogleProvidedPaymentOptions() + this.googleProvidedOptions?.init() + + } +} + +data class GoogleActionsV2OrdersPresentationOptions( + /** + * call_to_action can be one of the following values: + * + * `PLACE_ORDER`: Used for placing an order. + * `PAY`: Used for a payment. + * `BUY`: Used for a purchase. + * `SEND`: Used for a money transfer. + * `BOOK`: Used for a booking. + * `RESERVE`: Used for reservation. + * `SCHEDULE`: Used for scheduling an appointment. + * `SUBSCRIBE`: Used for subscription. + * + * call_to_action refers to the action verb which best describes this order. + * This will be used in various places like prompt, suggestion chip etc while + * proposing the order to the user. + */ + var callToAction: String? = null +) + +data class GoogleActionsV2OrdersPrice( + /** + * Monetary amount. Required. + */ + var amount: GoogleTypeMoney? = null, + /** + * Type of price. Required. + */ + var type: GoogleActionsV2OrdersPriceType? = null +) { + fun amount(init: GoogleTypeMoney.() -> Unit) { + amount = GoogleTypeMoney() + amount?.init() + } +} + +data class GoogleActionsV2OrdersPromotion( + /** + * Required. Coupon code understood by 3P. For ex: GOOGLE10. + */ + var coupon: String? = null +) + +data class GoogleActionsV2OrdersProposedOrder( + /** + * User's items. + */ + var cart: GoogleActionsV2OrdersCart? = null, + /** + * Extension to the proposed order based on the kind of order. + * For example, if the order includes a location then this extension will + * contain a OrderLocation value. + */ + var extension: ProtoAny? = null, //ApiClientObjectMap? = null, + /** + * Optional id for this ProposedOrder. Included as part of the + * ProposedOrder returned back to the integrator at confirmation time. + */ + var id: String? = null, + /** + * Image associated with the proposed order. + */ + var image: Image? = null, + /** + * Fees, adjustments, subtotals, etc. + */ + var otherItems: MutableList? = null, + /** + * A link to the terms of actions.service that apply to this proposed order. + */ + var termsOfServiceUrl: String? = null, + /** + * Total price of the proposed order. If of type `ACTUAL`, this is the amount + * the caller will charge when the user confirms the proposed order. + */ + var totalPrice: GoogleActionsV2OrdersPrice? = null +) { + fun cart(init: GoogleActionsV2OrdersCart.() -> Unit) { + if (cart == null) { + cart = GoogleActionsV2OrdersCart() + } + cart?.init() + } + + fun totalPrice(init: GoogleActionsV2OrdersPrice.() -> Unit) { + if (totalPrice == null) { + totalPrice = GoogleActionsV2OrdersPrice() + } + totalPrice?.init() + } + fun extension(init: ProtoAny.() -> Unit) { + if (extension == null) { + extension = ProtoAny() + } + extension?.init() + } + fun image(init: Image.() -> Unit) { + if (image == null) { + image = Image() + } + image?.init() + } +} + +fun order(init: GoogleActionsV2OrdersProposedOrder.() -> Unit): GoogleActionsV2OrdersProposedOrder { + val order = GoogleActionsV2OrdersProposedOrder() + order.init() + return order +} + +data class GoogleActionsV2OrdersReceipt( + /** + * Confirmed order id when order has been received by the integrator. This is + * the canonical order id used in integrator's system referencing the order + * and may subsequently be used to identify the order as `action_order_id`. + */ + var confirmedActionOrderId: String? = null, + /** + * Optional. + * The user facing id referencing to current order, which will show up in the + * receipt card if present. This should be the id that usually appears on + * a printed receipt or receipt sent to user's email. + * User should be able to use this id referencing her order for customer + * actions.service provided by integrators. + * Note that this field must be populated if integrator does generate + * user facing id for an order with a printed receipt / email receipt. + */ + var userVisibleOrderId: String? = null +) + +data class GoogleActionsV2OrdersRejectionInfo( + /** + * Reason for the error. + */ + var reason: String? = null, + /** + * Rejection type. + */ + var type: GoogleActionsV2OrdersRejectionInfoType? = null +) + +data class GoogleActionsV2OrdersReturnInfo( + /** + * Reason for return. + */ + var reason: String? = null +) + +data class GoogleActionsV2OrdersTime( + /** + * ISO 8601 representation of time indicator: could be a duration, date or + * exact datetime. + */ + var timeIso8601: String? = null, + /** + * Type of time indicator. + */ + var type: GoogleActionsV2OrdersTimeType? = null +) + +data class GoogleActionsV2PackageEntitlement( + /** + * List of entitlements for a given app + */ + var entitlements: MutableList? = null, + /** + * Should match the package name in action package + */ + var packageName: String? = null +) + +data class GoogleActionsV2PermissionValueSpec( + /** + * The context why agent needs to request permission. + */ + var optContext: String? = null, + /** + * List of permissions requested by the agent. + */ + var permissions: MutableList? = null, + /** + * Additional information needed to fulfill update permission request. + */ + var updatePermissionValueSpec: GoogleActionsV2UpdatePermissionValueSpec? = null +) + +data class GoogleActionsV2PlaceValueSpec( + /** + * Speech configuration for askForPlace dialog. The extension should be used + * to define the PlaceDialogSpec configuration. + */ + var dialogSpec: GoogleActionsV2DialogSpec? = null +) + +data class GoogleActionsV2PlaceValueSpecPlaceDialogSpec( + /** + * This is the context for seeking permission to access various user related + * data if the user prompts for personal location during the sub-dialog like + * \"Home\", \"Work\" or \"Dad's house\". For example \"*To help you find + * juice stores*, I just need to check your location. Can I get that from + * Google?\". The first part of this permission prompt is configurable. + */ + var permissionContext: String? = null, + /** + * This is the initial prompt by AskForPlace sub-dialog. For example \"What + * place do you want?\" + */ + var requestPrompt: String? = null +) + +data class GoogleActionsV2RawInput( + /** + * Indicates how the user provided this input: a typed response, a voice + * response, unspecified, etc. + */ + var inputType: GoogleActionsV2RawInputInputType? = null, + /** + * Typed or spoken input from the end user. + */ + var query: String? = null +) + +data class GoogleActionsV2RegisterUpdateValue( + /** + * The status of the registering the update requested by the app. + */ + var status: GoogleActionsV2RegisterUpdateValueStatus? = null +) + +data class GoogleActionsV2RegisterUpdateValueSpec( + /** + * The list of arguments to necessary to fulfill an update. + */ + var arguments: MutableList? = null, + /** + * The intent that the user wants to get updates from. + */ + var intent: String? = null, + /** + * The trigger context that defines how the update will be triggered. + * This may modify the dialog in order to narrow down the user's preferences + * for getting his or her updates. + */ + var triggerContext: GoogleActionsV2TriggerContext? = null +) + +interface GoogleActionsV2RichResponse { + /** + * A list of UI elements which compose the response + * The items must meet the following requirements: + * 1. The first item must be a SimpleResponse + * 2. At most two SimpleResponse + * 3. At most one card (e.g. BasicCard or + * StructuredResponse or + * MediaResponse + * 4. Cards may not be used if an actions.intent.OPTION intent is used + * ie ListSelect or + * CarouselSelect + */ + var items: MutableList? + /** + * An additional suggestion chip that can link out to the associated app + * or site. + */ + var linkOutSuggestion: GoogleActionsV2UiElementsLinkOutSuggestion? + /** + * A list of suggested replies. These will always appear at the end of the + * response. If used in a FinalResponse, + * they will be ignored. + */ + var suggestions: MutableList? +} + +data class GoogleActionsV2SignInValue( + /** + * The status of the sign in requested by the app. + */ + var status: GoogleActionsV2SignInValueStatus? = null +) + +data class GoogleActionsV2SignInValueSpec( + /** + * The optional context why the app needs to ask the user to sign in, as a + * prefix of a prompt for user consent, e.g. \"To track your exercise\", or + * \"To check your account balance\". + */ + var optContext: String? = null +) + +data class GoogleActionsV2SignedData( + /** + * Matches IN_APP_DATA_SIGNATURE from getPurchases() method in Play InApp + * Billing API. + */ + var inAppDataSignature: String? = null, + /** + * Match INAPP_PURCHASE_DATA + * from getPurchases() method. Contains all inapp purchase data in JSON format + * See details in table 6 of + * https://developer.android.com/google/play/billing/billing_reference.html. + */ + var inAppPurchaseData: ApiClientObjectMap? = null +) + +interface GoogleActionsV2SimpleResponse { + /** + * Optional text to display in the chat bubble. If not given, a display + * rendering of the text_to_speech or ssml above will be used. Limited to 640 + * chars. + */ + var displayText: String? + /** + * Structured spoken response to the user in the SSML format, e.g. + * ` Say animal name after the sound. `. + * Mutually exclusive with text_to_speech. + */ + var ssml: String? + /** + * Plain text of the speech output, e.g., \"where do you want to go?\" + * Mutually exclusive with ssml. + */ + var textToSpeech: String? +} + +data class GoogleActionsV2SimpleSelect( + /** + * List of items users should select from. + */ + var items: MutableList? = null +) + +data class GoogleActionsV2SimpleSelectItem( + /** + * Item key and synonyms. + */ + var optionInfo: GoogleActionsV2OptionInfo? = null, + /** + * Title of the item. It will act as synonym if it's provided. + * Optional + */ + var title: String? = null +) + +data class GoogleActionsV2SpeechResponse( + /** + * Structured spoken response to the user in the SSML format, e.g. + * \" Say animal name after the sound. \". + * Mutually exclusive with text_to_speech. + */ + var ssml: String? = null, + /** + * Plain text of the speech output, e.g., \"where do you want to go?\"/ + */ + var textToSpeech: String? = null +) + +data class GoogleActionsV2StructuredResponse( + /** + * App provides an order update (e.g. + * Receipt) after receiving the order. + */ + var orderUpdate: GoogleActionsV2OrdersOrderUpdate? = null +) + +data class GoogleActionsV2Surface( + /** + * A list of capabilities the surface supports at the time of the request + * e.g. `actions.capability.AUDIO_OUTPUT` + */ + var capabilities: MutableList? = null +) + +data class GoogleActionsV2TransactionDecisionValue( + /** + * If `check_result` is NOT `ResultType.OK`, the rest of the fields in + * this message should be ignored. + */ + var checkResult: MutableList? = null, + /** + * If user requests for delivery address update, this field includes the + * new delivery address. This field will be present only when `user_decision` + * is `DELIVERY_ADDRESS_UPDATED`. + */ + var deliveryAddress: GoogleActionsV2Location? = null, + /** + * The order that user has approved. This field will be present only when + * `user_decision` is `ORDER_ACCEPTED`. + */ + var order: GoogleActionsV2OrdersOrder? = null, + /** + * User decision regarding the proposed order. + */ + var userDecision: GoogleActionsV2TransactionDecisionValueUserDecision? = null +) + +data class GoogleActionsV2TransactionDecisionValueSpec( + /** + * Options associated with the order. + */ + var orderOptions: GoogleActionsV2OrdersOrderOptions? = null, + /** + * Payment options for this order, or empty if no payment + * is associated with the order. + */ + var paymentOptions: GoogleActionsV2OrdersPaymentOptions? = null, + /** + * Options used to customize order presentation to the user. + */ + var presentationOptions: GoogleActionsV2OrdersPresentationOptions? = null, + /** + * The proposed order that's ready for user to approve. + */ + var proposedOrder: GoogleActionsV2OrdersProposedOrder? = null +) { + + fun orderOptions(init: GoogleActionsV2OrdersOrderOptions.() -> Unit) { + this.orderOptions = GoogleActionsV2OrdersOrderOptions() + this.orderOptions?.init() + } + + fun paymentOptions(init: GoogleActionsV2OrdersPaymentOptions.() -> Unit) { + this.paymentOptions = GoogleActionsV2OrdersPaymentOptions() + this.paymentOptions?.init() + } +} + +data class GoogleActionsV2TransactionRequirementsCheckResult( + /** + * Result of the operation. + */ + var resultType: GoogleActionsV2TransactionRequirementsCheckResultResultType? = null +) + +data class GoogleActionsV2TransactionRequirementsCheckSpec( + /** + * Options associated with the order. + */ + var orderOptions: GoogleActionsV2OrdersOrderOptions? = null, + /** + * Payment options for this Order, or empty if no payment + * is associated with the Order. + */ + var paymentOptions: GoogleActionsV2OrdersPaymentOptions? = null +) + +data class GoogleActionsV2TriggerContext( + /** + * The time context for which the update can be triggered. + */ + var timeContext: GoogleActionsV2TriggerContextTimeContext? = null +) + +data class GoogleActionsV2TriggerContextTimeContext( + /** + * The high-level frequency of the recurring update. + */ + var frequency: GoogleActionsV2TriggerContextTimeContextFrequency? = null +) + +interface GoogleActionsV2UiElementsBasicCard { + /** + * Buttons. + * Currently at most 1 button is supported. + * Optional. + */ + var buttons: MutableList? + /** + * Body text of the card. + * Supports a limited set of markdown syntax for formatting. + * Required, unless image is present. + */ + var formattedText: String? + /** + * A hero image for the card. The height is fixed to 192dp. + * Optional. + */ + var image: GoogleActionsV2UiElementsImage? + /** + * Type of image display option. Optional. + */ + var imageDisplayOptions: GoogleActionsV2UiElementsBasicCardImageDisplayOptions? + /** + * Optional. + */ + var subtitle: String? + /** + * Overall title of the card. + * Optional. + */ + var title: String? +} + +interface GoogleActionsV2UiElementsButton { + /** + * Action to take when a user taps on the button. + * Required. + */ + var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? + /** + * Title of the button. + * Required. + */ + var title: String? + + fun openUrlAction(init: GoogleActionsV2UiElementsOpenUrlAction.() -> Unit) { + this.openUrlAction = GoogleActionsV2UiElementsOpenUrlAction() + this.openUrlAction?.init() + } +} + +interface GoogleActionsV2UiElementsCarouselBrowse { + /** + * Type of image display option. + * Optional. + */ + var imageDisplayOptions: GoogleActionsV2UiElementsCarouselBrowseImageDisplayOptions? + /** + * Min: 2. Max: 10. + */ + var items: MutableList? +} + +interface GoogleActionsV2UiElementsCarouselBrowseItem { + /** + * Description of the carousel item. + * Optional. + */ + var description: String? + /** + * Footer text for the carousel item, displayed below the description. + * Single line of text, truncated with an ellipsis. + * Optional. + */ + var footer: String? + /** + * Hero image for the carousel item. + * Optional. + */ + var image: GoogleActionsV2UiElementsImage? + /** + * URL of the document associated with the carousel item. + * The document can contain HTML content or, if \"url_type_hint\" is set to + * AMP_CONTENT, AMP content. + * Required. + */ + var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? + /** + * Title of the carousel item. + * Required. + */ + var title: String? +} + +data class GoogleActionsV2UiElementsCarouselSelect( + /** + * Type of image display option. Optional. + */ + var imageDisplayOptions: GoogleActionsV2UiElementsCarouselSelectImageDisplayOptions? = null, + /** + * min: 2 max: 10 + */ + var items: MutableList? = null +) + +data class GoogleActionsV2UiElementsCarouselSelectCarouselItem( + /** + * Body text of the card. + */ + var description: String? = null, + /** + * Optional. + */ + var image: GoogleActionsV2UiElementsImage? = null, + /** + * See google.actions.v2.OptionInfo + * for details. + * Required. + */ + var optionInfo: GoogleActionsV2OptionInfo? = null, + /** + * Title of the carousel item. When tapped, this text will be + * posted back to the conversation verbatim as if the user had typed it. + * Each title must be unique among the set of carousel items. + * Required. + */ + var title: String? = null +) + +interface GoogleActionsV2UiElementsImage { + /** + * A text description of the image to be used for accessibility, e.g. screen + * readers. + * Required. + */ + var accessibilityText: String? + /** + * The height of the image in pixels. + * Optional. + */ + var height: Int? + /** + * The source url of the image. Images can be JPG, PNG and GIF (animated and + * non-animated). For example,`https://www.agentx.com/logo.png`. Required. + */ + var url: String? + /** + * The width of the image in pixels. + * Optional. + */ + var width: Int? +} + +interface GoogleActionsV2UiElementsLinkOutSuggestion { + /** + * The name of the app or site this chip is linking to. The chip will be + * rendered with the title \"Open \". Max 20 chars. + * Required. + */ + var destinationName: String? + /** + * The URL of the App or Site to open when the user taps the suggestion chip. + * Ownership of this App/URL must be validated in the Actions on Google + * developer console, or the suggestion will not be shown to the user. + * Open URL Action supports http, https and intent URLs. + * For Intent URLs refer to: + * https://developer.chrome.com/multidevice/android/intents + */ + var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? + /** + * Deprecated. Use OpenUrlAction instead. + */ + var url: String? +} + +data class GoogleActionsV2UiElementsListSelect( + /** + * min: 2 max: 30 + */ + var items: MutableList? = null, + /** + * Overall title of the list. + * Optional. + */ + var title: String? = null +) + +data class GoogleActionsV2UiElementsListSelectListItem( + /** + * Main text describing the item. + * Optional. + */ + var description: String? = null, + /** + * Square image. + * Optional. + */ + var image: GoogleActionsV2UiElementsImage? = null, + /** + * Information about this option. See google.actions.v2.OptionInfo + * for details. + * Required. + */ + var optionInfo: GoogleActionsV2OptionInfo? = null, + /** + * Title of the list item. When tapped, this text will be + * posted back to the conversation verbatim as if the user had typed it. + * Each title must be unique among the set of list items. + * Required. + */ + var title: String? = null +) + +data class GoogleActionsV2UiElementsOpenUrlAction( + /** + * Information about the Android App if the URL is expected to be + * fulfilled by an Android App. + */ + var androidApp: GoogleActionsV2DevicesAndroidApp? = null, + /** + * The url field which could be any of: + * - http/https urls for opening an App-linked App or a webpage + */ + var url: String? = null, + /** + * Indicates a hint for the url type. + */ + var urlTypeHint: GoogleActionsV2UiElementsOpenUrlActionUrlTypeHint? = null +) + +data class GoogleActionsV2UiElementsSuggestion( + /** + * The text shown the in the suggestion chip. When tapped, this text will be + * posted back to the conversation verbatim as if the user had typed it. + * Each title must be unique among the set of suggestion chips. + * Max 25 chars + * Required + */ + var title: String? = null +) + +interface GoogleActionsV2UiElementsTableCard { + /** + * Buttons. + * Currently at most 1 button is supported. + * Optional. + */ + var buttons: MutableList? + /** + * Headers and alignment of columns. + */ + var columnProperties: MutableList? + /** + * Image associated with the table. Optional. + */ + var image: GoogleActionsV2UiElementsImage? + /** + * Row data of the table. The first 3 rows are guaranteed to be shown but + * others might be cut on certain surfaces. Please test with the simulator to + * see which rows will be shown for a given surface. On surfaces that support + * the WEB_BROWSER capability, you can point the user to + * a web page with more data. + */ + var rows: MutableList? + /** + * Subtitle for the table. Optional. + */ + var subtitle: String? + /** + * Overall title of the table. Optional but must be set if subtitle is set. + */ + var title: String? +} + +data class GoogleActionsV2UiElementsTableCardCell( + /** + * Text content of the cell. + */ + var text: String? = null +) + +interface GoogleActionsV2UiElementsTableCardColumnProperties { + /** + * Header text for the column. + */ + var header: String? + /** + * Horizontal alignment of content w.r.t column. If unspecified, content + * will be aligned to the leading edge. + */ + var horizontalAlignment: GoogleActionsV2UiElementsTableCardColumnPropertiesHorizontalAlignment? +} + +data class GoogleActionsV2UiElementsTableCardRow( + /** + * Cells in this row. The first 3 cells are guaranteed to be shown but + * others might be cut on certain surfaces. Please test with the simulator + * to see which cells will be shown for a given surface. + */ + var cells: MutableList? = null, + /** + * Indicates whether there should be a divider after each row. + */ + var dividerAfter: Boolean? = null +) + +data class GoogleActionsV2UpdatePermissionValueSpec( + /** + * The list of arguments necessary to fulfill an update. + */ + var arguments: MutableList? = null, + /** + * The intent that the user wants to get updates from. + */ + var intent: String? = null +) + +data class GoogleActionsV2User( + /** + * An OAuth2 token that identifies the user in your system. Only + * available if Account Linking + * configuration is defined in the action package and the user links their + * account. + */ + var accessToken: String? = null, + /** + * Token representing the user's identity. + * This is a Json web token including encoded profile. The definition is at + * https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo. + */ + var idToken: String? = null, + /** + * The timestamp of the last interaction with this user. + * This field will be omitted if the user has not interacted with the agent + * before. + */ + var lastSeen: String? = null, + /** + * Primary locale setting of the user making the request. + * Follows IETF BCP-47 language code + * http://www.rfc-editor.org/rfc/bcp/bcp47.txt + * However, the script subtag is not included. + */ + var locale: String? = null, + /** + * List of user entitlements for every package name listed in action package, + * if any. + */ + var packageEntitlements: MutableList? = null, + /** + * Contains permissions granted by user to this app. + */ + var permissions: MutableList? = null, + /** + * Information about the end user. Some fields are only available if the user + * has given permission to provide this information to the app. + */ + var profile: GoogleActionsV2UserProfile? = null, + /** + * Unique ID for the end user. + */ + var userId: String? = null, + /** + * An opaque token supplied by the application that is persisted across + * conversations for a particular user. + * The maximum size of the string is 10k characters. + */ + var userStorage: String? = null +) + + +data class GoogleActionsV2UserNotification( + /** + * The content of the notification. + */ + var text: String? = null, + /** + * The title for the notification. + */ + var title: String? = null +) + +data class GoogleActionsV2UserProfile( + /** + * The user's full name as specified in their Google account. + * Requires the NAME permission. + */ + var displayName: String? = null, + /** + * The user's last name as specified in their Google account. + * Note that this field could be empty. + * Requires the NAME permission. + */ + var familyName: String? = null, + /** + * The user's first name as specified in their Google account. + * Requires the NAME permission. + */ + var givenName: String? = null +) + + +data class GoogleRpcStatus( + /** + * The status code, which should be an enum value of google.rpc.Code. + */ + var code: Int? = null, + /** + * A list of messages that carry the error details. There is a common set of + * message types for APIs to use. + */ + var details: MutableList>? = null, + /** + * A developer-facing error message, which should be in English. Any + * user-facing error message should be localized and sent in the + * google.rpc.Status.details field, or localized by the client. + */ + var message: String? = null +) + +data class GoogleTypeDate( + /** + * Day of month. Must be from 1 to 31 and valid for the year and month, or 0 + * if specifying a year/month where the day is not significant. + */ + var day: Int? = null, + /** + * Month of year. Must be from 1 to 12, or 0 if specifying a date without a + * month. + */ + var month: Int? = null, + /** + * Year of date. Must be from 1 to 9999, or 0 if specifying a date without + * a year. + */ + var year: Int? = null +) + +data class GoogleTypeLatLng( + /** + * The latitude in degrees. It must be in the range [-90.0, +90.0]. + */ + var latitude: Double? = null, + /** + * The longitude in degrees. It must be in the range [-180.0, +180.0]. + */ + var longitude: Double? = null +) + +data class GoogleTypeMoney( + /** + * The 3-letter currency code defined in ISO 4217. + */ + var currencyCode: String? = null, + /** + * Number of nano (10^-9) units of the amount. + * The value must be between -999,999,999 and +999,999,999 inclusive. + * If `units` is positive, `nanos` must be positive or zero. + * If `units` is zero, `nanos` can be positive, zero, or negative. + * If `units` is negative, `nanos` must be negative or zero. + * For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000. + */ + var nanos: Int? = null, + /** + * The whole units of the amount. + * For example if `currencyCode` is `\"USD\"`, then 1 unit is one US dollar. + */ + var units: Int? = null +) + +data class GoogleTypePostalAddress( + /** + * Unstructured address lines describing the lower levels of an address. + * + * Because values in address_lines do not have type information and may + * sometimes contain multiple values in a single field (e.g. + * \"Austin, TX\"), it is important that the line order is clear. The order of + * address lines should be \"envelope order\" for the country/region of the + * address. In places where this can vary (e.g. Japan), address_language is + * used to make it explicit (e.g. \"ja\" for large-to-small ordering and + * \"ja-Latn\" or \"en\" for small-to-large). This way, the most specific line + * of an address can be selected based on the language. + * + * The minimum permitted structural representation of an address consists + * of a region_code with all remaining information placed in the + * address_lines. It would be possible to format such an address very + * approximately without geocoding, but no semantic reasoning could be + * made about any of the address components until it was at least + * partially resolved. + * + * Creating an address only containing a region_code and address_lines, and + * then geocoding is the recommended way to handle completely unstructured + * addresses (as opposed to guessing which parts of the address should be + * localities or administrative areas). + */ + var addressLines: MutableList? = null, + /** + * Optional. Highest administrative subdivision which is used for postal + * addresses of a country or region. + * For example, this can be a state, a province, an oblast, or a prefecture. + * Specifically, for Spain this is the province and not the autonomous + * community (e.g. \"Barcelona\" and not \"Catalonia\"). + * Many countries don't use an administrative area in postal addresses. E.g. + * in Switzerland this should be left unpopulated. + */ + var administrativeArea: String? = null, + /** + * Optional. BCP-47 language code of the contents of this address (if + * known). This is often the UI language of the input form or is expected + * to match one of the languages used in the address' country/region, or their + * transliterated equivalents. + * This can affect formatting in certain countries, but is not critical + * to the correctness of the data and will never affect any validation or + * other non-formatting related operations. + * + * If this value is not known, it should be omitted (rather than specifying a + * possibly incorrect default). + * + * Examples: \"zh-Hant\", \"ja\", \"ja-Latn\", \"en\". + */ + var languageCode: String? = null, + /** + * Optional. Generally refers to the city/town portion of the address. + * Examples: US city, IT comune, UK post town. + * In regions of the world where localities are not well defined or do not fit + * into this structure well, leave locality empty and use address_lines. + */ + var locality: String? = null, + /** + * Optional. The name of the organization at the address. + */ + var organization: String? = null, + /** + * Optional. Postal code of the address. Not all countries use or require + * postal codes to be present, but where they are used, they may trigger + * additional validation with other parts of the address (e.g. state/zip + * validation in the U.S.A.). + */ + var postalCode: String? = null, + /** + * Optional. The recipient at the address. + * This field may, under certain circumstances, contain multiline information. + * For example, it might contain \"care of\" information. + */ + var recipients: MutableList? = null, + /** + * Required. CLDR region code of the country/region of the address. This + * is never inferred and it is up to the user to ensure the value is + * correct. See http://cldr.unicode.org/ and + * http://www.unicode.org/cldr/charts/30/supplemental/territory_information.html + * for details. Example: \"CH\" for Switzerland. + */ + var regionCode: String? = null, + /** + * The schema revision of the `PostalAddress`. This must be set to 0, which is + * the latest revision. + * + * All new revisions **must** be backward compatible with old revisions. + */ + var revision: Int? = null, + /** + * Optional. Additional, country-specific, sorting code. This is not used + * in most regions. Where it is used, the value is either a string like + * \"CEDEX\", optionally followed by a number (e.g. \"CEDEX 7\"), or just a + * number alone, representing the \"sector code\" (Jamaica), \"delivery area + * indicator\" (Malawi) or \"post office indicator\" (e.g. Côte d'Ivoire). + */ + var sortingCode: String? = null, + /** + * Optional. Sublocality of the address. + * For example, this can be neighborhoods, boroughs, districts. + */ + var sublocality: String? = null +) + +data class GoogleTypeTimeOfDay( + /** + * Hours of day in 24 hour format. Should be from 0 to 23. An API may choose + * to allow the value \"24:00:00\" for scenarios like business closing time. + */ + var hours: Int? = null, + /** + * Minutes of hour of day. Must be from 0 to 59. + */ + var minutes: Int? = null, + /** + * Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999. + */ + var nanos: Double? = null, + /** + * Seconds of minutes of the time. Must normally be from 0 to 59. An API may + * allow the value 60 if it allows leap-seconds. + */ + var seconds: Int? = null +) diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/Conversation.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/Conversation.kt new file mode 100644 index 0000000..5889a20 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/Conversation.kt @@ -0,0 +1,517 @@ +package actions.service.actionssdk.conversation + +import actions.AppOptions +import actions.BaseApp +import actions.expected.OAuth2Client +import actions.framework.Headers +import actions.framework.JsonObject +import actions.service.actionssdk.conversation.argument.Arguments +import actions.service.actionssdk.conversation.response.* +import actions.service.actionssdk.ActionsSdkIntentHandler4 +import actions.service.actionssdk.api.* +import actions.service.dialogflow.DialogflowIntentHandler4 +import actions.service.dialogflow.api.Data + + +enum class IntentEnum(val value: String) { + MAIN("actions.intent.MAIN"), + TEXT("actions.intent.TEXT"), + PERMISSION("actions.intent.PERMISSION"), + OPTION("actions.intent.OPTION"), + TRANSACTION_REQUIREMENTS_CHECK("actions.intent.TRANSACTION_REQUIREMENTS_CHECK"), + DELIVERY_ADDRESS("actions.intent.DELIVERY_ADDRESS"), + TRANSACTION_DECISION("actions.intent.TRANSACTION_DECISION"), + CONFIRMATION("actions.intent.CONFIRMATION"), + DATETIME("actions.intent.DATETIME"), + SIGN_IN("actions.intent.SIGN_IN"), + NO_INPUT("actions.intent.NO_INPUT"), + CANCEL("actions.intent.CANCEL"), + NEW_SURFACE("actions.intent.NEW_SURFACE"), + REGISTER_UPDATE("actions.intent.REGISTER_UPDATE"), + CONFIGURE_UPDATES("actions.intent.CONFIGURE_UPDATES"), + PLACE("actions.intent.PLACE"), + LINK("actions.intent.LINK"), + MEDIA_STATUS("actions.intent.MEDIA_STATUS") +} + +enum class InputValueSpec(val value: String) { + PermissionValueSpec("type.googleapis.com/google.actions.v2.PermissionValueSpec"), + OptionValueSpec("type.googleapis.com/google.actions.v2.OptionValueSpec"), + TransactionRequirementsCheckSpec("type.googleapis.com/google.actions.v2.TransactionRequirementsCheckSpec"), + DeliveryAddressValueSpec("type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec"), + TransactionDecisionValueSpec("type.googleapis.com/google.actions.v2.TransactionDecisionValueSpec"), + ConfirmationValueSpec("type.googleapis.com/google.actions.v2.ConfirmationValueSpec"), + DateTimeValueSpec("type.googleapis.com/google.actions.v2.DateTimeValueSpec"), + NewSurfaceValueSpec("type.googleapis.com/google.actions.v2.NewSurfaceValueSpec"), + RegisterUpdateValueSpec("type.googleapis.com/google.actions.v2.RegisterUpdateValueSpec"), + SignInValueSpec("type.googleapis.com/google.actions.v2.SignInValueSpec"), + PlaceValueSpec("type.googleapis.com/google.actions.v2.PlaceValueSpec"), + LinkValueSpec("type.googleapis.com/google.actions.v2.LinkValueSpec") +} + +enum class DialogSpec(val value: String) { + PlaceDialogSpec("type.googleapis.com/google.actions.v2.PlaceValueSpec.PlaceDialogSpec"), + LinkDialogSpec("type.googleapis.com/google.actions.v2.LinkValueSpec.LinkDialogSpec") +} + +data class ConversationResponse( + var richResponse: GoogleActionsV2RichResponse? = null, + var expectUserResponse: Boolean? = null, + var userStorage: String? = null, + var expectedIntent: GoogleActionsV2ExpectedIntent? = null, + var noInputPrompts: MutableList? = null, + /** THESE ADDED TO AOG-KOTLIN TO GIVE RESPONSE IN DF CONSOLE AND USEFUL FOR OTHER PLATFORMS **/ + var speech: String? = null, + var displayText: String? = null) + +interface ConversationOptionsInit { + var data: MutableMap? + + var storage: TUserStorage? +} + +interface ConversationBaseOptions { + var headers: Headers? + var init: ConversationOptionsInit? + + var debug: Boolean? +} + +data class ConversationOptions( + var request: GoogleActionsV2AppRequest? = null, + var headers: Headers?, + var init: ConversationOptionsInit? = null) + +abstract class Conversation { + var request: GoogleActionsV2AppRequest? + + var headers: Headers? + + var responses: MutableList = mutableListOf() + var strResponses: MutableList = mutableListOf() + + var expectUserResponse = true + + var surface: Surface + + var available: Available + + var digested = false + + /** + * True if the app is being tested in sandbox mode. Enable sandbox + * mode in the [Actions console](console.actions.google.com) to test + * transactions. + * @public + */ + var sandbox: Boolean + + var input: Input + + /** + * Gets the {@link User} object. + * The user object contains information about the user, including + * a string identifier and personal information (requires requesting permissions, + * see {@link Permission|conv.ask(new Permission)}). + * @public + */ + var user: User + + var arguments: Arguments + + var device: Device + + /** + * Gets the unique conversation ID. It's a new ID for the initial query, + * and stays the same until the end of the conversation. + * + * @example + * ```javascript + * + * app.intent('actions.intent.MAIN', conv => { + * const conversationId = conv.id + * }) + * ``` + * + * @public + */ + var id: String + + var type: GoogleActionsV2ConversationType + + /** + * Shortcut for + * {@link Capabilities|conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT')} + * @public + */ + var screen: Boolean + + /** + * Set reprompts when users don't provide input to this action (no-input errors). + * Each reprompt represents as the {@link SimpleResponse}, but raw strings also can be specified + * for convenience (they're passed to the constructor of {@link SimpleResponse}). + * Notice that this value is not kept over conversations. Thus, it is necessary to set + * the reprompts per each conversation response. + */ + var noInputs: MutableList? = null + + var _raw: JsonObject? = null + + var _responded = false + + /** + * Holds platform data. May be used for other platforms with conv.data["facebook"] = + */ + var platformData: Data? = null + + /** + * Added to AOG-Kotlin to support DF console and other platforms + */ + var textToSpeech: String? = null + var displayText: String? = null + + private fun addToTextToSpeech(speech: String?) { + if (textToSpeech == null) + textToSpeech = String() + if (textToSpeech?.isBlank() == true) { + textToSpeech = speech + } else { + textToSpeech = " $speech" + } + } + + private fun addToTextToDisplayText(text: String?) { + if (displayText == null) + displayText = String() + if (displayText?.isBlank() == true) { + displayText = text + } else { + displayText = " $text" + } + } + + fun data(init: Data.() -> Unit) { + if (platformData == null) { + platformData = Data()//mutableMapOf() + } + platformData?.init() + } + + + constructor(options: ConversationOptions) { + val request = options.request + val headers = options.headers + val init = options.init + + this.request = request + this.headers = headers + + this.sandbox = this.request?.isInSandbox ?: false + + val inputs = this.request?.inputs + val conversation = this.request?.conversation + val input = inputs?.firstOrNull() + val rawInputs = input?.rawInputs + + this.input = Input(rawInputs?.get(0)) + this.surface = Surface(this.request?.surface) + this.available = Available(this.request?.availableSurfaces) + + this.user = User(this.request?.user/*, init && init.storage*/) + + this.arguments = Arguments(input?.arguments) + + this.device = Device(this.request?.device) + + this.id = conversation?.conversationId ?: "" + + this.type = conversation?.type ?: GoogleActionsV2ConversationType.TYPE_UNSPECIFIED + + this.screen = this.surface.capabilities?.has(SurfaceCapability.ACTIONS_CAPABILITY_SCREEN_OUTPUT) == true + } + + fun json(json: JsonObject): Conversation { + this._raw = json + this._responded = true + return this + } + + fun add(vararg responses: Response): Conversation { + if (this.digested) { + throw Error("Response has already been sent. " + + "Is this being used in an async call that was not " + + "returned as a promise to the intent handler?") + } + this.responses.addAll(responses) + this._responded = true + + responses?.forEach { + if (it is SimpleResponse) { + addToTextToSpeech(it.textToSpeech) + addToTextToDisplayText(it.displayText) + } + } + return this + } + + fun add(vararg responses: String): Conversation { + if (textToSpeech == null) { + textToSpeech = String() + } + responses.forEach { + this.add(SimpleResponse(it)) + addToTextToSpeech(it) + } +// if (this.digested) { +// throw Error("Response has already been sent. " + +// "Is this being used in an async call that was not " + +// "returned as a promise to the intent handler?") +// } +// this.strResponses.addAll(responses) +// this._responded = true + return this + } + + /** + * Asks to collect user's input. All user's queries need to be sent to the app. + * {@link https://developers.google.com/actions/policies/general-policies#user_experience| + * The guidelines when prompting the user for a response must be followed at all times}. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * const ssml = 'Hi! ' + + * 'I can read out an ordinal like 123. ' + + * 'Say a number.' + * conv.ask(ssml) + * }) + * + * app.intent('actions.intent.TEXT', (conv, input) => { + * if (input === 'bye') { + * return conv.close('Goodbye!') + * } + * const ssml = `You said, ${input}` + * conv.ask(ssml) + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask('Welcome to action snippets! Say a number.') + * }) + * + * app.intent('Number Input', (conv, {num}) => { + * conv.close(`You said ${num}`) + * }) + * ``` + * + * @param responses A response fragment for the library to construct a single complete response + * @public + */ + fun ask(vararg responses: Response): Conversation { + this.expectUserResponse = true + return this.add(*responses) + } + + fun ask(vararg responses: String): Conversation { + this.expectUserResponse = true + return this.add(*responses) + } + + fun noInputPrompts(vararg prompts: String) { + noInputs = prompts.map { SimpleResponse { speech = it } }.toMutableList() + } + + fun noInputPrompts(vararg init: SimpleResponseOptions.() -> Unit) { + noInputs = init.map { SimpleResponse(it) }.toMutableList() + } + + /** + * Have Assistant render the speech response and close the mic. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * const ssml = 'Hi! ' + + * 'I can read out an ordinal like 123. ' + + * 'Say a number.' + * conv.ask(ssml) + * }) + * + * app.intent('actions.intent.TEXT', (conv, input) => { + * if (input === 'bye') { + * return conv.close('Goodbye!') + * } + * const ssml = `You said, ${input}` + * conv.ask(ssml) + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask('Welcome to action snippets! Say a number.') + * }) + * + * app.intent('Number Input', (conv, {num}) => { + * conv.close(`You said ${num}`) + * }) + * ``` + * + * @param responses A response fragment for the library to construct a single complete response + * @public + */ + fun close(vararg responses: Response): Conversation { + this.expectUserResponse = false + return this.add(*responses) + } + + fun close(vararg responses: String): Conversation { + this.expectUserResponse = false + return this.add(*responses) + } + + fun close(): Conversation { + this.expectUserResponse = false + return this + } + + /** @public */ + fun response(): ConversationResponse { + if (!this._responded) { + throw Error("No response has been set. " + + "Is this being used in an async call that was not " + + "returned as a promise to the intent handler?") + } + if (this.digested) { + throw Error("Response has already been digested") + } + this.digested = true + val expectUserResponse = this.expectUserResponse + var richResponse = RichResponse() + var expectedIntent: GoogleActionsV2ExpectedIntent? = null + + for (response in this.responses) { + when (response) { + + is Question -> { + expectedIntent = response + if (response is SoloQuestion) { + // SoloQuestions don't require a SimpleResponse + // but API still requires a SimpleResponse + // so a placeholder is added to not error + + // It won't show up to the user as PLACEHOLDER + richResponse.add("PLACEHOLDER") + } + } + + is RichResponse -> richResponse = response + + is Suggestions -> { + if (richResponse.suggestions == null || richResponse.suggestions?.isEmpty() == true) { + richResponse.suggestions = mutableListOf() + } + richResponse.suggestions!!.addAll(response.suggestions) + } + + is Image -> richResponse.add(BasicCard(image = response)) + + is MediaObject -> richResponse.add(MediaResponse(response)) + + is RichResponseItem -> richResponse.add(response) + } + } + val userStorage = this.user._serialize() + + return ConversationResponse(expectUserResponse = expectUserResponse, + richResponse = richResponse, + userStorage = userStorage, + expectedIntent = expectedIntent, + noInputPrompts = noInputs, + speech = textToSpeech, + displayText = this.displayText) + } + + fun isNewSurface(): Boolean { + val ext = request?.inputs?.firstOrNull()?.arguments?.firstOrNull() + return ext?.name == "NEW_SURFACE" && ext?.extension?.status == "OK" + } + + /**** ADDED TO KOTLIN SDK FOR CONVENIENCE FOR MIGRATING FROM V1 *****/ + + fun getArgument(name: String): Any? = arguments.get(name) + + fun getTransactionDecision(): ArgumentExtension? { + val tmp = arguments.get("TRANSACTION_DECISION_VALUE") + return tmp?.extension + } + + fun getSignInStatus(): GoogleActionsV2SignInValueStatus? { + val arg = arguments.get("SIGN_IN") + return if (arg?.extension?.status == null) + GoogleActionsV2SignInValueStatus.ERROR + else + GoogleActionsV2SignInValueStatus.valueOf(arg.extension?.status!!) + } + + fun getTransactionRequirementsResult(): GoogleActionsV2TransactionRequirementsCheckResultResultType { + val tmp = arguments.get("TRANSACTION_REQUIREMENTS_CHECK_RESULT") + return if (tmp?.extension?.status == null) + GoogleActionsV2TransactionRequirementsCheckResultResultType.RESULT_TYPE_UNSPECIFIED + else + GoogleActionsV2TransactionRequirementsCheckResultResultType.valueOf(tmp?.extension?.resultType!!) + } + +} + +typealias ExceptionHandler = (TConversation, Exception) -> Any + +// interface ExceptionHandler> { +// /** @public */ +// tslint:disable-next-line:no-any allow to return any just detect if is promise +// +// (conv: TConversation, error: Error): Promise | any +// } + +/** @hidden */ +class TraversedActionsHandlers : MutableMap, Boolean> by mutableMapOf() + +/** @hidden */ +class TraversedDialogflowHandlers : MutableMap, Boolean> by mutableMapOf() + +/** @hidden */ +interface ConversationAppOptions : AppOptions { + var init: (() -> ConversationOptionsInit)? + + /** + * Client ID for User Profile Payload Verification + * See {@link Profile#payload|conv.user.profile.payload} + * @public + */ + var clientId: String? +} + +data class OAuth2ConfigClient(var id: String? = null) + +data class OAuth2Config(var client: OAuth2ConfigClient? = null) + +abstract class ConversationApp : BaseApp() { + /** @public */ + abstract var init: (() -> ConversationOptionsInit)? + + /** @public */ + abstract var auth: OAuth2Config? + + abstract var _client: OAuth2Client? +} + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/Device.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/Device.kt new file mode 100644 index 0000000..7ac07e4 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/Device.kt @@ -0,0 +1,19 @@ +package actions.service.actionssdk.conversation + +import actions.service.actionssdk.api.GoogleActionsV2Device +import actions.service.actionssdk.api.GoogleActionsV2Location + + +class Device(device: GoogleActionsV2Device? = null) { + /** + * If granted permission to device's location in previous intent, returns device's + * location (see {@link Permission|conv.ask(new Permission)}). + * @public + */ + var location: GoogleActionsV2Location? = null + + init { + location = device?.location + } + +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/Input.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/Input.kt new file mode 100644 index 0000000..1ef627c --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/Input.kt @@ -0,0 +1,41 @@ +package actions.service.actionssdk.conversation + +import actions.service.actionssdk.api.GoogleActionsV2RawInput +import actions.service.actionssdk.api.GoogleActionsV2RawInputInputType + + +class Input(var input: GoogleActionsV2RawInput? = null) { + /** + * Gets the user's raw input query. + * + * Will also be sent via intent handler 2nd argument which is the encouraged method to retrieve. + * + * @example + * ```javascript + * + * // Encouraged method through intent handler + * app.intent('actions.intent.TEXT', (conv, input) => { + * conv.close(`You said ${input}`) + * }) + * + * // Using conv.input.raw + * app.intent('actions.intent.TEXT', conv => { + * conv.close(`You said ${conv.input.raw}`) + * }) + * ``` + * + * @public + */ + var raw: String? = null + + /** + * Gets type of input used for this request. + * @public + */ + var type: GoogleActionsV2RawInputInputType? = null + + init { + this.raw = input?.query + this.type = input?.inputType + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/Intent.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/Intent.kt new file mode 100644 index 0000000..0cd70d9 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/Intent.kt @@ -0,0 +1,25 @@ +package actions.service.actionssdk.conversation + +/* +sealed class Intent(val value: String) { + class Main : Intent("actions.intent.MAIN") + class Text : Intent("actions.intent.TEXT:") + class Permission: Intent("actions.intent.PERMISSION") + class Option: Intent("actions.intent.OPTION") + class TransactionRequirementsCheck: Intent("actions.intent.TRANSACTION_REQUIREMENTS_CHECK") + class DeliveryAddress: Intent("actions.intent.DELIVERY_ADDRESS") + class TransactionDecision: Intent("actions.intent.TRANSACTION_DECISION") + class Confirmation: Intent("actions.intent.CONFIRMATION") + class Datetime: Intent("actions.intent.DATETIME") + class SignIn: Intent("actions.intent.SIGN_IN") + class NoInput: Intent("actions.intent.NO_INPUT") + class Cancel: Intent("actions.intent.CANCEL") + class NewSurface: Intent("actions.intent.NEW_SURFACE") + class RegisterUpdate: Intent("actions.intent.REGISTER_UPDATE") + class ConfigureUpdates: Intent("actions.intent.CONFIGURE_UPDATES") + class Place: Intent("actions.intent.PLACE") + class Link: Intent("actions.intent.LINK") + class MediaStatus: Intent("actions.intent.MEDIA_STATUS") +} + +*/ diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/Surface.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/Surface.kt new file mode 100644 index 0000000..a16a5fa --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/Surface.kt @@ -0,0 +1,81 @@ +package actions.service.actionssdk.conversation + +import actions.service.actionssdk.api.GoogleActionsV2Capability +import actions.service.actionssdk.api.GoogleActionsV2Surface + + +enum class SurfaceCapability(val value: String) { + ACTIONS_CAPABILITY_AUDIO_OUTPUT("actions.capability.AUDIO_OUTPUT"), + ACTIONS_CAPABILITY_SCREEN_OUTPUT("actions.capability.SCREEN_OUTPUT"), + ACTIONS_CAPABILITY_MEDIA_RESPONSE_AUDIO("actions.capability.MEDIA_RESPONSE_AUDIO"), + ACTIONS_CAPABILITY_WEB_BROWSER("actions.capability.WEB_BROWSER") +} + +class Surface(surface: GoogleActionsV2Surface? = null) { + /** @public */ + var capabilities: Capabilities? = null + + init { + this.capabilities = Capabilities(surface?.capabilities) + } +} + +class Capabilities(list: List? = null) { + /** + * List of surface capabilities of user device. + * @public + */ + var list: List? = null + + init { + this.list = list + } + + /** + * Returns true if user device has a given surface capability. + * @public + */ + fun has(capability: SurfaceCapability): Boolean = + list?.find { it.name == capability.value } != null +} + +class AvailableSurfacesCapabilities(surfaces: List? = null) { + /** @public */ + var surfaces: List? = null + + init{ + this.surfaces = surfaces + } + + /** + * Returns true if user has an available surface which includes all given + * capabilities. Available surfaces capabilities may exist on surfaces other + * than that used for an ongoing conversation. + * @public + */ + fun has(capability: SurfaceCapability) = + surfaces?.find {it.capabilities?.has(capability) == true } != null + +} + +class AvailableSurfaces(list: List? = null) { + /** @public */ + var list: List? = null + + /** @public */ + var capabilities: AvailableSurfacesCapabilities? = null + + init { + this.list = list?.map { Surface(it) } + this.capabilities = AvailableSurfacesCapabilities(this.list) + } +} + +class Available(surfaces: List? = null) { + /** @public */ + var surfaces: AvailableSurfaces? = null + + init { + this.surfaces = AvailableSurfaces(surfaces) + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/User.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/User.kt new file mode 100644 index 0000000..01a3b04 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/User.kt @@ -0,0 +1,284 @@ +package actions.service.actionssdk.conversation + +import actions.expected.* +import actions.expected.Serializer.serialize +import actions.service.actionssdk.api.GoogleActionsV2PackageEntitlement +import actions.service.actionssdk.api.GoogleActionsV2User +import actions.service.actionssdk.api.GoogleActionsV2UserPermissions +import actions.service.actionssdk.api.GoogleActionsV2UserProfile + + +data class Last( + /** + * Timestamp for the last access from the user. + * Undefined if never seen. + * @public + */ + var seen: String? = null) { + + /** @hidden */ + constructor(user: GoogleActionsV2User? = null) : + this(user?.lastSeen) + +} + +data class Name( + /** + * User's display name. + * @public + */ + var display: String? = null, + + /** + * User's family name. + * @public + */ + var family: String? = null, + + /** + * User's given name. + * @public + */ + var given: String? = null) { + + constructor(profile: GoogleActionsV2UserProfile? = null) : + this(display = profile?.displayName, + family = profile?.familyName, + given = profile?.givenName) +} + +data class Access( + /** + * Unique Oauth2 token. Only available with account linking. + * @public + */ + var token: String? = null) { + + constructor(user: GoogleActionsV2User? = null) : + this(token = user?.accessToken) +} + +data class Profile( + /** + * Gets the Profile Payload object encoded in {@link Profile#token|conv.user.profile.token}. + * Only retrievable with "Google Sign In" linking type set up for account linking in the console. + * + * To access just the email in the payload, you can also use {@link User#email|conv.user.email}. + * + * @example + * ```javascript + * + * // Dialogflow + * const app = dialogflow({ + * clientId: CLIENT_ID, + * }) + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new SignIn('To get your account details')) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_SIGN_IN` event + * app.intent('Get Signin', (conv, params, signin) => { + * if (signin.status === 'OK') { + * const payload = conv.user.profile.payload + * conv.ask(`I got your account details. What do you want to do next?`) + * } else { + * conv.ask(`I won't be able to save your data, but what do you want to do next?`) + * } + * }) + * + * // Actions SDK + * const app = actionssdk({ + * clientId: CLIENT_ID, + * }) + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new SignIn('To get your account details')) + * }) + * + * app.intent('actions.intent.SIGN_IN', (conv, input, signin) => { + * if (signin.status === 'OK') { + * const payload = conv.user.profile.payload + * conv.ask(`I got your account details. What do you want to do next?`) + * } else { + * conv.ask(`I won't be able to save your data, but what do you want to do next?`) + * } + * }) + * ``` + * + * @public + */ + var payload: TokenPayload? = null, + + /** + * The `user.idToken` retrieved from account linking. + * Only retrievable with "Google Sign In" linking type set up for account linking in the console. + * @public + */ + var token: String? = null) { + + constructor(user: GoogleActionsV2User? = null) : + this(token = user?.idToken) + + /** @hidden */ + fun async_verify(client: OAuth2Client, id: String): TokenPayload? { + val login = client.verifyIdToken( + IdToken( + idToken = this.token, + audience = id)) + + this.payload = login.getPayload() + return this.payload + } +} + +data class User( + /** + * The data persistent across sessions in JSON format. + * It exists in the same context as `conv.user.id` + * + * @example + * ```javascript + * + * // Actions SDK + * app.intent('actions.intent.MAIN', conv => { + * conv.user.storage.someProperty = 'someValue' + * }) + * + * // Dialogflow + * app.intent('Default Welcome Intent', conv => { + * conv.user.storage.someProperty = 'someValue' + * }) + * ``` + * + * @public + */ + var storage: TUserStorage? = null, + + /** + * Random string ID for Google user. + * @public + */ + var id: String? = null, + + /** + * The user locale. String represents the regional language + * information of the user set in their Assistant settings. + * For example, 'en-US' represents US English. + * @public + */ + var locale: String? = null, + + /** @public */ + var last: Last? = null, + + /** @public */ + var permissions: MutableList? = null, + + /** + * User's permissioned name info. + * Properties will be undefined if not request with {@link Permission|conv.ask(new Permission)} + * @public + */ + var name: Name? = null, + + /** + * The list of all digital goods that your user purchased from + * your published Android apps. To enable this feature, see the instructions + * in the (documentation)[https://developers.google.com/actions/identity/digital-goods]. + * @public + */ + var entitlements: MutableList? = null, + + /** @public */ + var access: Access? = null, + + /** @public */ + var profile: Profile? = null, + + /** + * Gets the user profile email. + * Only retrievable with "Google Sign In" linking type set up for account linking in the console. + * + * See {@link Profile#payload|conv.user.profile.payload} for all the payload properties. + * + * @example + * ```javascript + * + * // Dialogflow + * const app = dialogflow({ + * clientId: CLIENT_ID, + * }) + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new SignIn('To get your account details')) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_SIGN_IN` event + * app.intent('Get Signin', (conv, params, signin) => { + * if (signin.status === 'OK') { + * const email = conv.user.email + * conv.ask(`I got your email as ${email}. What do you want to do next?`) + * } else { + * conv.ask(`I won't be able to save your data, but what do you want to next?`) + * } + * }) + * + * // Actions SDK + * const app = actionssdk({ + * clientId: CLIENT_ID, + * }) + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new SignIn('To get your account details')) + * }) + * + * app.intent('actions.intent.SIGN_IN', (conv, input, signin) => { + * if (signin.status === 'OK') { + * const email = conv.user.email + * conv.ask(`I got your email as ${email}. What do you want to do next?`) + * } else { + * conv.ask(`I won't be able to save your data, but what do you want to next?`) + * } + * }) + * ``` + * + * @public + */ + var email: String? = null) { + + /** @hidden */ + constructor(raw: GoogleActionsV2User? = null, initial: TUserStorage? = null) : + this(id = raw?.userId, + locale = raw?.locale, + permissions = raw?.permissions ?: mutableListOf(), + last = Last(raw), + name = Name(profile = raw?.profile ?: GoogleActionsV2UserProfile()), + entitlements = raw?.packageEntitlements, + access = Access(raw), + profile = Profile(raw) + ) { + //TODO("handle user storage") +// this.storage = if (this.raw ? JSON.parse(userStorage).data : (initial || {}), + } + + /** @hidden */ + fun _serialize(): String? { + return if (this.storage == null) + """{"data":{}}""" + else + serialize(UserStorage(this.storage)) + } + + /** @hidden */ + fun /* async */ _verifyProfile(client: OAuth2Client, id: String): TokenPayload? { + val payload = this.profile?.async_verify(client, id) + this.email = payload?.email + return payload + } +} + +/** + * JS lib uses dynamic type. Examine this closer to see if a Map works as a type + */ +data class UserStorage(var data: TStorage? = null) diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Argument.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Argument.kt new file mode 100644 index 0000000..8be91c5 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Argument.kt @@ -0,0 +1,314 @@ +package actions.service.actionssdk.conversation.argument + +import actions.ApiClientObjectMap +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.question.* +import actions.service.actionssdk.conversation.question.option.OptionArgument +import actions.service.actionssdk.conversation.question.permission.PermissionArgument +import actions.service.actionssdk.conversation.question.permission.UpdatePermissionUserIdArgument +import actions.service.actionssdk.conversation.question.transaction.DeliveryAddressArgument +import actions.service.actionssdk.conversation.question.transaction.TransactionDecisionArgument +import actions.service.actionssdk.conversation.question.transaction.TransactionRequirementsArgument + +/* commented out because this is duplicate of GoogleActionsV2Argument +data class Argument( + var boolValue: Boolean? = null, + var datetimeValue: GoogleActionsV2DateTime? = null, +// var extension: ArgumentExtension? = null, + var extension: ApiClientObjectMap? = null, + var floatValue: Float? = null, + var intValue: Int? = null, + var name: String? = null, + var placeValue: GoogleActionsV2Location? = null, + var rawText: String? = null, + var status: GoogleRpcStatus? = null, + var structuredValue: ApiClientObjectMap? = null, + var textValue: String? = null) + */ + +class ArgumentsNamed { + /** + * True if the request follows a previous request asking for + * permission from the user and the user granted the permission(s). + * Otherwise, false. + * Only use after calling {@link Permission|conv.ask(new Permission)} + * or {@link UpdatePermission|conv.ask(new UpdatePermission)}. + * @public + */ + var PERMISSION: PermissionArgument? = null + + /** + * The option key user chose from options response. + * Only use after calling {@link List|conv.ask(new List)} + * or {@link Carousel|conv.ask(new Carousel)}. + * @public + */ + var OPTION: OptionArgument? = null + + /** + * The transactability of user. + * Only use after calling {@link TransactionRequirements|conv.ask(new TransactionRequirements)}. + * Undefined if no result given. + * @public + */ + var TRANSACTION_REQUIREMENTS_CHECK_RESULT: TransactionRequirementsArgument? = null + + /** + * The order delivery address. + * Only use after calling {@link DeliveryAddress|conv.ask(new DeliveryAddress)}. + * @public + */ + var DELIVERY_ADDRESS_VALUE: DeliveryAddressArgument? = null + + /** + * The transaction decision information. + * Is object with userDecision only if user declines. + * userDecision will be one of {@link GoogleActionsV2TransactionDecisionValueUserDecision}. + * Only use after calling {@link TransactionDecision|conv.ask(new TransactionDecision)}. + * @public + */ + var TRANSACTION_DECISION_VALUE: TransactionDecisionArgument? = null + + /** + * The confirmation decision. + * Use after {@link Confirmation|conv.ask(new Confirmation)} + * @public + */ + var CONFIRMATION: ConfirmationArgument? = null + + /** + * The user provided date and time. + * Use after {@link DateTime|conv.ask(new DateTime)} + * @public + */ + var DATETIME: DateTimeArgument? = null + + /** + * The status of user sign in request. + * Use after {@link SignIn|conv.ask(new SignIn)} + * @public + */ + var SIGN_IN: SignInArgument? = null + + /** + * The number of subsequent reprompts related to silent input from the user. + * This should be used along with the `actions.intent.NO_INPUT` intent to reprompt the + * user for input in cases where the Google Assistant could not pick up any speech. + * @public + */ + var REPROMPT_COUNT: RepromptArgument? = null + + /** + * True if it is the final reprompt related to silent input from the user. + * This should be used along with the `actions.intent.NO_INPUT` intent to give the final + * response to the user after multiple silences and should be an `conv.close` + * which ends the conversation. + * @public + */ + var IS_FINAL_REPROMPT: FinalRepromptArgument? = null + + /** + * The result of {@link NewSurface|conv.ask(new NewSurface)} + * True if user has triggered conversation on a new device following the + * `actions.intent.NEW_SURFACE` intent. + * @public + */ + var NEW_SURFACE: NewSurfaceArgument? = null + + /** + * True if user accepted update registration request. + * Used with {@link RegisterUpdate|conv.ask(new RegisterUpdate)} + * @public + */ + var REGISTER_UPDATE: RegisterUpdateArgument? = null + + /** + * The updates user id. + * Only use after calling {@link UpdatePermission|conv.ask(new UpdatePermission)}. + * @public + */ + var UPDATES_USER_ID: UpdatePermissionUserIdArgument? = null + + /** + * The user provided place. + * Use after {@link Place|conv.ask(new Place)}. + * @public + */ + var PLACE: PlaceArgument? = null + + /** + * The link non status argument. + * Is undefined as a noop. + * Use {@link Status#get|conv.arguments.status.get('LINK')} to explicitly get the status. + * @public + */ + var LINK: DeepLinkArgument? = null + + /** + * The status of MEDIA_STATUS intent. + * @public + */ + var MEDIA_STATUS: MediaStatusArgument? = null +} + +class ArgumentsParsed : MutableMap by mutableMapOf() { +} + +class ArgumentsIndexable : MutableMap by mutableMapOf() { +} + +class ArgumentsStatus : MutableMap by mutableMapOf() { +} + +class ArgumentsRaw : MutableMap by mutableMapOf() { + /** @public */ +// [name: string]: Api.GoogleActionsV2Argument +} + +fun getValue(arg: GoogleActionsV2Argument): GoogleActionsV2Argument? { + return arg + +// for (key in arg) { +// if (key === 'name' || key === 'textValue' || key === 'status') { +// continue +// } +// return (arg as ArgumentsIndexable)[key] +// } +// Manually handle the PERMISSION argument because of a bug not returning boolValue +// if (arg.name === 'PERMISSION') { +// return !!arg.boolValue +// } +// return arg.textValue +// return null + +} + +class Parsed(raw: MutableList? = null) { + /** @public */ + var list: MutableList? = null + + /** @public */ + var input: ArgumentsParsed? = null + + init { + input = ArgumentsParsed() +// raw?.forEach { +// input?.put(it.name ?: "", it) +// } + } + + /** @public */ +// get(name: TName): ArgumentsNamed[TName] + /** @public */ +// get(name: string): Argument + fun get(name: String): GoogleActionsV2Argument? { + return this.input?.get(name) + } +} + +class Status(raw: MutableList? = null) { + /** @public */ + var list: MutableList? = null + + /** @public */ + var input: ArgumentsStatus? = null + + init { + input = ArgumentsStatus() + this.list = raw?.mapNotNull { + val name = it.name + val status = it.status + if (name != null && status != null) + this.input?.put(name, status) + status + }?.toMutableList() + } + + fun get(name: String): GoogleRpcStatus? { + return this.input?.get(name) + } +} + +class Raw(list: MutableList? = null) { + /** @public */ + var input: ArgumentsRaw? = null + + init { + input = ArgumentsRaw() + list?.forEach { + if (it.extension?.resultType != null) { + it.resultType = it.extension?.resultType + } + if (it.extension?.userDecision != null) { + it.userDecision = it.extension?.userDecision + } + if (it.extension?.location != null) { + it.location = it.extension?.location + } + input?.put(it.name ?: "", it) + } + } + + fun get(name: String): GoogleActionsV2Argument? { + return this.input?.get(name) + } +} + +class Arguments(raw: MutableList? = null) { + /** @public */ + var parsed: Parsed? = null + + /** @public */ + var status: Status? = null + + /** @public */ + var raw: Raw? = null + + init { + this.parsed = Parsed(raw) + this.status = Status(raw) + this.raw = Raw(raw) + } + + /** + * Get the argument value by name from the current intent. + * The first property value not named `name` or `status` will be returned. + * Will retrieve `textValue` last. + * If there is no other properties, return undefined. + * + * @example + * ```javascript + * + * // Actions SDK + * app.intent('actions.intent.PERMISSION', conv => { + * const granted = conv.arguments.get('PERMISSION') // boolean true if granted, false if not + * }) + * + * // Dialogflow + * // Create a Dialogflow intent with the `actions_intent_PERMISSION` event + * app.intent('Get Permission', conv => { + * const granted = conv.arguments.get('PERMISSION') // boolean true if granted, false if not + * }) + * ``` + * + * @param argument Name of the argument. + * @return First property not named 'name' or 'status' with 'textValue' given last priority + * or undefined if no other properties. + * + * @public + */ +// get(name: TName): ArgumentsNamed[TName] + /** @public */ +// get(name: string): Argument + fun get(name: String): GoogleActionsV2Argument? { + return this.raw?.get(name) + } + +// /** @public */ +// [Symbol.iterator]() +// { +// return this.raw.list[Symbol.iterator]() +// suppose to be Array.prototype.values(), but can't use because of bug: +// https://bugs.chromium.org/p/chromium/issues/detail?id=615873 +// } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Media.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Media.kt new file mode 100644 index 0000000..8b861e4 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/Media.kt @@ -0,0 +1,5 @@ +package actions.service.actionssdk.conversation.argument + +import actions.service.actionssdk.api.GoogleActionsV2MediaStatus + +typealias MediaStatusArgument = GoogleActionsV2MediaStatus \ No newline at end of file diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/NoInput.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/NoInput.kt new file mode 100644 index 0000000..7dfda0e --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/argument/NoInput.kt @@ -0,0 +1,5 @@ +package actions.service.actionssdk.conversation.argument + +typealias RepromptArgument = String + +typealias FinalRepromptArgument = Boolean \ No newline at end of file diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/Confirmation.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/Confirmation.kt new file mode 100644 index 0000000..2e4b94b --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/Confirmation.kt @@ -0,0 +1,63 @@ +package actions.service.actionssdk.conversation.question + +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + + +typealias ConfirmationArgument = Boolean + +/** + * Asks user for a confirmation. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new Confirmation('Are you sure you want to do that?')) + * }) + * + * app.intent('actions.intent.CONFIRMATION', (conv, input, confirmation) => { + * if (confirmation) { + * conv.close(`Great! I'm glad you want to do it!`) + * } else { + * conv.close(`That's okay. Let's not do it now.`) + * } + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new Confirmation('Are you sure you want to do that?')) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_CONFIRMATION` event + * app.intent('Get Confirmation', (conv, input, confirmation) => { + * if (confirmation) { + * conv.close(`Great! I'm glad you want to do it!`) + * } else { + * conv.close(`That's okay. Let's not do it now.`) + * } + * }) + * ``` + * + * @public + */ +class Confirmation(text: String): SoloQuestion(IntentEnum.CONFIRMATION) { + + /** + * @param text The confirmation prompt presented to the user to + * query for an affirmative or negative response. + * @public + */ + init { + this._data(actions.service.actionssdk.conversation.InputValueSpec.ConfirmationValueSpec) { + dialogSpec { + requestConfirmationText = text + } + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/DateTime.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/DateTime.kt new file mode 100644 index 0000000..d785f9a --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/DateTime.kt @@ -0,0 +1,114 @@ +package actions.service.actionssdk.conversation.question + +import actions.service.actionssdk.api.GoogleActionsV2DateTime +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + + +/** @public */ +typealias DateTimeArgument = GoogleActionsV2DateTime + +interface DateTimeOptionsPrompts { + /** + * The initial prompt used to ask for a date and time. + * If not provided, Google will use a generic prompt. + * @public + */ + var initial: String? + + /** + * The prompt used to specifically ask for the date if not provided by user. + * If not provided, Google will use a generic prompt. + * @public + */ + var date: String + + /** + * The prompt used to specifically ask for the time if not provided by user. + * If not provided, Google will use a generic prompt. + * @public + */ + var time: String? +} + +/** @public */ +interface DateTimeOptions { + /** + * Prompts for the user + * @public + */ + var prompts: DateTimeOptionsPrompts? +} + +/** + * Asks user for a timezone-agnostic date and time. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new DateTime({ + * prompts: { + * initial: 'When do you want to come in?', + * date: 'Which date works best for you?', + * time: 'What time of day works best for you?', + * } + * })) + * }) + * + * app.intent('actions.intent.DATETIME', (conv, input, datetime) => { + * const { month, day } = datetime.date + * const { hours, minutes } = datetime.time + * conv.close(new SimpleResponse({ + * speech: 'Great see you at your appointment!', + * text: `Great, we will see you on ${month}/${day} at ${hours} ${minutes || ''}` + * })) + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new DateTime({ + * prompts: { + * initial: 'When do you want to come in?', + * date: 'Which date works best for you?', + * time: 'What time of day works best for you?', + * } + * })) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_DATETIME` event + * app.intent('Get Datetime', (conv, params, datetime) => { + * const { month, day } = datetime.date + * const { hours, minutes } = datetime.time + * conv.close(new SimpleResponse({ + * speech: 'Great see you at your appointment!', + * text: `Great, we will see you on ${month}/${day} at ${hours} ${minutes || ''}` + * })) + * }) + * ``` + * + * @public + */ +class DateTime(options: DateTimeOptions? = null) : SoloQuestion(IntentEnum.DATETIME) { + /** + * @param options DateTime options + * @public + */ + init { + this._data(InputValueSpec.DateTimeValueSpec) { + options?.prompts?.let { + dialogSpec { + requestDatetimeText = it.initial + requestDateText = it.date + requestTimeText = it.time + } + } + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/DeepLink.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/DeepLink.kt new file mode 100644 index 0000000..afa8935 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/DeepLink.kt @@ -0,0 +1,106 @@ +package actions.service.actionssdk.conversation.question + +import actions.DialogSpecData +import actions.service.actionssdk.conversation.DialogSpec +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.Question + + +interface DeepLinkOptions { + /** + * The name of the link destination. + * @public + */ + var destination: String + + /** + * URL of Android deep link. + * @public + */ + var url: String + + /** + * Android app package name to which to link. + * @public + */ + var `package`: String + + /** + * The reason to transfer the user. This may be appended to a Google-specified prompt. + * @public + */ + var reason: String? +} + +/** @public */ +typealias DeepLinkArgument = Unit + +/** + * Requests the user to transfer to a linked out Android app intent. Using this feature + * requires verifying the linked app in the (Actions console)[console.actions.google.com]. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask('Great! Looks like we can do that in the app.') + * conv.ask(new DeepLink({ + * destination: 'Google', + * url: 'example://gizmos', + * package: 'com.example.gizmos', + * reason: 'handle this for you', + * })) + * }) + * + * app.intent('actions.intent.LINK', (conv, input, arg, status) => { + * // possibly do something with status + * conv.close('Okay maybe we can take care of that another time.') + * }) + * + * // Dialogflow + * const app = actionssdk() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask('Great! Looks like we can do that in the app.') + * conv.ask(new DeepLink({ + * destination: 'Google', + * url: 'example://gizmos', + * package: 'com.example.gizmos', + * reason: 'handle this for you', + * })) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_LINK` event + * app.intent('Get Link Status', (conv, input, arg, status) => { + * // possibly do something with status + * conv.close('Okay maybe we can take care of that another time.') + * }) + * ``` + * + * @public + */ +class DeepLink(options: DeepLinkOptions) : Question(IntentEnum.LINK) { + /** + * @param options DeepLink options + * @public + */ + init { + val extension = DialogSpecData( + `@type` = DialogSpec.LinkDialogSpec.value, + destinationName = options.destination, + requestLinkReason = options.reason) + + this._data(InputValueSpec.LinkValueSpec) { + openUrlAction = actions.service.actionssdk.api.GoogleActionsV2UiElementsOpenUrlAction( + url = options.url, + androidApp = actions.service.actionssdk.api.GoogleActionsV2DevicesAndroidApp( + packageName = options.`package`) + ) + dialogSpec = extension + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/NewSurface.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/NewSurface.kt new file mode 100644 index 0000000..3b26f38 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/NewSurface.kt @@ -0,0 +1,124 @@ +package actions.service.actionssdk.conversation.question + +import actions.service.actionssdk.api.GoogleActionsV2NewSurfaceValue +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.SurfaceCapability +import actions.service.actionssdk.conversation.response.SoloQuestion + + +typealias NewSurfaceArgument = GoogleActionsV2NewSurfaceValue + +data class NewSurfaceOptions( + /** + * Context why new surface is requested. + * It's the TTS prompt prefix (action phrase) we ask the user. + * @public + */ + var context: String? = null, + + /** + * Title of the notification appearing on new surface device. + * @public + */ + var notification: String? = null, + + /** + * The list of capabilities required in the surface. + * @public + */ + var capabilities: MutableList? = null +) + +/** + * Requests the user to switch to another surface during the conversation. + * Works only for en-* locales. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * const imageResponses = [ + * `Here's an image of Google`, + * new Image({ + * url: 'https://storage.googleapis.com/gweb-uniblog-publish-prod/images/' + + * 'Search_GSA.2e16d0ba.fill-300x300.png', + * alt: 'Google Logo', + * }) + * ] + * + * app.intent('actions.intent.MAIN', conv => { + * const capability = 'actions.capability.SCREEN_OUTPUT' + * if (conv.surface.capabilities.has(capability)) { + * conv.close(...imageResponses) + * } else { + * conv.ask(new NewSurface({ + * capabilities: capability, + * context: 'To show you an image', + * notification: 'Check out this image', + * })) + * } + * }) + * + * app.intent('actions.intent.NEW_SURFACE', (conv, input, newSurface) => { + * if (newSurface.status === 'OK') { + * conv.close(...imageResponses) + * } else { + * conv.close(`Ok, I understand. You don't want to see pictures. Bye`) + * } + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * const imageResponses = [ + * `Here's an image of Google`, + * new Image({ + * url: 'https://storage.googleapis.com/gweb-uniblog-publish-prod/images/' + + * 'Search_GSA.2e16d0ba.fill-300x300.png', + * alt: 'Google Logo', + * }) + * ] + * + * app.intent('Default Welcome Intent', conv => { + * const capability = 'actions.capability.SCREEN_OUTPUT' + * if (conv.surface.capabilities.has(capability)) { + * conv.close(...imageResponses) + * } else { + * conv.ask(new NewSurface({ + * capabilities: capability, + * context: 'To show you an image', + * notification: 'Check out this image', + * })) + * } + * }) + * + * // Create a Dialogflow intent with the `actions_intent_NEW_SURFACE` event + * app.intent('Get New Surface', (conv, input, newSurface) => { + * if (newSurface.status === 'OK') { + * conv.close(...imageResponses) + * } else { + * conv.close(`Ok, I understand. You don't want to see pictures. Bye`) + * } + * }) + * ``` + * + * @public + */ +class NewSurface(init: NewSurfaceOptions.() -> Unit): SoloQuestion(IntentEnum.NEW_SURFACE){ + /** + * @param options NewSurface options + * @public + */ + init { + val options = NewSurfaceOptions() + options.init() + this._data(InputValueSpec.NewSurfaceValueSpec) { + capabilities = options.capabilities + context = options.context + notificationTitle = options.notification + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/Place.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/Place.kt new file mode 100644 index 0000000..6270144 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/Place.kt @@ -0,0 +1,98 @@ +package actions.service.actionssdk.conversation.question + +import actions.DialogSpecData +import actions.service.actionssdk.api.GoogleActionsV2Location +import actions.service.actionssdk.conversation.DialogSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + + +/** @public */ +interface PlaceOptions { + /** + * This is the initial response by location sub-dialog. + * For example: "Where do you want to get picked up?" + * @public + */ + var prompt: String + + /** + * This is the context for seeking permissions. + * For example: "To find a place to pick you up" + * Prompt to user: "*To find a place to pick you up*, I just need to check your location. + * Can I get that from Google?". + * @public + */ + var context: String +} + +typealias PlaceArgument = GoogleActionsV2Location? + +/** + * Asks user to provide a geo-located place, possibly using contextual information, + * like a store near the user's location or a contact's address. + * + * Developer provides custom text prompts to tailor the request handled by Google. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new Place({ + * prompt: 'Where do you want to get picked up?', + * context: 'To find a place to pick you up', + * })) + * }) + * + * app.intent('actions.intent.PLACE', (conv, input, place, status) => { + * if (place) { + * conv.close(`Ah, I see. You want to get picked up at ${place.formattedAddress}`) + * } else { + * // Possibly do something with status + * conv.close(`Sorry, I couldn't find where you want to get picked up`) + * } + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new Place({ + * prompt: 'Where do you want to get picked up?', + * context: 'To find a place to pick you up', + * })) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_PLACE` event + * app.intent('Get Place', (conv, params, place, status) => { + * if (place) { + * conv.close(`Ah, I see. You want to get picked up at ${place.formattedAddress}`) + * } else { + * // Possibly do something with status + * conv.close(`Sorry, I couldn't find where you want to get picked up`) + * } + * }) + * ``` + * + * @public + */ +class Place(options: PlaceOptions) : SoloQuestion(IntentEnum.PLACE) { + /** + * @param options Place options + * @public + */ + init { + val extension = DialogSpecData( + `@type` = DialogSpec.PlaceDialogSpec.value, + permissionContext = options.context, + requestPrompt = options.prompt) + + this._data(actions.service.actionssdk.conversation.InputValueSpec.PlaceValueSpec) { + dialogSpec = extension + + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/RegisterUpdate.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/RegisterUpdate.kt new file mode 100644 index 0000000..f2c2aa4 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/RegisterUpdate.kt @@ -0,0 +1,96 @@ +package actions.service.actionssdk.conversation.question + +import actions.service.actionssdk.api.GoogleActionsV2Argument +import actions.service.actionssdk.api.GoogleActionsV2RegisterUpdateValue +import actions.service.actionssdk.api.GoogleActionsV2TriggerContextTimeContextFrequency +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + + +typealias RegisterUpdateArgument = GoogleActionsV2RegisterUpdateValue + +interface RegisterUpdateOptions { + /** + * The Dialogflow/Actions SDK intent name to be triggered when the update is received. + * @public + */ + var intent: String + + /** + * The necessary arguments to fulfill the intent triggered on update. + * These can be retrieved using {@link Arguments#get|conv.arguments.get}. + * @public + */ + var arguments: MutableList + + /** + * The high-level frequency of the recurring update. + * @public + */ + var frequency: GoogleActionsV2TriggerContextTimeContextFrequency +} + +/** + * Requests the user to register for daily updates. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new RegisterUpdate({ + * frequency: 'DAILY', + * intent: 'show.image', + * arguments: [{ + * name: 'image_to_show', + * textValue: 'image_type_1', + * }], + * })) + * }) + * + * app.intent('show.image', conv => { + * const arg = conv.arguments.get('image_to_show') // will be 'image_type_1' + * // do something with arg + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new RegisterUpdate({ + * frequency: 'DAILY', + * intent: 'Show Image', + * arguments: [{ + * name: 'image_to_show', + * textValue: 'image_type_1', + * }], + * })) + * }) + * + * app.intent('Show Image', conv => { + * const arg = conv.arguments.get('image_to_show') // will be 'image_type_1' + * // do something with arg + * }) + * ``` + * + * @public + */ +class RegisterUpdate(options: RegisterUpdateOptions) : SoloQuestion(IntentEnum.REGISTER_UPDATE) { + /** + * @param options RegisterUpdate options + * @public + */ + init { + this._data(InputValueSpec.RegisterUpdateValueSpec) { + intent = options.intent + arguments = options.arguments + triggerContext = actions.service.actionssdk.api.GoogleActionsV2TriggerContext( + timeContext = actions.service.actionssdk.api.GoogleActionsV2TriggerContextTimeContext( + frequency = options.frequency) + ) + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/SignIn.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/SignIn.kt new file mode 100644 index 0000000..ee373b3 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/SignIn.kt @@ -0,0 +1,69 @@ +package actions.service.actionssdk.conversation.question + +import actions.service.actionssdk.api.GoogleActionsV2SignInValue +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + + +/** @public */ +typealias SignInArgument = GoogleActionsV2SignInValue + +/** + * Hands the user off to a web sign in flow. App sign in and OAuth credentials + * are set in the {@link https://console.actions.google.com|Actions Console}. + * Retrieve the access token in subsequent intents using + * {@link Access#token|conv.user.access.token}. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new SignIn()) + * }) + * + * app.intent('actions.intent.SIGN_IN', (conv, input, signin) => { + * if (signin.status === 'OK') { + * const access = conv.user.access.token // possibly do something with access token + * conv.ask('Great, thanks for signing in! What do you want to do next?') + * } else { + * conv.ask(`I won't be able to save your data, but what do you want to do next?`) + * } + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new SignIn()) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_SIGN_IN` event + * app.intent('Get Signin', (conv, params, signin) => { + * if (signin.status === 'OK') { + * const access = conv.user.access.token // possibly do something with access token + * conv.ask('Great, thanks for signing in! What do you want to do next?') + * } else { + * conv.ask(`I won't be able to save your data, but what do you want to do next?`) + * } + * }) + * ``` + * + * @public + */ +class SignIn(context: String? = null) : SoloQuestion(IntentEnum.SIGN_IN) { + /** + * @param context The optional context why the app needs to ask the user to sign in, as a + * prefix of a prompt for user consent, e.g. "To track your exercise", or + * "To check your account balance". + * @public + */ + init { + this._data(InputValueSpec.SignInValueSpec) { + optContext = context + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Carousel.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Carousel.kt new file mode 100644 index 0000000..44c925a --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Carousel.kt @@ -0,0 +1,37 @@ +package actions.service.actionssdk.conversation.question.option + +import actions.service.actionssdk.api.GoogleActionsV2OptionInfo +import actions.service.actionssdk.api.GoogleActionsV2UiElementsCarouselSelectCarouselItem +import actions.service.actionssdk.api.GoogleActionsV2UiElementsCarouselSelectImageDisplayOptions + +/** + * Carousel class in Response.kt file because it is a part of the Response sealed class + */ + +data class CarouselOptions( + /** + * Sets the display options for the images in this carousel. + * @public + */ + var display: GoogleActionsV2UiElementsCarouselSelectImageDisplayOptions? = null, + + /** + * List of 2-20 items to show in this carousel. Required. + * @public + */ + var items: MutableMap? = null +) + + +fun MutableMap?.toGoogleActionsV2CarouselItem(): MutableList { + return this?.map { + GoogleActionsV2UiElementsCarouselSelectCarouselItem( + title = it.value.title, + description = it.value.description, + image = it.value.image, + optionInfo = GoogleActionsV2OptionInfo(key = it.key, synonyms = it.value.synonyms) + ) + }?.toMutableList() ?: mutableListOf() +} + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/List.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/List.kt new file mode 100644 index 0000000..6fee2ea --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/List.kt @@ -0,0 +1,28 @@ +package actions.service.actionssdk.conversation.question.option + +import actions.service.actionssdk.api.GoogleActionsV2OptionInfo +import actions.service.actionssdk.api.GoogleActionsV2UiElementsListSelectListItem + +data class ListOptions(var title: String? = null, + var items: MutableList? = null) + +data class ListOptions2(var title: String? = null, + var items: MutableMap? = null) + +fun item(name: String, init: OptionItem.() -> Unit): Pair { + val item = OptionItem() + item.init() + return name to item +} + +fun MutableMap?.toGoogleActionsV2ListItem(): MutableList { + return this?.map { + GoogleActionsV2UiElementsListSelectListItem( + title = it.value.title, + description = it.value.description, + image = it.value.image, + optionInfo = GoogleActionsV2OptionInfo(key = it.key, synonyms = it.value.synonyms) + ) + }?.toMutableList() ?: mutableListOf() +} + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Option.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Option.kt new file mode 100644 index 0000000..8494a40 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/option/Option.kt @@ -0,0 +1,78 @@ +package actions.service.actionssdk.conversation.question.option + +import actions.service.actionssdk.api.GoogleActionsV2UiElementsCarouselSelectCarouselItem +import actions.service.actionssdk.api.GoogleActionsV2UiElementsImage +import actions.service.actionssdk.conversation.response.Image + + +/** @public */ +typealias OptionArgument = String + +class OptionItems { + /** + * key: Unique string ID for this option. + * @public + */ +// [key: string]: TOptionItem +} + +/** + * Option item. Used in actions.intent.OPTION intent. + * @public + */ +data class OptionItem( + + /** + * Synonyms that can be used by the user to indicate this option if they do not use the key. + * @public + */ + var synonyms: MutableList? = null, + + /** + * Name of the item. + * @public + */ + var title: String? = null, + + /** + * Optional text describing the item. + * @public + */ + var description: String? = null, + + /** + * Square image to show for this item. + * @public + */ + var image: Image? = null +) + +/** @hidden */ +typealias ApiOptionItem = GoogleActionsV2UiElementsCarouselSelectCarouselItem + +/** @hidden */ +fun convert(items: OptionItems): Unit? {//=> Object.keys(items).map(key => { +// const value = items[key] +// if (typeof value === 'string') { +// const item: ApiOptionItem = { +// title: value, +// optionInfo: { +// key, +// }, +// } +// return item +// } +// const { description, image, synonyms, title } = value +// const item: ApiOptionItem = { +// optionInfo: { +// key, +// synonyms, +// }, +// description, +// image, +// title, +// } +// return item +//} + return null +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Permission.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Permission.kt new file mode 100644 index 0000000..2106ee6 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Permission.kt @@ -0,0 +1,120 @@ +package actions.service.actionssdk.conversation.question.permission + + +import actions.service.actionssdk.api.GoogleActionsV2PermissionValueSpec +import actions.service.actionssdk.api.GoogleActionsV2PermissionValueSpecPermissions +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + + +/** @public */ +typealias PermissionArgument = Boolean + +/** @public */ +data class PermissionOptions( + /** + * Context why the permission is being asked. + * It's the TTS prompt prefix (action phrase) we ask the user. + * @public + */ + var context: String? = null, + + /** + * Array or string of permissions App supports, + * each of which comes from {@link GoogleActionsV2PermissionValueSpecPermissions}. + * @public + */ + var permissions: MutableList? = null, +// | +// Api.GoogleActionsV2PermissionValueSpecPermissions[] + + /** + * Extra properties to be spread into the value. + * For advanced usages like used in {@link UpdatePermission} + * @public + */ + var extra: GoogleActionsV2PermissionValueSpec? = null +) + +/** + * Asks the Assistant to guide the user to grant a permission. For example, + * if you want your app to get access to the user's name, you would invoke + * `conv.ask(new Permission)` with the context containing the reason for the request, + * and the {@link GoogleActionsV2PermissionValueSpecPermissions} permission. + * With this, the Assistant will ask the user, in your agent's voice, + * the following: '[Context with reason for the request], + * I'll just need to get your name from Google, is that OK?'. + * + * Once the user accepts or denies the request, the Assistant will fire another intent: + * `actions.intent.PERMISSION` with a boolean argument: `PERMISSION` + * and, if granted, the information that you requested. + * + * Notes for multiple permissions: + * * The order in which you specify the permission prompts does not matter - + * it is controlled by the Assistant to provide a consistent user experience. + * * The user will be able to either accept all permissions at once, or none. + * If you wish to allow them to selectively accept one or other, make several + * dialog turns asking for each permission independently with `conv.ask(new Permission)`. + * * Asking for `DEVICE_COARSE_LOCATION` and `DEVICE_PRECISE_LOCATION` at once is + * equivalent to just asking for `DEVICE_PRECISE_LOCATION` + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new Permission({ + * context: 'To read your mind', + * permissions: 'NAME', + * })) + * }) + * + * app.intent('actions.intent.PERMISSION', (conv, input, granted) => { + * // granted: inferred first (and only) argument value, boolean true if granted, false if not + * const explicit = conv.arguments.get('PERMISSION') // also retrievable w/ explicit arguments.get + * const name = conv.user.name + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new Permission({ + * context: 'To read your mind', + * permissions: 'NAME', + * })) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_PERMISSION` event + * app.intent('Get Permission', (conv, params, granted) => { + * // granted: inferred first (and only) argument value, boolean true if granted, false if not + * const explicit = conv.arguments.get('PERMISSION') // also retrievable w/ explicit arguments.get + * const name = conv.user.name + * }) + * ``` + * + * Read more: + * * {@link GoogleActionsV2PermissionValueSpecPermissions|Supported Permissions} + * * Check if the permission has been granted with `conv.arguments.get('PERMISSION')` + * * {@link Device#location|conv.device.location} + * * {@link User#name|conv.user.name} + * * {@link Place|conv.ask(new Place)} which also can ask for Location permission to get a place + * @public + */ +open class Permission(init: PermissionOptions.() -> Unit): SoloQuestion(IntentEnum.PERMISSION) { + /** + * @param options Permission options + * @public + */ + init { + val options = PermissionOptions() + options.init() + this._data(actions.service.actionssdk.conversation.InputValueSpec.PermissionValueSpec) { + optContext = options.context + permissions = options.permissions + //...options.extra, + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Update.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Update.kt new file mode 100644 index 0000000..25e7aa3 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/permission/Update.kt @@ -0,0 +1,102 @@ +package actions.service.actionssdk.conversation.question.permission + +import actions.service.actionssdk.api.GoogleActionsV2Argument +import actions.service.actionssdk.api.GoogleActionsV2PermissionValueSpec +import actions.service.actionssdk.api.GoogleActionsV2PermissionValueSpecPermissions +import actions.service.actionssdk.api.GoogleActionsV2UpdatePermissionValueSpec + +/** @public */ +typealias UpdatePermissionUserIdArgument = String + +/** @public */ +class UpdatePermissionOptions { + /** + * The Dialogflow/Actions SDK intent name to be triggered when the update is received. + * @public + */ + var intent: String? = null + + /** + * The necessary arguments to fulfill the intent triggered on update. + * These can be retrieved using {@link Arguments#get|conv.arguments.get}. + * @public + */ + var arguments: MutableList? = null +} + +/** + * Prompts the user for permission to send proactive updates at any time. + * + * @example + * ```javascript + * + * // Actions SDK + * const app = actionssdk() + * + * app.intent('actions.intent.MAIN', conv => { + * conv.ask(new UpdatePermission({ + * intent: 'show.image', + * arguments: [{ + * name: 'image_to_show', + * textValue: 'image_type_1', + * } + * )) + * }) + * + * app.intent('actions.intent.PERMISSION', conv => { + * const granted = conv.arguments.get('PERMISSION') + * if (granted) { + * conv.close(`Great, I'll send an update whenever I notice a change`) + * } else { + * // Response shows that user did not grant permission + * conv.close('Alright, just let me know whenever you need the weather!') + * } + * }) + * + * app.intent('show.image', conv => { + * const arg = conv.arguments.get('image_to_show') // will be 'image_type_1' + * // do something with arg + * }) + * + * // Dialogflow + * const app = dialogflow() + * + * app.intent('Default Welcome Intent', conv => { + * conv.ask(new UpdatePermission({ + * intent: 'Show Image', + * arguments: [{ + * name: 'image_to_show', + * textValue: 'image_type_1', + * } + * )) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_PERMISSION` event + * app.intent('Get Permission', conv => { + * const granted = conv.arguments.get('PERMISSION') + * if (granted) { + * conv.close(`Great, I'll send an update whenever I notice a change`) + * } else { + * // Response shows that user did not grant permission + * conv.close('Alright, just let me know whenever you need the weather!') + * } + * }) + * + * app.intent('Show Image', conv => { + * const arg = conv.arguments.get('image_to_show') // will be 'image_type_1' + * // do something with arg + * }) + * ``` + * + * @public + */ +/** + * @param options UpdatePermission options + * @public + */ +class UpdatePermission(options: UpdatePermissionOptions? = null) : Permission({ + permissions = mutableListOf(GoogleActionsV2PermissionValueSpecPermissions.UPDATE) + extra = GoogleActionsV2PermissionValueSpec( + updatePermissionValueSpec = GoogleActionsV2UpdatePermissionValueSpec(arguments = options?.arguments, intent = options?.intent)) + }) + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Decision.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Decision.kt new file mode 100644 index 0000000..8f56b68 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Decision.kt @@ -0,0 +1,30 @@ +package actions.service.actionssdk.conversation.question.transaction + +import actions.service.actionssdk.api.GoogleActionsV2TransactionDecisionValue +import actions.service.actionssdk.api.GoogleActionsV2TransactionDecisionValueSpec +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + +typealias TransactionDecisionArgument = GoogleActionsV2TransactionDecisionValue + +/** + * Asks user to confirm transaction information. + * @public + */ +class TransactionDecision(init: GoogleActionsV2TransactionDecisionValueSpec.() -> Unit): SoloQuestion(IntentEnum.TRANSACTION_DECISION) { + /** + * @param options The raw {@link GoogleActionsV2TransactionDecisionValueSpec} + * @public + */ + init { + val options = GoogleActionsV2TransactionDecisionValueSpec() + options.init() + this._data(InputValueSpec.TransactionDecisionValueSpec) { + orderOptions = options.orderOptions + paymentOptions = options.paymentOptions + presentationOptions = options.presentationOptions + proposedOrder = options.proposedOrder + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/DeliveryAddress.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/DeliveryAddress.kt new file mode 100644 index 0000000..6125bf8 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/DeliveryAddress.kt @@ -0,0 +1,28 @@ +package actions.service.actionssdk.conversation.question.transaction + +import actions.service.actionssdk.api.GoogleActionsV2ConfirmationValueSpec +import actions.service.actionssdk.api.GoogleActionsV2DeliveryAddressValue +import actions.service.actionssdk.api.GoogleActionsV2DeliveryAddressValueSpec +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + +typealias DeliveryAddressArgument = GoogleActionsV2DeliveryAddressValue + +/** + * Asks user for delivery address. + * @public + */ +class DeliveryAddress(init: GoogleActionsV2DeliveryAddressValueSpec.() -> Unit): SoloQuestion(IntentEnum.DELIVERY_ADDRESS) { + /** + * @param options The raw {@link GoogleActionsV2DeliveryAddressValueSpec} + * @public + */ + init { + val options = GoogleActionsV2DeliveryAddressValueSpec() + options.init() + this._data(InputValueSpec.DeliveryAddressValueSpec) { + addressOptions = options?.addressOptions + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Requirements.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Requirements.kt new file mode 100644 index 0000000..1617654 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/question/transaction/Requirements.kt @@ -0,0 +1,28 @@ +package actions.service.actionssdk.conversation.question.transaction + +import actions.service.actionssdk.api.GoogleActionsV2TransactionRequirementsCheckResult +import actions.service.actionssdk.api.GoogleActionsV2TransactionRequirementsCheckSpec +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.response.SoloQuestion + +typealias TransactionRequirementsArgument = GoogleActionsV2TransactionRequirementsCheckResult + +/** + * Checks whether user is in transactable state. + * @public + */ +class TransactionRequirements(init: GoogleActionsV2TransactionRequirementsCheckSpec.() -> Unit): SoloQuestion(IntentEnum.TRANSACTION_REQUIREMENTS_CHECK) { + /** + * @param options The raw {@link GoogleActionsV2TransactionRequirementsCheckSpec} + * @public + */ + init { + val options = GoogleActionsV2TransactionRequirementsCheckSpec() + options.init() + this._data(InputValueSpec.TransactionRequirementsCheckSpec) { + orderOptions = options.orderOptions + paymentOptions = options.paymentOptions + } + } +} diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Browse.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Browse.kt new file mode 100644 index 0000000..5f9dc50 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Browse.kt @@ -0,0 +1,83 @@ +package actions.service.actionssdk.conversation.response + +import actions.service.actionssdk.api.* + +data class BrowseCarouselOptions( + /** + * Sets the display options for the images in this carousel. + * @public + */ + var display: GoogleActionsV2UiElementsCarouselBrowseImageDisplayOptions? = null, + + /** + * List of 2-20 items to show in this carousel. Required. + * @public + */ + var items: MutableList? = null +) + +data class BrowseCarouselItemOptions( + /** + * Title of the option item. Required. + * @public + */ + var title: String? = null, + + /** + * The URL of the link opened by clicking the BrowseCarouselItem. Optional. + * @public + */ + var url: String? = null, + + /** + * Description text of the item. Optional. + * @public + */ + var description: String? = null, + + /** + * Footer text of the item. Optional. + * @public + */ + var footer: String? = null, + + /** + * Image to show on item. Optional. + * @public + */ + var image: GoogleActionsV2UiElementsImage? = null +) + +/** + * Class for initializing and constructing BrowseCarousel Items + * @public + */ +class BrowseCarouselItem(override var description: String? = null, + override var footer: String? = null, + override var image: GoogleActionsV2UiElementsImage? = null, + override var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? = null, + override var title: String? = null) : GoogleActionsV2UiElementsCarouselBrowseItem { + /** + * @param options BrowseCarouselItem options + * @public + */ + constructor(init: BrowseCarouselItemOptions.() -> Unit) : this() { + val options = BrowseCarouselItemOptions() + options.init() + title = options.title + openUrlAction = GoogleActionsV2UiElementsOpenUrlAction( + url = options.url) + description = options.description + footer = options.footer + image = options.image + } +} + +//const isOptions = ( +//options: BrowseCarouselOptions | Api.GoogleActionsV2UiElementsCarouselBrowseItem, +//): options is BrowseCarouselOptions => { +// const test = options as BrowseCarouselOptions +// return Array.isArray(test.items) +//} + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Image.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Image.kt new file mode 100644 index 0000000..177d19a --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Image.kt @@ -0,0 +1,28 @@ +package actions.service.actionssdk.conversation.response + + +data class ImageOptions( + /** + * Image source URL. + * @public + */ + var url: String, + + /** + * Text to replace for image for accessibility. + * @public + */ + var alt: String, + + /** + * Height of the image. + * @public + */ + var height: Int? = null, + + /** + * Width of the image. + * @public + */ + var width: Int? = null) + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Linkout.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Linkout.kt new file mode 100644 index 0000000..595701f --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Linkout.kt @@ -0,0 +1,17 @@ +package actions.service.actionssdk.conversation.response + + +data class LinkOutSuggestionOptions( + /** + * Text shown on the suggestion chip. + * @public + */ + var name: String, + + /** + * String URL to open. + * @public + */ + var url: String) + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Media.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Media.kt new file mode 100644 index 0000000..592327f --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Media.kt @@ -0,0 +1,60 @@ +package actions.service.actionssdk.conversation.response + +import actions.service.actionssdk.api.GoogleActionsV2MediaResponseMediaType +import actions.service.actionssdk.api.GoogleActionsV2UiElementsImage + +data class MediaObjectOptions( + /** + * MediaObject URL. + * @public + */ + var url: String? = null, + + var description: String? = null, + + /** + * Name of the MediaObject. + * @public + */ + var name: String? = null, + + /** + * Icon image. + * @public + */ + var icon: GoogleActionsV2UiElementsImage? = null, + + /** + * Large image. + * @public + */ + var image: GoogleActionsV2UiElementsImage? = null +) + +fun String.toMediaObject(): MediaObject = MediaObject(contentUrl = this) + + +//typealias MediaObjectString = GoogleActionsV2MediaObject | string + +data class MediaResponseOptions( + /** + * Array of MediaObject held in the MediaResponse. + * @public + */ + var objects: MutableList? = null, + /** + * Type of the media within this MediaResponse. + * Defaults to 'AUDIO' + * @public + */ + var type: GoogleActionsV2MediaResponseMediaType? = null +) + +//const isOptions = ( +//options: MediaResponseOptions | MediaObjectString, +//): options is MediaResponseOptions => { +// const test = options as MediaResponseOptions +// return Array.isArray(test.objects) +//} + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Order.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Order.kt new file mode 100644 index 0000000..627204e --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Order.kt @@ -0,0 +1,3 @@ +package actions.service.actionssdk.conversation.response + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Response.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Response.kt new file mode 100644 index 0000000..b07cd2e --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Response.kt @@ -0,0 +1,771 @@ +package actions.service.actionssdk.conversation.response + +import actions.ApiClientObjectMap +import actions.ProtoAny +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.InputValueSpec +import actions.service.actionssdk.conversation.IntentEnum +import actions.service.actionssdk.conversation.question.option.* +import actions.service.actionssdk.conversation.response.card.BasicCardOptions +import actions.service.actionssdk.conversation.response.card.TableOptions +import actions.service.actionssdk.push + +sealed class Response + + +/** + * Sealed class of all RichResponseItem types + * Equivalent to TypeScript Union: + * type RichResponseItem = +SimpleResponse | +BasicCard | +Table | +BrowseCarousel | +MediaResponse | +OrderUpdate | +LinkOutSuggestion | +Api.GoogleActionsV2RichResponseItem + + * String type is handled in separate functions + */ +sealed class RichResponseItem : Response() + + +/** + * Class for initializing and constructing Rich Responses with chainable interface. + * @public + */ +class RichResponse(override var items: MutableList? = null, + override var linkOutSuggestion: GoogleActionsV2UiElementsLinkOutSuggestion? = null, + override var suggestions: MutableList? = null) : GoogleActionsV2RichResponse, Response() { + /** + * @param options RichResponse options + * @public + */ + constructor(options: RichResponseOptions) : this() { + this.items = mutableListOf() + if (options.items != null && options.items?.isNotEmpty() == true) { + add(*options.items!!.toTypedArray()) + } + val link = options.link + val suggestions = options.suggestions + this.linkOutSuggestion = link + if (suggestions != null) { + this.addSuggestion(*suggestions.toTypedArray()) + } + } + + /** + * @param items RichResponse items + * @public + */ + constructor(items: MutableList) : this() { + this.items = mutableListOf() + TODO("IS this needed?") + } + + /** + * @param items RichResponse items + * @public + */ + constructor(vararg items: RichResponseItem) : this() { + this.items = mutableListOf() + this.add(*items) + } + +// constructor(options?: RichResponseOptions | RichResponseItem[] | RichResponseItem, +// ...items: RichResponseItem[], +// ) +// { +// this.items = [] +// if (!options) { +// return +// } +// if (Array.isArray(options)) { +// this.add(... options) +// return +// } +// if (isOptions(options)) { +// if (options.items) { +// this.add(... options . items) +// } +// const { link, suggestions } = options +// this.linkOutSuggestion = link +// if (suggestions) { +// if (Array.isArray(suggestions)) { +// this.addSuggestion(... suggestions) +// } else { +// this.addSuggestion(suggestions) +// } +// } +// return +// } +// this.add(options, ... items) +// } + + constructor(options: RichResponseOptions? = null, vararg items: RichResponseItem) : this() { + + } + + constructor(options: MutableList? = null, vararg items: RichResponseItem) : this() { + + } + + constructor(options: RichResponseItem? = null, vararg items: RichResponseItem) : this() { + + } + + fun add(vararg items: String) { + items.forEach { + this.add(SimpleResponse(it)) + } + } + + /** + * Add a RichResponse item + * @public + */ + fun add(vararg items: RichResponseItem): RichResponse { + if (this.items == null) { + this.items = mutableListOf() + } + items.forEach { + when (it) { +// is String -> { //Handled in fun add(vararg items: String)} + + is LinkOutSuggestion -> this.linkOutSuggestion = it + + is SimpleResponse -> this.items!!.add { simpleResponse = it } + + is BasicCard -> + this.items!!.add { basicCard = it } + + is Table -> + this.items!!.add { tableCard = it } + + + is BrowseCarousel -> + this.items!!.add { carouselBrowse = it } + + + is MediaResponse -> + this.items!!.add { mediaResponse = it } + + is OrderUpdate -> { + this.items!!.add { structuredResponse = GoogleActionsV2StructuredResponse(orderUpdate = it) } + } + } + } + return this + } + + fun addSuggestion(vararg suggestions: String): RichResponse { + if (this.suggestions == null) { + this.suggestions = mutableListOf() + } + suggestions.forEach { + this.suggestions?.push(GoogleActionsV2UiElementsSuggestion(it)) + } + return this + } + + /** + * Adds a single suggestion or list of suggestions to list of items. + * @public + */ + fun addSuggestion(vararg suggestions: Suggestions): RichResponse { + suggestions.forEach { + this.suggestions?.push(*it.suggestions.toTypedArray()) + } + return this + } + + /** + * Adds a single suggestion or list of suggestions to list of items. + * @public + */ + fun addSuggestion(vararg suggestions: GoogleActionsV2UiElementsSuggestion): RichResponse { + suggestions.forEach { + this.suggestions?.push(it) + } + return this + } +} + +fun MutableList.add(init: GoogleActionsV2RichResponseItem.() -> Unit) { + val item = GoogleActionsV2RichResponseItem() + item.init() + add(item) +} + +/** + * Image type shown on visual elements. + * @public + */ +data class Image(override var accessibilityText: String? = null, + override var height: Int? = null, + override var url: String? = null, + override var width: Int? = null) : GoogleActionsV2UiElementsImage, Response() { + /** + * @param options Image options + * @public + */ + constructor(option: ImageOptions? = null) : this(url = option?.url, + accessibilityText = option?.alt, + height = option?.height, + width = option?.width) + + constructor(init: ImageOptions.() -> Unit) : this({ val options = ImageOptions(url = "", alt = ""); options.init(); options }.invoke()) +} + + +/** + * Suggestions to show with response. + * @public + */ +data class Suggestions( + var suggestions: MutableList = mutableListOf()) : Response() { + + /** + * @param suggestions Texts of the suggestions. + * @public + */ + constructor(vararg suggestions: String) : this(suggestions = suggestions.map { GoogleActionsV2UiElementsSuggestion(title = it) }.toMutableList()) + +// constructor(suggestions: Array) : this(suggestions = suggestions.map { GoogleActionsV2UiElementsSuggestion(title = it) }.asReversed().toMutableList()) + + fun add(vararg suggs: String): Suggestions { + this.suggestions = suggs.map { GoogleActionsV2UiElementsSuggestion(title = it) }.toMutableList() + return this + } +} + + +/** + * Class for initializing and constructing MediaObject + * @public + */ +class MediaObject(override var contentUrl: String? = null, + override var description: String? = null, + override var icon: GoogleActionsV2UiElementsImage? = null, + override var largeImage: GoogleActionsV2UiElementsImage? = null, + override var name: String? = null) : GoogleActionsV2MediaObject, Response() { + /** + * @param options MediaObject options or just a string for the url + * @public + */ + constructor(init: MediaObjectOptions.() -> Unit) : this() { + val options = MediaObjectOptions() + options.init() + contentUrl = options.url + description = options.description + icon = options.icon + largeImage = options.image + name = options.name + } + + constructor(options: String) : this(contentUrl = options) +} + +abstract class Question(intent: IntentEnum) : GoogleActionsV2ExpectedIntent, Response() { + override var inputValueData: ProtoAny? = null + + override var intent: String? = null + + override var parameterName: String? = null + + init { + this.intent = intent.value + } + + fun _data(type: InputValueSpec, init: ProtoAny.() -> Unit) { + if (inputValueData == null) { + inputValueData = ProtoAny() + } + inputValueData?.`@type` = type.value + inputValueData?.init() + } +} + +abstract class SoloQuestion(intent: IntentEnum) : Question(intent) + + +/** + * Simple Response type. + * @public + */ + +data class SimpleResponse(override var displayText: String? = null, + override var ssml: String? = null, + override var textToSpeech: String? = null) : GoogleActionsV2SimpleResponse, RichResponseItem() { + /** + * @param options SimpleResponse options + * @public + */ + constructor(options: SimpleResponseOptions) : this(textToSpeech = options.speech, + displayText = options.text) + + constructor(init: SimpleResponseOptions.() -> Unit) : this({ val options = SimpleResponseOptions(speech = ""); options.init(); options }.invoke()) + + constructor(options: String? = null) : this(textToSpeech = options) +} + + +class BasicCard(override var buttons: MutableList? = null, + override var formattedText: String? = null, + override var image: GoogleActionsV2UiElementsImage? = null, + override var imageDisplayOptions: GoogleActionsV2UiElementsBasicCardImageDisplayOptions? = null, + override var subtitle: String? = null, + override var title: String? = null) : GoogleActionsV2UiElementsBasicCard, RichResponseItem() { + + constructor(options: BasicCardOptions) : this( + title = options.title, + subtitle = options.subtitle, + formattedText = options.text, + image = options.image, + buttons = options.buttons, + imageDisplayOptions = options.display + ) + + constructor(init: BasicCardOptions.() -> Unit) : this({ val options = BasicCardOptions(); options.init();options }.invoke()) +} + + +/** + * Creates a Table card. + * + * @example + * ```javascript + * + * // Simple table + * conv.ask('Simple Response') + * conv.ask(new Table({ + * dividers: true, + * columns: ['header 1', 'header 2', 'header 3'], + * rows: [ + * ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'], + * ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'], + * ], + * })) + * + * // All fields + * conv.ask('Simple Response') + * conv.ask(new Table({ + * title: 'Table Title', + * subtitle: 'Table Subtitle', + * image: new Image({ + * url: 'https://avatars0.githubusercontent.com/u/23533486', + * alt: 'Actions on Google' + * }), + * columns: [ + * { + * header: 'header 1', + * align: 'CENTER', + * }, + * { + * header: 'header 2', + * align: 'LEADING', + * }, + * { + * header: 'header 3', + * align: 'TRAILING', + * }, + * ], + * rows: [ + * { + * cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'], + * dividerAfter: false, + * }, + * { + * cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'], + * dividerAfter: true, + * }, + * { + * cells: ['row 3 item 1', 'row 3 item 2', 'row 3 item 3'], + * }, + * ], + * buttons: new Button({ + * title: 'Button Title', + * url: 'https://github.com/actions-on-google' + * }), + * })) + * ``` + * + * @public + */ +data class Table(override var buttons: MutableList? = null, + override var columnProperties: MutableList? = null, + override var image: GoogleActionsV2UiElementsImage? = null, + override var rows: MutableList? = null, + override var subtitle: String? = null, + override var title: String? = null) : GoogleActionsV2UiElementsTableCard, RichResponseItem() { + + constructor(init: TableOptions.() -> Unit) : this( + +// rows = options.rows.map(row => Array.isArray(row) ? { +// cells: row.map(text => ({ text })), +// dividerAfter: options.dividers, +// } as Api.GoogleActionsV2UiElementsTableCardRow : { +// cells: row.cells!.map(cell => typeof cell === 'string' ? { text: cell } : cell), +// dividerAfter: typeof row.dividerAfter === 'undefined' ? options.dividers : row.dividerAfter, +// } as Api.GoogleActionsV2UiElementsTableCardRow) +// const { columnProperties, columns, buttons } = options +// if (columnProperties) { +// this.columnProperties = toColumnProperties(columnProperties) +// } +// if (typeof columns !== 'undefined') { +// if (!this.columnProperties) { +// this.columnProperties = [] +// } +// const properties = typeof columns === 'number' ? +// new Array(columns).fill({}) : +// toColumnProperties(columns) +// properties.forEach((v, i) => { +// if (!this.columnProperties![i]) { +// this.columnProperties![i] = properties[i] +// } +// }) +// } +// this.buttons = if (options.buttons) +//} +//} + ) { + val options = TableOptions() + options.init() + title = options.title + subtitle = options.subtitle + image = options.image + } +} + + +/** + * Class for initializing and constructing MediaResponse. + * @public + */ +class MediaResponse() : GoogleActionsV2MediaResponse, RichResponseItem() { + override var mediaObjects: MutableList? = null + + override var mediaType: GoogleActionsV2MediaResponseMediaType? = null + + + /** + * @param objects MediaObjects + * @public + */ + constructor(vararg objects: MediaObject) : this() { + this.mediaType = GoogleActionsV2MediaResponseMediaType.AUDIO + this.mediaObjects = objects.toMutableList() //objects.map(o => toMediaObject (o)) + } + + constructor(vararg strings: String) : this() { + this.mediaType = GoogleActionsV2MediaResponseMediaType.AUDIO + this.mediaObjects = strings.map { it.toMediaObject() }.toMutableList() + } + + /** + * @param options MediaResponse options + * @public + */ + constructor(init: MediaResponseOptions.() -> Unit) : this() { + val options = MediaResponseOptions() + options.init() + this.mediaType = GoogleActionsV2MediaResponseMediaType.AUDIO + + if (options != null) { + this.mediaObjects = mutableListOf() + return + } + + + + this.mediaType = options.type ?: this.mediaType + this.mediaObjects = options.objects?.toMutableList() + + } +} + + +/** + * Class for initializing and constructing OrderUpdate + * Delegates to MutableMap so dynamic fields may be added. + * @public + */ +data class OrderUpdate(override var actionOrderId: String? = null, + override var cancellationInfo: GoogleActionsV2OrdersCancellationInfo? = null, + override var fulfillmentInfo: GoogleActionsV2OrdersFulfillmentInfo? = null, + override var googleOrderId: String? = null, + override var inTransitInfo: GoogleActionsV2OrdersInTransitInfo? = null, + override var infoExtension: ApiClientObjectMap? = null, + override var lineItemUpdates: ApiClientObjectMap? = null, + override var orderManagementActions: MutableList? = null, + override var orderState: GoogleActionsV2OrdersOrderState? = null, + override var receipt: GoogleActionsV2OrdersReceipt? = null, + override var rejectionInfo: GoogleActionsV2OrdersRejectionInfo? = null, + override var returnInfo: GoogleActionsV2OrdersReturnInfo? = null, + override var totalPrice: GoogleActionsV2OrdersPrice? = null, + override var updateTime: GoogleTypeTimeOfDay? = null, + override var userNotification: GoogleActionsV2OrdersOrderUpdateUserNotification? = null, + override var orderDate: String? = null, + override var locale: String? = null) : GoogleActionsV2OrdersOrderUpdate, MutableMap by mutableMapOf(), RichResponseItem() { + /** + * @param options The raw {@link GoogleActionsV2OrdersOrderUpdate} + * @public + */ + constructor(options: GoogleActionsV2OrdersOrderUpdate? = null) : this( + actionOrderId = options?.actionOrderId, + cancellationInfo = options?.cancellationInfo, + fulfillmentInfo = options?.fulfillmentInfo, + googleOrderId = options?.googleOrderId, + inTransitInfo = options?.inTransitInfo, + infoExtension = options?.infoExtension, + lineItemUpdates = options?.lineItemUpdates, + orderManagementActions = options?.orderManagementActions, + orderState = options?.orderState, + receipt = options?.receipt, + rejectionInfo = options?.rejectionInfo, + returnInfo = options?.returnInfo, + totalPrice = options?.totalPrice, + updateTime = options?.updateTime, + userNotification = options?.userNotification + ) + + constructor(init: OrderUpdate.() -> Unit) : this() { + val options = OrderUpdate() + options.init() + actionOrderId = options.actionOrderId + cancellationInfo = options.cancellationInfo + fulfillmentInfo = options.fulfillmentInfo + googleOrderId = options.googleOrderId + inTransitInfo = options.inTransitInfo + infoExtension = options.infoExtension + lineItemUpdates = options.lineItemUpdates + orderManagementActions = options.orderManagementActions + orderState = options.orderState + receipt = options.receipt + rejectionInfo = options.rejectionInfo + returnInfo = options.returnInfo + totalPrice = options.totalPrice + updateTime = options.updateTime + userNotification = options.userNotification + } + + fun orderState(init: GoogleActionsV2OrdersOrderState.() -> Unit) { + this.orderState = GoogleActionsV2OrdersOrderState() + this.orderState?.init() + } + + fun receipt(init: GoogleActionsV2OrdersReceipt.() -> Unit) { + this.receipt = GoogleActionsV2OrdersReceipt() + this.receipt?.init() + } + + fun orderManagementActions(vararg init: GoogleActionsV2OrdersOrderUpdateAction.() -> Unit) { + this.orderManagementActions = init.map { + val action = GoogleActionsV2OrdersOrderUpdateAction() + action.it() + action + }.toMutableList() + } + + fun userNotification(init: GoogleActionsV2OrdersOrderUpdateUserNotification.() -> Unit) { + this.userNotification = GoogleActionsV2OrdersOrderUpdateUserNotification() + this.userNotification?.init() + } +} + + +/** + * Link Out Suggestion. + * Used in rich response as a suggestion chip which, when selected, links out to external URL. + * @public + */ +data class LinkOutSuggestion(override var destinationName: String? = null, + override var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? = null, + override var url: String? = null) : GoogleActionsV2UiElementsLinkOutSuggestion, RichResponseItem() { + /** + * @param options LinkOutSuggestion options + * @public + */ + constructor(options: LinkOutSuggestionOptions) : this( + destinationName = options.name, + url = options.url) + + constructor(init: LinkOutSuggestionOptions.() -> Unit) : this({ val options = LinkOutSuggestionOptions(name = "", url = ""); options.init(); options }.invoke()) +} + + +data class GoogleActionsV2RichResponseItem( + /** + * A basic card. + */ + var basicCard: GoogleActionsV2UiElementsBasicCard? = null, + /** + * Carousel browse card. + */ + var carouselBrowse: GoogleActionsV2UiElementsCarouselBrowse? = null, + /** + * Response indicating a set of media to be played. + */ + var mediaResponse: GoogleActionsV2MediaResponse? = null, + /** + * Voice and text-only response. + */ + var simpleResponse: GoogleActionsV2SimpleResponse? = null, + /** + * Structured payload to be processed by Google. + */ + var structuredResponse: GoogleActionsV2StructuredResponse? = null, + /** + * Table card. + */ + var tableCard: GoogleActionsV2UiElementsTableCard? = null +) : RichResponseItem() + + +/** + * Class for initializing and constructing Browse Carousel. + * @public + */ +class BrowseCarousel(override var imageDisplayOptions: GoogleActionsV2UiElementsCarouselBrowseImageDisplayOptions? = null, + override var items: MutableList? = null) : GoogleActionsV2UiElementsCarouselBrowse, RichResponseItem() { + + /** + * @param items BrowseCarousel items + * @public + */ + constructor(vararg items: GoogleActionsV2UiElementsCarouselBrowseItem?) : this() { + this.items = items.filterNotNull().toMutableList() + } + + /** + * @param item BrowseCarousel item + * @public + */ + constructor(item: GoogleActionsV2UiElementsCarouselBrowseItem?) : this() { + if (item == null) { + this.items = mutableListOf() + } else { + items?.add(item) + } + } + + /** + * @param options BrowseCarouselOptions + * @public + */ + constructor(init: BrowseCarouselOptions.() -> Unit) : this() { + val options = BrowseCarouselOptions() + options.init() + if (options == null) { + this.items = mutableListOf() + return + } + + this.imageDisplayOptions = options.display + this.items = options.items + return + } +} + +class List(init: ListOptions2.() -> Unit) : Question(IntentEnum.OPTION) { + + init { + val options = ListOptions2() + options.init() + this._data(InputValueSpec.OptionValueSpec) { + listSelect = actions.service.actionssdk.api.GoogleActionsV2UiElementsListSelect( + title = options.title, + items = options.items.toGoogleActionsV2ListItem() + ) + } + } +} + + +/** + * Asks to collect user"s input with a carousel. + * + * @example + * ```javascript + * + * // Actions SDK + * val app = actionssdk() + * + * app.intent("actions.intent.MAIN", conv => { + * conv.ask("Which of these looks good?") + * conv.ask(new Carousel({ + * items: { + * [SELECTION_KEY_ONE]: { + * title: "Number one", + * description: "Description of number one", + * synonyms: ["synonym of KEY_ONE 1", "synonym of KEY_ONE 2"], + * }, + * [SELECTION_KEY_TWO]: { + * title: "Number two", + * description: "Description of number one", + * synonyms: ["synonym of KEY_TWO 1", "synonym of KEY_TWO 2"], + * } + * } + * })) + * }) + * + * app.intent("actions.intent.OPTION", (conv, input, option) => { + * if (option === SELECTION_KEY_ONE) { + * conv.close("Number one is a great choice!") + * } else { + * conv.close("Number two is also a great choice!") + * } + * }) + * + * // Dialogflow + * val app = dialogflow() + * + * app.intent("Default Welcome Intent", conv => { + * conv.ask("Which of these looks good?") + * conv.ask(new Carousel({ + * items: { + * [SELECTION_KEY_ONE]: { + * title: "Number one", + * description: "Description of number one", + * synonyms: ["synonym of KEY_ONE 1", "synonym of KEY_ONE 2"], + * }, + * [SELECTION_KEY_TWO]: { + * title: "Number two", + * description: "Description of number one", + * synonyms: ["synonym of KEY_TWO 1", "synonym of KEY_TWO 2"], + * } + * } + * })) + * }) + * + * // Create a Dialogflow intent with the `actions_intent_OPTION` event + * app.intent("Get Option", (conv, input, option) => { + * if (option === SELECTION_KEY_ONE) { + * conv.close("Number one is a great choice!") + * } else { + * conv.close("Number two is also a great choice!") + * } + * }) + * ``` + * + * @public + */ +class Carousel(init: CarouselOptions.() -> Unit) : Question(IntentEnum.OPTION) { + + /** + * @param options Carousel option + * @public + */ + init { + val options = CarouselOptions() + options.init() + + this._data(actions.service.actionssdk.conversation.InputValueSpec.OptionValueSpec) { + carouselSelect = actions.service.actionssdk.api.GoogleActionsV2UiElementsCarouselSelect( + items = options.items.toGoogleActionsV2CarouselItem(), + imageDisplayOptions = options.display + ) + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Rich.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Rich.kt new file mode 100644 index 0000000..0832722 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Rich.kt @@ -0,0 +1,37 @@ +package actions.service.actionssdk.conversation.response + +import actions.service.actionssdk.api.GoogleActionsV2UiElementsLinkOutSuggestion + + +interface RichResponseOptions { + /** + * Ordered list of either SimpleResponse objects or BasicCard objects. + * First item must be SimpleResponse. There can be at most one card. + * @public + */ + var items: MutableList? + + /** + * Ordered list of text suggestions to display. Optional. + * @public + */ + var suggestions: MutableList? //TODO support: | Suggestions + + /** + * Link Out Suggestion chip for this rich response. Optional. + * @public + */ + var link: GoogleActionsV2UiElementsLinkOutSuggestion? +} + +//const isOptions = ( +//options: RichResponseOptions | RichResponseItem, +//): options is RichResponseOptions => { +// const test = options as RichResponseOptions +// return typeof test.link === 'object' || +// Array.isArray(test.items) || +// Array.isArray(test.suggestions) || +// test.suggestions instanceof Suggestions +//} + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/RichResponseItem.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/RichResponseItem.kt new file mode 100644 index 0000000..ebde693 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/RichResponseItem.kt @@ -0,0 +1,7 @@ +package actions.service.actionssdk.conversation.response + +import actions.ApiClientObjectMap +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.response.card.BasicCardOptions +import actions.service.actionssdk.conversation.response.card.TableOptions + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Simple.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Simple.kt new file mode 100644 index 0000000..99f2456 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Simple.kt @@ -0,0 +1,16 @@ +package actions.service.actionssdk.conversation.response + + +data class SimpleResponseOptions( + /** + * Speech to be spoken to user. SSML allowed. + * @public + */ + var speech: String, + + /** + * Optional text to be shown to user + * @public + */ + var text: String? = null +) diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Suggestion.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Suggestion.kt new file mode 100644 index 0000000..0dc572b --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Suggestion.kt @@ -0,0 +1,4 @@ +package actions.service.actionssdk.conversation.response + + + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Url.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Url.kt new file mode 100644 index 0000000..5ed7776 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/Url.kt @@ -0,0 +1,10 @@ +package actions.service.actionssdk.conversation.response + +import actions.service.actionssdk.api.GoogleActionsV2DevicesAndroidApp +import actions.service.actionssdk.api.GoogleActionsV2UiElementsOpenUrlAction +import actions.service.actionssdk.api.GoogleActionsV2UiElementsOpenUrlActionUrlTypeHint + +interface OpenUrlActionOptions { + var url: String? +} + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Basic.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Basic.kt new file mode 100644 index 0000000..e60a69d --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Basic.kt @@ -0,0 +1,19 @@ +package actions.service.actionssdk.conversation.response.card + +import actions.service.actionssdk.api.GoogleActionsV2UiElementsBasicCardImageDisplayOptions +import actions.service.actionssdk.api.GoogleActionsV2UiElementsButton +import actions.service.actionssdk.api.GoogleActionsV2UiElementsImage + +data class BasicCardOptions( + var title: String? = null, + + var subtitle: String? = null, + + var text: String? = null, + + var image: GoogleActionsV2UiElementsImage? = null, + + var buttons: MutableList? = null, + + var display: GoogleActionsV2UiElementsBasicCardImageDisplayOptions? = null) + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Button.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Button.kt new file mode 100644 index 0000000..beaa683 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Button.kt @@ -0,0 +1,48 @@ +package actions.service.actionssdk.conversation.response.card + +import actions.service.actionssdk.api.GoogleActionsV2UiElementsButton +import actions.service.actionssdk.api.GoogleActionsV2UiElementsOpenUrlAction + + +data class ButtonOptions( + /** + * Text shown on the button. + * @public + */ + var title: String, + + /** + * String URL to open. + * @public + */ + var url: String? = null, + + /** + * Action to take when selected. Recommended to use the url property for simple web page url open. + * @public + */ + var action: GoogleActionsV2UiElementsOpenUrlAction? = null +) + +/** + * Card Button. Shown below cards. Open a URL when selected. + * @public + */ +data class Button(override var openUrlAction: GoogleActionsV2UiElementsOpenUrlAction? = null, + override var title: String? = null) : GoogleActionsV2UiElementsButton { + /** + * @param options Button options + * @public + */ + constructor(options: ButtonOptions) : this( + title = options.title, + openUrlAction = when { + options.url != null -> GoogleActionsV2UiElementsOpenUrlAction(url = options.url) + options.action != null -> options.action + else -> null + }) + + constructor(init: ButtonOptions.() -> Unit): this({val options = ButtonOptions(title = ""); options.init(); options}.invoke()) + +} + diff --git a/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Table.kt b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Table.kt new file mode 100644 index 0000000..4ca7ae1 --- /dev/null +++ b/common/src/main/kotlin/actions/service/actionssdk/conversation/response/card/Table.kt @@ -0,0 +1,114 @@ +package actions.service.actionssdk.conversation.response.card + +import actions.service.actionssdk.api.* + +data class TableColumn( + /** + * Alias for `horizontalAlignment` + * + * Horizontal alignment of content w.r.t column. If unspecified, content + * will be aligned to the leading edge. + * @public + */ + var align: GoogleActionsV2UiElementsTableCardColumnPropertiesHorizontalAlignment?, + override var header: String?, + override var horizontalAlignment: GoogleActionsV2UiElementsTableCardColumnPropertiesHorizontalAlignment? +) : GoogleActionsV2UiElementsTableCardColumnProperties + +data class TableRow ( + /** + * Cells in this row. + * The first 3 cells are guaranteed to be shown but others might be cut on certain surfaces. + * Please test with the simulator to see which cells will be shown for a given surface. + * + * When provided as a string array, creates the cells as text. + * @public + */ + var cells: MutableList? = null, //| string)[] + /** + * Indicates whether there should be a divider after each row. + * + * Overrides top level `dividers` property for this specific row if set. + * @public + */ + var dividerAfter: Boolean? = null +) + +data class TableOptions( + /** + * Overall title of the table. + * + * Must be set if subtitle is set. + * @public + */ + var title: String? = null, + + /** + * Subtitle for the table. + * @public + */ + var subtitle: String? = null, + + /** + * Image associated with the table. + * @public + */ + var image: GoogleActionsV2UiElementsImage? = null, + + /** + * Headers and alignment of columns with shortened name. + * Alias of `columnProperties` with the additional capability of accepting a number type. + * + * This property or `columnProperties` is required. + * + * When provided as string array, just the header field is set per column. + * When provided a number, it represents the number of elements per row. + * @public + */ + var columns: MutableList? = null,//(TableColumn | string)[] | number + + /** + * Headers and alignment of columns. + * + * This property or `columns` is required. + * + * When provided as string array, just the header field is set per column. + * @public + */ + var columnProperties: MutableList? = null,//(TableColumn | string)[] + + /** + * Row data of the table. + * + * The first 3 rows are guaranteed to be shown but others might be cut on certain surfaces. + * Please test with the simulator to see which rows will be shown for a given surface. + * + * On surfaces that support the WEB_BROWSER capability, you can point the user to + * a web page with more data. + * @public + */ + var rows: MutableList? = null, //(TableRow | string[])[] + + /** + * Default dividerAfter for all rows. + * Individual rows with `dividerAfter` set will override for that specific row. + * @public + */ + var dividers: Boolean? = null, + + /** + * Buttons for the Table. + * Currently at most 1 button is supported. + * @public + */ + var buttons: GoogleActionsV2UiElementsButton? = null //GoogleActionsV2UiElementsButton | Api.GoogleActionsV2UiElementsButton[] +) + +//const toColumnProperties = (columns: (TableColumn | string)[]) => columns.map(column => +//typeof column === 'string' ? { +// header: column, +//} : { +// header: column.header, +// horizontalAlignment: column.horizontalAlignment || column.align, +//} as Api.GoogleActionsV2UiElementsTableCardColumnProperties) + diff --git a/common/src/main/kotlin/actions/service/dialogflow/Context.kt b/common/src/main/kotlin/actions/service/dialogflow/Context.kt new file mode 100644 index 0000000..8117879 --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/Context.kt @@ -0,0 +1,292 @@ +package actions.service.dialogflow + +import actions.service.dialogflow.api.DialogflowV1Context +import actions.service.dialogflow.api.DialogflowV1Parameters +import actions.service.dialogflow.api.GoogleCloudDialogflowV2Context + +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @public */ +//typealias Parameters = MutableMap + +/** @public */ +class Contexts : MutableMap by mutableMapOf() {} + +//export interface Contexts { +// /** @public */ +// [context: string]: Context | undefined +//} + +/** @public */ +class OutputContexts : MutableMap by mutableMapOf() { + /** @public */ +// [context: string]: OutputContext | undefined +} + +/** @public */ +class Context( + /** + * Full name of the context. + * @public + */ + var name: String? = null, + + /** + * Remaining number of intents + * @public + */ + lifespan: Int? = null, + + /** + * The context parameters from the current intent. + * Context parameters include parameters collected in previous intents + * during the lifespan of the given context. + * + * See {@link https://dialogflow.com/docs/concept-actions#section-extracting-values-from-contexts| + * here}. + * + * @example + * ```javascript + * + * app.intent("Tell Greeting", conv => { + * val context1 = conv.contexts.get("context1") + * val parameters = context1.parameters + * val color = parameters.color + * val num = parameters.num + * }) + * + * // Using destructuring + * app.intent("Tell Greeting", conv => { + * val context1 = conv.contexts.get("context1") + * val { color, num } = context1.parameters + * }) + * ``` + * + * @public + */ + parameters: DialogflowV1Parameters? = null +) : OutputContext(lifespan = lifespan, parameters = parameters) + +/** @public */ +open class OutputContext( + /** @public */ + var lifespan: Int?, + + /** @public */ + var parameters: DialogflowV1Parameters? +) + +//typeof (context as ApiV1.DialogflowV1Context).lifespan === "number" + +val contextNameRegex by lazy { """([^/]+)?$""".toRegex() } + +class ContextValues { + /** @public */ + var input: Contexts? = null + + /** @public */ + var output: OutputContexts? = null + + private var _session: String? = null + + constructor(outputContexts: MutableList?, session: String? = null, flag: Boolean) { + this.input = Contexts() + this._session = session + outputContexts?.forEach { + val name = it.name + val parameters = it.parameters + val lifespanCount = it.lifespanCount + //TODO test this regex + val find = contextNameRegex.find(name) + val first = find?.groups?.first()?.value ?: name + this.input?.put(first, DialogflowV1Context(name = name, + lifespan = lifespanCount, + parameters = parameters)) + } + + this.output = OutputContexts() + } + + /** @hidden */ + constructor(outputContexts: MutableList?, session: String? = null) { + this.input = Contexts() + this._session = session + outputContexts?.forEach { + val name = it.name + val parameters = it.parameters + val lifespan = it.lifespan + if (name != null) { + this.input?.put(name, DialogflowV1Context(name = name, + lifespan = lifespan, + parameters = parameters)) + } + + } + this.output = OutputContexts() + } + + /** @hidden */ + fun _serialize(): MutableList { + return this.output?.map { + GoogleCloudDialogflowV2Context( + name = "${this._session}/contexts/${it.key}", + lifespanCount = it.value.lifespan ?: 0, + parameters = it.value.parameters + ) + }?.toMutableList() ?: mutableListOf() + /*).map((name): Api.GoogleCloudDialogflowV2Context => { + val { lifespan, parameters } = this.output[name]! + return { + name: `${this._session}/contexts/${name}`, + lifespanCount: lifespan, + parameters, + } + }) + */ + } + + /** @hidden */ + fun _serializeV1(): MutableList { + return this.output?.map { + DialogflowV1Context( + name = it.key, + lifespan = it.value.lifespan ?: 0, + parameters = it.value.parameters + ) + }?.toMutableList() ?: mutableListOf() + + /* + (name): ApiV1.DialogflowV1Context => { + val { lifespan, parameters } = this.output[name]! + return { + name, + lifespan, + parameters, + } + }) + } + */ + } + + /** + * Returns the incoming context by name for this intent. + * + * @example + * ```javascript + * + * val AppContexts = { + * NUMBER: "number", + * } + * + * val app = dialogflow() + * + * app.intent("Default Welcome Intent", conv => { + * conv.contexts.set(AppContexts.NUMBER, 1) + * conv.ask("Welcome to action snippets! Say a number.") + * }) + * + * // Create intent with "number" context as requirement + * app.intent("Number Input", conv => { + * val context = conv.contexts.get(AppContexts.NUMBER) + * }) + * ``` + * + * @param name The name of the Context to retrieve. + * @return Context value matching name or undefined if no matching context. + * @public + */ + fun get(name: String): DialogflowV1Context? { + return this.input?.get(name) + } + + /** + * Set a new context for the current intent. + * + * @example + * ```javascript + * + * val AppContexts = { + * NUMBER: "number", + * } + * + * val app = dialogflow() + * + * app.intent("Default Welcome Intent", conv => { + * conv.contexts.set(AppContexts.NUMBER, 1) + * conv.ask("Welcome to action snippets! Say a number.") + * }) + * + * // Create intent with "number" context as requirement + * app.intent("Number Input", conv => { + * val context = conv.contexts.get(AppContexts.NUMBER) + * }) + * ``` + * + * @param name Name of the context. Dialogflow converts to lowercase. + * @param lifespan Context lifespan. + * @param parameters Context parameters. + * @public + */ + fun set(name: String, lifespan: Int, parameters: DialogflowV1Parameters? = null) { + output?.put(name, OutputContext( + lifespan, + parameters)) + } + + /** @public */ + fun delete(name: String) { + this.set(name, 0) + } + + /** + * Returns the incoming contexts for this intent as an iterator. + * + * @example + * ```javascript + * + * val AppContexts = { + * NUMBER: "number", + * } + * + * val app = dialogflow() + * + * app.intent("Default Welcome Intent", conv => { + * conv.contexts.set(AppContexts.NUMBER, 1) + * conv.ask("Welcome to action snippets! Say a number.") + * }) + * + * // Create intent with "number" context as requirement + * app.intent("Number Input", conv => { + * for (val context of conv.contexts) { + * // do something with the contexts + * } + * }) + * ``` + * + * @public + */ + +//todo see if we can implement 'in' function to closely match js. + inline fun forEach(action: (ContextValues) -> Unit) { +// [Symbol.iterator]() { + TODO("iterate through Context - fix generic contexts through base class or intermediate types") +// val contexts = values(this.input) as Context[] +// return contexts[Symbol.iterator]() + // suppose to be Array.prototype.values(), but can"t use because of bug: + // https://bugs.chromium.org/p/chromium/issues/detail?id=615873 + } +} diff --git a/common/src/main/kotlin/actions/service/dialogflow/Conv.kt b/common/src/main/kotlin/actions/service/dialogflow/Conv.kt new file mode 100644 index 0000000..7d18c3d --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/Conv.kt @@ -0,0 +1,380 @@ +package actions.service.dialogflow + +import actions.ProtoAny +import actions.expected.Serializer +import actions.framework.Headers +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import actions.service.actionssdk.api.GoogleActionsV2RichResponse +import actions.service.actionssdk.api.GoogleActionsV2SimpleResponse +import actions.service.actionssdk.conversation.Conversation +import actions.service.actionssdk.conversation.ConversationBaseOptions +import actions.service.actionssdk.conversation.ConversationOptions +import actions.service.actionssdk.conversation.ConversationOptionsInit +import actions.service.dialogflow.api.* + +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const val APP_DATA_CONTEXT = "_actions_on_google" +const val APP_DATA_CONTEXT_LIFESPAN = 99 + +/** @hidden */ +data class SystemIntent( + var intent: String? = null, + var data: ProtoAny) + +/** @hidden */ +data class GoogleAssistantResponse( + var expectUserResponse: Boolean? = null, + var noInputPrompts: MutableList? = null, + var isSsml: Boolean? = null, + var richResponse: GoogleActionsV2RichResponse? = null, + var systemIntent: SystemIntent? = null, + var userStorage: String? = null +) + +/** @hidden */ +data class PayloadGoogle( + var google: GoogleAssistantResponse? = null) + +/** @public */ +data class DialogflowConversationOptions(var body: GoogleCloudDialogflowV2WebhookRequest? = null, + var bodyV1: DialogflowV1WebhookRequest? = null, + override var headers: Headers? = null, + override var init: ConversationOptionsInit?, + override var debug: Boolean? +) : ConversationBaseOptions { + fun isV1(): Boolean = bodyV1 != null + + fun getRequest(): GoogleActionsV2AppRequest? { + return if (isV1()) { + bodyV1?.originalRequest?.data + null + } else { + body?.originalDetectIntentRequest!!.payload + } + + } +} + +//val getRequest = ( +// body: Api.GoogleCloudDialogflowV2WebhookRequest | ApiV1.DialogflowV1WebhookRequest, +//) => { +// if (isV1(body)) { +// val { originalRequest = {} } = body +// val { data = {} } = originalRequest +// return data +// } +// return body.originalDetectIntentRequest!.payload! +//} + +/** @public */ +class DialogflowConversation(options: DialogflowConversationOptions) : Conversation( + ConversationOptions(request = options.getRequest(), + headers = options.headers, + init = options.init)) { + + /** @public */ + var body: GoogleCloudDialogflowV2WebhookRequest? + var bodyV1: DialogflowV1WebhookRequest? + + /** + * Get the current Dialogflow action name. + * + * @example + * ```javascript + * + * app.intent("Default Welcome Intent", conv => { + * val action = conv.action + * }) + * ``` + * + * @public + */ + var action: String + + /** + * Get the current Dialogflow intent name. + * + * @example + * ```javascript + * + * app.intent("Default Welcome Intent", conv => { + * val intent = conv.intent // will be "Default Welcome Intent" + * }) + * ``` + * + * @public + */ + var intent: String + + /** + * The Dialogflow parameters from the current intent. + * Values will only be a string, an Object, or undefined if not included. + * + * Will also be sent via intent handler 3rd argument which is the encouraged method to retrieve. + * + * @example + * ```javascript + * + * // Encouraged method through intent handler + * app.intent("Tell Greeting", (conv, params) => { + * val color = params.color + * val num = params.num + * }) + * + * // Encouraged method through destructuring in intent handler + * app.intent("Tell Greeting", (conv, { color, num }) => { + * // now use color and num as variables + * })) + * + * // Using conv.parameters + * app.intent("Tell Greeting", conv => { + * val parameters = conv.parameters + * // or destructed + * val { color, num } = conv.parameters + * }) + * ``` + * + * @public + */ + var parameters: DialogflowV1Parameters + + /** @public */ + var contexts: ContextValues + + /** @public */ + var incoming: Incoming + + /** + * The user"s raw input query. + * + * @example + * ```javascript + * + * app.intent("User Input", conv => { + * conv.close(`You said ${conv.query}`) + * }) + * ``` + * + * @public + */ + var query: String + + /** + * The session data in JSON format. + * Stored using contexts. + * + * @example + * ```javascript + * + * app.intent("Default Welcome Intent", conv => { + * conv.data.someProperty = "someValue" + * }) + * ``` + * + * @public + */ + var data: MutableMap = mutableMapOf() + + + /** @public */ + var version: Int + + /** @public */ + init { + + val init = options + + this.body = options.body + this.bodyV1 = options.bodyV1 + + if (options.isV1()) { + this.version = 1 + + val result = bodyV1?.result + + val action = result?.action ?: "" + val parameters = result?.parameters + val contexts = result?.contexts + val resolvedQuery = result?.resolvedQuery + val metadata = result?.metadata + val fulfillment = result?.fulfillment + val intentName = metadata?.intentName + + this.action = action + this.intent = intentName ?: "" + this.parameters = parameters ?: mutableMapOf() + this.contexts = ContextValues(contexts) + this.incoming = Incoming(fulfillment!!) + this.query = resolvedQuery ?: "" + } else { + this.version = 2 + + val queryResult = this.body?.queryResult + val action = queryResult?.action + val parameters = queryResult?.parameters + val outputContexts = queryResult?.outputContexts + val intent = queryResult?.intent + val queryText = queryResult?.queryText + val fulfillmentMessages = queryResult?.fulfillmentMessages + + val displayName = intent?.displayName + + this.action = action ?: "" + this.intent = displayName ?: "" + this.parameters = parameters ?: mutableMapOf() + this.contexts = ContextValues(outputContexts = outputContexts, session = this.body?.session, flag = true) + this.incoming = Incoming(fulfillmentMessages!!) + this.query = queryText ?: "" + } + + parameters.forEach { + //Not needed for kotlin SDK +// val value = this.parameters[key] +// if (typeof value !== "object") { + // Convert all non-objects to strings for consistency +// this.parameters[key] = String(value) +// } + } + + //TODO find a way to do this in kotlin +// this.data = (init && init.data) || {} as TConvData +// this.data = init.body?.originalDetectIntentRequest?.s + + val context = this.contexts.input?.get(APP_DATA_CONTEXT) + if (context != null) { + val data = context.parameters?.get("data")//?.data + if (data is String) { + this.data = Serializer.deserializeMap(data) + } + } + } + + /** + * Triggers an intent of your choosing by sending a followup event from the webhook. + * + * @example + * ```javascript + * + * val app = dialogflow() + * + * // Create a Dialogflow intent with event "apply-for-license-event" + * + * app.intent("Default Welcome Intent", conv => { + * conv.followup("apply-for-license-event", { + * date: new Date().toISOString(), + * }) + * // The dialogflow intent with the "apply-for-license-event" event + * // will be triggered with the given parameters `date` + * }) + * ``` + * + * @param event Name of the event + * @param parameters Parameters to send with the event + * @param lang The language of this query. + * See {@link https://dialogflow.com/docs/languages|Language Support} + * for a list of the currently supported language codes. + * Note that queries in the same session do not necessarily need to specify the same language. + * By default, it is the languageCode sent with Dialogflow"s queryResult.languageCode + * @public + */ + fun followup(event: String, parameters: DialogflowV1Parameters?, lang: String?) { + /* + if (this.version === 1) { + return this.json({ + followupEvent: { name: event, + data: parameters, + }, + }) + } + val body = this.body as GoogleCloudDialogflowV2WebhookRequest + return this.json({ + followupEventInput: { + name: event, + parameters, + languageCode: lang || body.queryResult!.languageCode, + }, + }) + */ + } + + + fun commonPayload(): Data { + + return if (platformData != null) { + platformData!! + } else { + val response = this.response() + val richResponse = response.richResponse + val expectUserResponse = response.expectUserResponse ?: true + val userStorage = response.userStorage + val expectedIntent = response.expectedIntent + val systemIntent = if (expectedIntent?.intent != null) + SystemIntent( + intent = expectedIntent?.intent, + data = expectedIntent?.inputValueData ?: ProtoAny()) + else + null + + val googleData = Data() + googleData.google = GoogleAssistantResponse( + expectUserResponse = expectUserResponse, + richResponse = richResponse!!, + userStorage = userStorage, + systemIntent = systemIntent + ) + googleData + } + + } + + fun serializeV1(): DialogflowV1WebhookResponse { + if (this._raw != null) { + //TODO investigate _raw and implementation + return this._raw as DialogflowV1WebhookResponse + } + val contextOut = this.contexts._serializeV1() + val payload = commonPayload() + val response = DialogflowV1WebhookResponse( + speech = textToSpeech, + displayText = displayText, + data = payload, + contextOut = contextOut) + return response + } + + /** @public */ + fun serialize(): GoogleCloudDialogflowV2WebhookResponse { + if (this._raw != null) { + return this._raw as GoogleCloudDialogflowV2WebhookResponse + } + + val payload = commonPayload() + + val data = mutableMapOf() + data["data"] = Serializer.serialize(this.data) ?: Any() + + this.contexts.set(APP_DATA_CONTEXT, APP_DATA_CONTEXT_LIFESPAN, data) + + val outputContexts = this.contexts._serialize() + val response = GoogleCloudDialogflowV2WebhookResponse( + fulfillmentText = textToSpeech, + payload = payload, + outputContexts = outputContexts) + return response + } +} diff --git a/common/src/main/kotlin/actions/service/dialogflow/Dialogflow.kt b/common/src/main/kotlin/actions/service/dialogflow/Dialogflow.kt new file mode 100644 index 0000000..a2fbb22 --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/Dialogflow.kt @@ -0,0 +1,509 @@ +package actions.service.dialogflow + +import actions.BaseAppPlugin +import actions.Plugin +import actions.expected.BuiltinFrameworks +import actions.expected.OAuth2Client +import actions.expected.Serializer +import actions.expected.log +import actions.framework.Headers +import actions.framework.OmniHandler +import actions.framework.StandardHandler +import actions.framework.StandardResponse +import actions.service.actionssdk.ActionsSdkIntentHandler4 +import actions.service.actionssdk.WebhookError +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import actions.service.actionssdk.api.GoogleActionsV2Argument +import actions.service.actionssdk.api.GoogleRpcStatus +import actions.service.actionssdk.conversation.* +import actions.service.actionssdk.push +import actions.service.dialogflow.api.DialogflowV1Parameters +import actions.service.dialogflow.api.DialogflowV1WebhookRequest +import actions.service.dialogflow.api.GoogleCloudDialogflowV2WebhookRequest + + +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +typealias DialogflowIntentHandler1 = (conv: DialogflowConversation) -> Any + +typealias DialogflowIntentHandler2 = (conv: DialogflowConversation, param: DialogflowV1Parameters) -> Any +typealias DialogflowIntentHandler3 = (conv: DialogflowConversation, param: DialogflowV1Parameters, arg: GoogleActionsV2Argument?) -> Any +typealias DialogflowIntentHandler4 = (conv: DialogflowConversation, param: DialogflowV1Parameters, arg: GoogleActionsV2Argument?, status: GoogleRpcStatus?) -> Any + + +/** @hidden */ +class DialogflowIntentHandlers : MutableMap> by mutableMapOf() + + +/** @hidden */ +data class DialogflowHandlers< + TUserStorage, + TConversation>( + var intents: DialogflowIntentHandlers, + var catcher: ExceptionHandler? = null, + var fallback: DialogflowIntentHandler4? = null //| string +) + +/** @public */ +interface DialogflowMiddleware +/* +TConversationPlugin extends DialogflowConversation<{}, {}, Contexts> +> { +( + conv: DialogflowConversation<{}, {}, Contexts>, +): (DialogflowConversation<{}, {}, Contexts> & TConversationPlugin) | void +} +*/ + +/** @public */ +abstract class DialogflowApp< + TUserStorage, + TConversation, + TArgument> : ConversationApp() { + /** @hidden */ + abstract var _handlers: DialogflowHandlers + + /** + * Sets the IntentHandler to be execute when the fulfillment is called + * with a given Dialogflow intent name. + * + * @param intent The Dialogflow intent name to match. + * When given an array, sets the IntentHandler for any intent name in the array. + * @param handler The IntentHandler to be executed when the intent name is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent name. + * @public + */ + abstract fun intent(intents: MutableList, handler: DialogflowIntentHandler1 /*| Intent,*/): DialogflowApp + + abstract fun intent(intents: MutableList, handler: DialogflowIntentHandler2 /*| Intent,*/): DialogflowApp + abstract fun intent(intents: MutableList, handler: DialogflowIntentHandler3 /*| Intent,*/): DialogflowApp + abstract fun intent( + intent: MutableList, + handler: DialogflowIntentHandler4< + TUserStorage> //| string, + ): DialogflowApp + + /** + * Sets the IntentHandler to be execute when the fulfillment is called + * with a given Dialogflow intent name. + * + * @param intent The Dialogflow intent name to match. + * When given an array, sets the IntentHandler for any intent name in the array. + * @param handler The IntentHandler to be executed when the intent name is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent name. + * @public + */ + abstract fun intent(intents: String, handler: DialogflowIntentHandler1 /*| Intent,*/): DialogflowApp + + abstract fun intent(intents: String, handler: DialogflowIntentHandler2 /*| Intent,*/): DialogflowApp + abstract fun intent(intents: String, handler: DialogflowIntentHandler3 /*| Intent,*/): DialogflowApp + abstract fun intent( + intent: String, + handler: DialogflowIntentHandler4< + TUserStorage> //| string, + ): DialogflowApp + + /** + * Sets the IntentHandler to be execute when the fulfillment is called + * with a given Dialogflow intent name. + * + * @param intent The Dialogflow intent name to match. + * When given an array, sets the IntentHandler for any intent name in the array. + * @param handler The IntentHandler to be executed when the intent name is matched. + * When given a string instead of a function, the intent fulfillment will be redirected + * to the IntentHandler of the redirected intent name. + * @public + */ + /* + abstract fun intent( + intent: MutableList, + handler: DialogflowIntentHandler4< + TConvData, + TUserStorage, + TParameters, + TArgument> //| string, + ): DialogflowApp + */ + + + /** @public */ + abstract fun catch(catcher: ExceptionHandler): DialogflowApp + + /** @public */ + abstract fun fallback( + handler: DialogflowIntentHandler4< + TUserStorage> + ): DialogflowApp + + abstract var _middlewares: MutableList + + /** @public */ + abstract fun middleware/**/( + middleware: DialogflowMiddleware// + ): DialogflowApp + + /** @public */ + abstract var verification: DialogflowVerification? +} + +/** @public */ +//class DialogflowVerificationHeaders : MutableMap by mutableMapOf() { +/** + * A header key value pair to check against. + * @public + */ +// [key: string]: string +//} + +/** @public */ +data class DialogflowVerification( + /** + * An object representing the header key to value map to check against, + * @public + */ + // Reusing Headers from framework. Difference is Map vs Map> + var headers: Headers? = null, //DialogflowVerificationHeaders? = null, + + /** + * Custom status code to return on verification error. + * @public + */ + var status: Int? = null, + + /** + * Custom error message as a string or a function that returns a string + * given the original error message set by the library. + * + * The message will get sent back in the JSON top level `error` property. + * @public + */ + var error: String? = null //| ((error: string) => string) +) + +/** @public */ +data class DialogflowOptions( + + /** + * Verifies whether the request comes from Dialogflow. + * Uses header keys and values to check against ones specified by the developer + * in the Dialogflow Fulfillment settings of the app. + * + * HTTP Code 403 will be thrown by default on verification error. + * + * @public + */ + var verification: DialogflowVerification? = null, // | DialogflowVerificationHeaders, + override var init: (() -> ConversationOptionsInit)? = null, + override var clientId: String? = null, + override var debug: Boolean? = null +) : ConversationAppOptions + + +fun isVerification(): Boolean = true +//val isVerification = (verification: DialogflowVerification | DialogflowVerificationHeaders): +//verification is DialogflowVerification => +//typeof (verification as DialogflowVerification).headers === "object" + +/** + * This is the function that creates the app instance which on new requests, + * creates a way to handle the communication with Dialogflow"s fulfillment API. + * + * Supports Dialogflow v1 and v2. + * + * @example + * ```javascript + * + * val app = dialogflow() + * + * app.intent("Default Welcome Intent", conv => { + * conv.ask("How are you?") + * }) + * ``` + * + * @public + */ +fun dialogflow(init: (DialogflowOptions.() -> Unit)? = null): DialogflowApp { + val options = DialogflowOptions() + options.init?.invoke() + return DialogflowSdk(options) +} + +class DialogflowSdk(options: DialogflowOptions? = null) : DialogflowApp() { + + + override lateinit var frameworks: BuiltinFrameworks + + override fun use(plugin: Plugin): BaseAppPlugin { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override var debug: Boolean = false + + override var _handlers: DialogflowHandlers = DialogflowHandlers( + intents = DialogflowIntentHandlers(), + catcher = { conv, e -> throw e }) + + override var _middlewares: MutableList = mutableListOf() + + + override fun intent( + intents: MutableList, + handler: DialogflowIntentHandler4< + TUserStorage> //| string, + ): DialogflowApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status, g, arg) } + } + return this + } + + override fun intent(intent: String, handler: DialogflowIntentHandler4): DialogflowApp { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status, g, arg) } + return this + } + + override fun intent(intents: MutableList, handler: DialogflowIntentHandler1): DialogflowApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv) } + } + return this + } + + override fun intent(intents: MutableList, handler: DialogflowIntentHandler2): DialogflowApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status) } + } + return this + } + + override fun intent(intents: MutableList, handler: DialogflowIntentHandler3): DialogflowApp { + for (intent in intents) { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status, g) } + } + return this + } + + override fun intent(intent: String, handler: DialogflowIntentHandler1): DialogflowApp { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv) } + return this + } + + override fun intent(intent: String, handler: DialogflowIntentHandler2): DialogflowApp { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status) } + return this + } + + override fun intent(intent: String, handler: DialogflowIntentHandler3): DialogflowApp { + this._handlers.intents[intent] = { conv, status, g, arg -> handler(conv, status, g) } + return this + } + + override fun catch(catcher: ExceptionHandler): DialogflowSdk { + this._handlers.catcher = catcher + return this + } + + override fun fallback(handler: DialogflowIntentHandler4): DialogflowSdk { + this._handlers.fallback = handler + return this + } + + override fun middleware(middleware: DialogflowMiddleware + ): DialogflowApp { + this._middlewares.push(middleware) + return this + } + + override var init: (() -> ConversationOptionsInit)? = options?.init + + override var verification: DialogflowVerification? = options?.verification + + + override var _client: OAuth2Client? = if (options?.verification != null || options?.clientId != null) + OAuth2Client(options.clientId!!) else null + + override var auth: OAuth2Config? = if (options?.clientId != null) OAuth2Config(client = OAuth2ConfigClient(id = options.clientId)) else null + + override var handler: StandardHandler = object : StandardHandler { + override fun handle(body: Any, headers: Headers, overrideHandler: DialogflowIntentHandler4?, aogOverrideHandler: ActionsSdkIntentHandler4?): StandardResponse { + val convBodyV1 = body as? DialogflowV1WebhookRequest + val convBodyV2 = body as? GoogleCloudDialogflowV2WebhookRequest + +// override fun handler( +// body: GoogleCloudDialogflowV2WebhookRequest, headers: DialogflowVerificationHeaders) { + val debug = debug +// } + + val init = init + val verification = verification + + if (verification != null) { + + val newVerification = DialogflowVerification(headers) + val verificationHeaders = newVerification.headers + val status = newVerification.status + val error = newVerification.error + +// val StandardResponse( +// headers = newVerification.headers, //verificationHeaders, +// status = 403, +// error = WebhookError(error = error) +// ) = isVerification(verification) ? verification : +// { headers: verification } as DialogflowVerification + + newVerification.headers?.forEach { + val check = headers!![it.key.toLowerCase()] + if (check?.isNotEmpty() == true) { + error("A verification header key was not found") + return StandardResponse( + status, + body = WebhookError( + error = error) + ) + } + val value = verificationHeaders!![it.key]?.first() +// val checking = common.toArray(check) + if (check == null || check.indexOf(value) < 0) { + error("A verification header value was invalid") + return StandardResponse( + status = status, + body = WebhookError( + error = error) + ) + } + } + } + + + val conv = DialogflowConversation( + DialogflowConversationOptions( + body = convBodyV2, + bodyV1 = convBodyV1, + headers = headers, + init = init?.invoke(), //init &&init (), + debug = debug)) + + if (conv.user.profile?.token != null) { +// await conv . user . _verifyProfile (this._client!, this.auth!.client.id) + conv.user._verifyProfile(_client!!, auth?.client?.id!!) + } + for (middleware in _middlewares) { + TODO("Handle middleware") +// conv = middleware(conv) //as DialogflowConversation | void) +// || conv + } +// val log = debug ? common.info : common.debug +// log("Conversation", common.stringify(conv, "request", "headers", "body")) + + //Using the action field to match handlers here. Nodejs lib uses intent, which differs from V1 and may break some agents. + //TODO: match the implementation of nodejs once issue is resolved: https://github.com/actions-on-google/actions-on-google-nodejs/issues/132 + val intent = conv.action + val traversed: TraversedDialogflowHandlers = TraversedDialogflowHandlers() + var handler = if (overrideHandler != null) overrideHandler else _handlers.intents[intent] +// while (typeof handler !== 'function') { + while (false) { + //TODO why is this loop here? handle intents mapped to a string? + if (handler == null) { + if (_handlers.fallback == null) { + throw Error("Dialogflow IntentHandler not found for intent: $intent") + } + handler = _handlers.fallback + break + } + if (traversed[handler] == true) { + throw Error("Circular intent map detected: $handler traversed twice") + } + traversed[handler] = true +// handler = _handlers.intents[handler] + } + + try { + /*await*/ handler?.invoke( + conv, + conv.parameters!!, + conv.arguments.parsed?.list?.firstOrNull(), + conv.arguments.status?.list?.firstOrNull()) + } catch (e: Exception) { +// await this._handlers.catcher(conv as TConversation, e) +// _handlers.catcher?.invoke(conv!!, e) + log(e.message ?: "") + } + return StandardResponse( + status = 200, + headers = mutableMapOf("Content-type" to mutableListOf("UTF-8")), + body = if (convBodyV1 != null) conv.serializeV1() else conv.serialize()) + } + } + + //TODO - refactor init from Dialogflow & ActionsSdk into common function + init { + frameworks = BuiltinFrameworks() +// val baseApp = create(options) + omni = object : OmniHandler { + override fun handle(vararg args: Any): Any { + log("Args in omniHandler: ${args.map { it.toString() }.joinToString { it }}") + for (framework in frameworks) { + if (framework.check(*args)) { + return framework.handle(handler).handle(*args) + } + } + return handler.handle(args[0] as GoogleActionsV2AppRequest, args[1] as Headers) + } + } + +// var handler = baseApp.handler + val standard = object : StandardHandler { + override fun handle(body: Any, headers: Headers, overrideHandler: DialogflowIntentHandler4?, aogOverrideHandler: ActionsSdkIntentHandler4?): StandardResponse { + val body = body as GoogleActionsV2AppRequest + log("Request", Serializer.serialize(body)) + log("Headers", Serializer.serialize(headers)) + val response = /* await */ handler.handle(body, headers) + response.headers?.get("content-type")?.add("application/json; charset=utf-8") + log("Response", Serializer.serialize(response)) + return response + } + } +// baseApp.omni = omni +// baseApp.handler = standard + +// var appResult = object: OmniHandler by omni, actions.BaseApp by baseApp, actions.framework.StandardHandler by standardHandler, actions.ServiceBaseApp by service { +// +// } + +// var attachedResult = AttachResult( +// baseApp = baseApp, +// service = service, +// omni = omni, +// handler = standardHandler) + +// return object: AppResult() { +// handler = standard + + fun use(plugin: Plugin): BaseAppPlugin { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +// override fun handle(body: JsonObject, headers: Headers): StandardResponse = standard.handle(body, headers) +// +// override var frameworks: BuiltinFrameworks = baseApp.frameworks +// +// override var debug: Boolean = baseApp.debug +// } + } +} diff --git a/common/src/main/kotlin/actions/service/dialogflow/DialogflowV1Message.kt b/common/src/main/kotlin/actions/service/dialogflow/DialogflowV1Message.kt new file mode 100644 index 0000000..bcb20e9 --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/DialogflowV1Message.kt @@ -0,0 +1,116 @@ +package actions.service.dialogflow + +import actions.ApiClientObjectMap +import actions.framework.JsonObject +import actions.service.dialogflow.api.DialogflowV1Button + +data class Message( + var type: String = "", + var platform: String? = "", + var payload: String? = "", + var items: MutableList? = null, + var speech: String? = null, + var textToSpeech: String? = null, + var displayText: String? = null, + var suggestions: MutableList? = null, + var destinationName: String? = null, + var url: String? = null, + var title: String? = null, + var subtitle: String? = null, + var formattedText: String? = null, + var image: DialogflowV1MessageImage? = null, + var buttons: MutableList? = null) + +sealed class DialogflowV1Message : DialogflowV1BaseMessage() {} + +data class DialogflowV1MessageText(var speech: String? = null) : DialogflowV1BaseMessage() + +open class DialogflowV1BaseMessage( + var platform: String? = null, //"facebook" | "kik" | "line" | "skype" | "slack" | "telegram" | "viber" + var type: String? = null // <-- investigate Int/String - what is actually returned? both? look in Incoming.kt for examples +) + + +data class DialogflowV1MessageImage(var imageUrl: String? = null) : DialogflowV1BaseMessage() + +data class DialogflowV1MessageCard( + var buttons: MutableList? = null, + var imageUrl: String? = null, + var subtitle: String? = null, + var title: String? = null +) : DialogflowV1BaseMessage(type = "1") // 1 + +data class DialogflowV1MessageQuickReplies( + var replies: MutableList? = null, + var title: String? = null +) : DialogflowV1BaseMessage(type = "2") //<2> { + +data class DialogflowV1MessageCustomPayload( + var payload: JsonObject? = null +) : DialogflowV1BaseMessage(type = "4") //<4> { + + +open class DialogflowV1BaseGoogleMessage( + var platform: String? = null, //= "Google" + var type: Int? = null) + +data class DialogflowV1MessageSimpleResponse( + var displayText: String? = null, + var textToSpeech: String? = null +) : DialogflowV1BaseGoogleMessage() //{//<"simple_response"> { + +data class DialogflowV1MessageBasicCardButtonAction( + var url: String? = null +) + +data class DialogflowV1MessageBasicCardButton( + var openUrlAction: DialogflowV1MessageBasicCardButtonAction? = null, + var title: String? = null +) + +data class DialogflowV1MessageBasicCard( + var buttons: MutableList? = null, + var formattedText: String? = null, + var image: DialogflowV1MessageImage? = null, + var subtitle: String? = null, + var title: String? = null +) : DialogflowV1BaseGoogleMessage() + +interface DialogflowV1MessageOptionInfo { + var key: String + var synonyms: MutableList +} + +data class DialogflowV1MessageOptionItem( + var description: String? = null, + var image: DialogflowV1MessageImage? = null, + var optionInfo: DialogflowV1MessageOptionInfo? = null, + var title: String? = null +) + +data class DialogflowV1MessageList( + var items: MutableList? = null, + var title: String? = null +) : DialogflowV1BaseGoogleMessage() + +data class DialogflowV1MessageSuggestion( + var title: String? = null +) + +data class DialogflowV1MessageSuggestions( + var suggestions: MutableList? = null +) : DialogflowV1BaseGoogleMessage() + +data class DialogflowV1MessageCarousel( + var items: MutableList? = null +) : DialogflowV1BaseGoogleMessage() + +data class DialogflowV1MessageLinkOut( + var destinationName: String? = null, + var url: String? = null +) : DialogflowV1BaseGoogleMessage() + +data class DialogflowV1MessageGooglePayload(var payload: ApiClientObjectMap? = null) : DialogflowV1BaseGoogleMessage() + + + diff --git a/common/src/main/kotlin/actions/service/dialogflow/Incoming.kt b/common/src/main/kotlin/actions/service/dialogflow/Incoming.kt new file mode 100644 index 0000000..391aa88 --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/Incoming.kt @@ -0,0 +1,383 @@ +package actions.service.dialogflow + +import actions.service.actionssdk.conversation.response.* +import actions.service.actionssdk.push +import actions.service.dialogflow.api.DialogflowV1Fulfillment +import actions.service.dialogflow.api.GoogleCloudDialogflowV2IntentMessage + +/** + * Copyright 2018 Google Inc. All Rights Reserved.d + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + +type IncomingMessage = +string | +Image | +Suggestions | +BasicCard | +SimpleResponse | +LinkOutSuggestion | +List | +Carousel | +JsonObject +*/ + +fun toImage(imageUri: String?): Image? { + if (!imageUri.isNullOrBlank()) { + return Image { + url = imageUri!! + alt = "" + } + } + return null +} + +class Incoming { + /** @public */ + var parsed: MutableList? = null //IncomingMessage can be multiple types. See above + + constructor(fulfillment: DialogflowV1Fulfillment) { + val speech = fulfillment.speech + val messages = fulfillment.messages + parsed = mutableListOf() + + if (speech != null) { + this.parsed?.push(speech) + } + if (messages != null) { + for (message in messages) { + val platform = message.platform + val type = message.type + if (platform != null && platform != "google") { + continue + } + if (type == "0") { + val assumed = message //as DialogflowV1MessageText + this.parsed?.push(assumed.speech ?: "") + continue + } + if (type == "3") { + val assumed = message //as DialogflowV1MessageImage +// this.parsed?.push(toImage(assumed.imageUrl)) + continue + } + if (type == "1") { + val assumed = message //as DialogflowV1MessageCard + /* + val buttons = assumed.buttons + this.parsed?.push(BasicCard( + title = assumed.title, + subtitle = assumed.subtitle, + image = toImage(assumed.imageUrl), + buttons = buttons?.map { + Button { + title = it.text ?: "" + url = it.postback + } + }?.toMutableList())) + */ + continue + } + if (type == "2") { + val assumed = message //as DialogflowV1MessageQuickReplies + //TODO find cleaner way for Suggestions creation + /* + if (assumed?.replies != null) + this.parsed?.push(Suggestions(*assumed.replies!!.toTypedArray())) + */ + continue + } + if (type == "4") { + val assumed = message //as DialogflowV1MessageCustomPayload + this.parsed?.push(assumed.payload ?: "") + continue + } + if (type == "simple_response") { + val assumed = message //as DialogflowV1MessageSimpleResponse + this.parsed?.push(SimpleResponse { + text = assumed.displayText + this.speech = assumed.textToSpeech ?: "" + }) + continue + } + if (type == "basic_card") { + val assumed = message //as DialogflowV1MessageBasicCard + val image = assumed.image + val buttons = assumed.buttons + /* + this.parsed?.push(BasicCard( + title = assumed.title, + subtitle = assumed.subtitle, + text = assumed.formattedText, + image = toImage(image.imageUrl), + buttons = buttons?.map { + Button { + title = it.title + url = it.openUrlAction.url + } + }.toMutableList() + )) + */ + continue + } + if (type == "list_card") { + val assumed = message //as DialogflowV1MessageList + /* + this.parsed?.push(List ({ title: assumed.title, + items: assumed.items!, + })) + */ + continue + } + if (type == "suggestion_chips") { + val assumed = message //as DialogflowV1MessageSuggestions +// this.parsed?.push(Suggestions (assumed.suggestions!.map(s => s . title !))) + continue + } + if (type == "carousel_card") { + val assumed = message //as DialogflowV1MessageCarousel + this.parsed?.push(Carousel { + // items = assumed.items + }) + continue + } + if (type == "link_out_chip") { + val assumed = message //as DialogflowV1MessageLinkOut + this.parsed?.push(LinkOutSuggestion { + name = assumed.destinationName ?: "" + url = assumed.url ?: "" + }) + continue + } + if (type == "custom_payload") { + val assumed = message //as DialogflowV1MessageGooglePayload + this.parsed?.push(assumed.payload ?: "") + continue + } + } + } + } + + + /** @hidden */ + constructor(fulfillment: MutableList) { + /* + // Dialogflow v2 + for (val message of fulfillment) { + val { text, + image, + quickReplies, + card, + simpleResponses, + basicCard, + suggestions, + linkOutSuggestion, + listSelect, + carouselSelect, + platform, + payload, + } = message + if (platform && platform !== "ACTIONS_ON_GOOGLE" && platform !== "PLATFORM_UNSPECIFIED") { + continue + } + if (text) { + this.parsed.push(... text . text !) + continue + } + if (image) { + this.parsed.push(new Image ({ url: image.imageUri!, + alt: image.accessibilityText!, + })) + continue + } + if (quickReplies) { + this.parsed.push(new Suggestions (quickReplies.quickReplies!)) + continue + } + if (card) { + val { buttons } = card + this.parsed.push(new BasicCard ({ + title: card.title, + subtitle: card.subtitle, + image: toImage(card.imageUri), + buttons: buttons ? buttons.map(b => new Button({ title: b.text!, + url: b.postback, + })) : undefined, + })) + continue + } + if (simpleResponses) { + this.parsed.push(... simpleResponses . simpleResponses !. map (s => new SimpleResponse({ + speech: s.textToSpeech || s.ssml!, + text: s.displayText, + }))) + continue + } + if (basicCard) { + val { image, buttons } = basicCard + this.parsed.push(new BasicCard ({ + title: basicCard.title, + subtitle: basicCard.subtitle, + text: basicCard.formattedText, + image: image ? new Image({ url: image.imageUri!, + alt: image.accessibilityText!, + }) : undefined, + buttons: buttons ? buttons.map(b => new Button({ title: b.title!, + url: b.openUriAction!.uri, + })) : undefined, + })) + continue + } + if (suggestions) { + this.parsed.push(new Suggestions (suggestions.suggestions!.map(s => s . title !))) + continue + } + if (linkOutSuggestion) { + this.parsed.push(new LinkOutSuggestion ({ name: linkOutSuggestion.destinationName!, + url: linkOutSuggestion.uri!, + })) + continue + } + if (listSelect) { + this.parsed.push(new List ({ title: listSelect.title, + items: listSelect.items!, + })) + continue + } + if (carouselSelect) { + this.parsed.push(new Carousel ({ items: carouselSelect.items!, + })) + continue + } + if (payload) { + this.parsed.push(payload) + continue + } + } + */ + } + + /** + * Gets the first Dialogflow incoming message with the given type. + * Messages are converted into client library class instances or a string. + * + * Only messages with the platform field unlabeled (for generic use) + * or labeled `ACTIONS_ON_GOOGLE` (`google` in v1) will be converted and read. + * + * The conversation is detailed below for a specific message oneof: + * * Generic Platform Response + * * `text` -> `typeof string` + * * `image` -> `Image` + * * `quickReplies` -> `Suggestions` + * * `card` -> `BasicCard` + * * Actions on Google Response + * * `simpleResponses` -> `SimpleResponse[]` + * * `basicCard` -> `BasicCard` + * * `suggestions` -> `Suggestions` + * * `linkOutSuggestion` -> `LinkOutSuggestion` + * * `listSelect` -> `List` + * * `carouselSelect` -> `Carousel` + * * `payload` -> `typeof object` + * + * Dialogflow v1: + * * Generic Platform Response + * * `0` (text) -> `typeof string` + * * `3` (image) -> `Image` + * * `1` (card) -> `BasicCard` + * * `2` (quick replies) -> `Suggestions` + * * `4` (custom payload) -> `typeof object` + * * Actions on Google Response + * * `simple_response` -> `SimpleResponse` + * * `basic_card` -> `BasicCard` + * * `list_card` -> `List` + * * `suggestion_chips` -> `Suggestions` + * * `carousel_card` -> `Carousel` + * * `link_out_chip` -> `LinkOutSuggestion` + * * `custom_payload` -> `typeof object` + * + * @example + * ```javascript + * + * // Dialogflow + * val { dialogflow, BasicCard } = require("actions-on-google") + * + * val app = dialogflow() + * + * // Create an Actions on Google Basic Card in the Dialogflow Console Intent Responses section + * app.intent("Default Welcome Intent", conv => { + * val str = conv.incoming.get("string") // get the first text response + * val card = conv.incoming.get(BasicCard) // gets the instance of BasicCard + * // Do something with the Basic Card + * }) + * ``` + * + * @param type A string checking for the typeof message or a class checking for instanceof message + * @public + */ +// tslint:disable-next-line:no-any allow constructors with any type of arguments + /* + get(type: new (...args: any[]) => TMessage): TMessage + /** @public */ + get(type: "string"): string +// tslint:disable-next-line:no-any allow constructors with any type of arguments + get(type: "string" | (new (...args: any[]) => TMessage)) + { + for (val message of this) { + if (typeof type === "string") { + if (typeof message === type) { + return message + } + continue + } + if (message instanceof type) { + return message + } + } + return null + } + + /** + * Gets the Dialogflow incoming messages as an iterator. + * Messages are converted into client library class instances or a string. + * See {@link Incoming#get|conv.incoming.get} for details on how the conversion works. + * + * @example + * ```javascript + * + * // Dialogflow + * val app = dialogflow() + * + * // Create messages in the Dialogflow Console Intent Responses section + * app.intent("Default Welcome Intent", conv => { + * val messages = [...conv.incoming] + * // do something with the messages + * // or just spread them out back to the user + * conv.ask(`Here"s what was set in the Dialogflow console`) + * conv.ask(...conv.incoming) + * } + * ``` + * + * @public + */ + [Symbol.iterator]() + { + return this.parsed[Symbol.iterator]() + // suppose to be Array.prototype.values(), but can"t use because of bug: + // https://bugs.chromium.org/p/chromium/issues/detail?id=615873 + } + */ +} + diff --git a/common/src/main/kotlin/actions/service/dialogflow/api/V1.kt b/common/src/main/kotlin/actions/service/dialogflow/api/V1.kt new file mode 100644 index 0000000..4980d64 --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/api/V1.kt @@ -0,0 +1,141 @@ +package actions.service.dialogflow.api + +import actions.ApiClientObjectMap +import actions.framework.JsonObject +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import actions.service.dialogflow.DialogflowV1Message +import actions.service.dialogflow.GoogleAssistantResponse +import actions.service.dialogflow.Message +import actions.service.dialogflow.PayloadGoogle + +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* tslint:disable:no-any max-line-length written like auto generated types from protobufs */ + +data class DialogflowV1OriginalRequest( + var source: String? = null, + var version: String? = null, + var data: GoogleActionsV2AppRequest? = null +) + +typealias DialogflowV1Parameters = MutableMap +//class DialogflowV1Parameters: MutableMap by mutableMapOf() { +// [parameter: String]: String | Object | undefined +//} + +data class DialogflowV1Context( + var name: String? = null, + var lifespan: Int? = null, + var parameters: DialogflowV1Parameters? = null +) + +data class DialogflowV1Metadata( + var intentId: String? = null, + var webhookUsed: String? = null, + var webhookForSlotFillingUsed: String? = null, + var nluResponseTime: Int? = null, + var intentName: String? = null +) + +data class DialogflowV1Button( + var text: String? = null, + var postback: String? = null +) + + +/* +type DialogflowV1Message = +DialogflowV1MessageText | +DialogflowV1MessageImage | +DialogflowV1MessageCard | +DialogflowV1MessageQuickReplies | +DialogflowV1MessageCustomPayload | +DialogflowV1MessageSimpleResponse | +DialogflowV1MessageBasicCard | +DialogflowV1MessageList | +DialogflowV1MessageSuggestions | +DialogflowV1MessageCarousel | +DialogflowV1MessageLinkOut | +DialogflowV1MessageGooglePayload +*/ + +data class DialogflowV1Fulfillment( + var speech: String? = null, + var messages: MutableList? = null, + var data: Data? = null +) + +data class DialogflowV1Result( + var source: String? = null, + var resolvedQuery: String? = null, + var speech: String? = null, + var action: String? = null, + var actionIncomplete: Boolean? = null, + var parameters: DialogflowV1Parameters? = null, + var contexts: MutableList? = null, + var metadata: DialogflowV1Metadata? = null, + var fulfillment: DialogflowV1Fulfillment? = null, + var score: Float? = null +) + +/** + * Holds data for original platform. Extends MutableMap so this is extendable + * to other platforms by adding a field + * Requires custom serialization in JVM. See DataTypeAdapter + */ +data class Data(val nothing: Nothing? = null) : MutableMap by mutableMapOf() { + var google: GoogleAssistantResponse? by this + + inline fun google(init: GoogleAssistantResponse.() -> Unit) { + if (google == null) { + google = GoogleAssistantResponse() + } + google?.init() + } +} + +data class DialogflowV1Status( + var code: Int? = null, + var errorType: String? = null, + var webhookTimedOut: Boolean? = null +) + +data class DialogflowV1WebhookRequest( + var originalRequest: DialogflowV1OriginalRequest? = null, + var id: String? = null, + var sessionId: String? = null, + var timestamp: String? = null, + var timezone: String? = null, + var lang: String? = null, + var result: DialogflowV1Result? = null, + var status: DialogflowV1Status? = null +) + +data class DialogflowV1FollowupEvent( + var name: String? = null, + var data: DialogflowV1Parameters? = null +) + +data class DialogflowV1WebhookResponse( + var speech: String? = null, + var displayText: String? = null, + var messages: MutableList? = null, + var data: Data? = null, +// var data: ApiClientObjectMap? = null, + var contextOut: MutableList? = null, + var source: String? = null, + var followupEvent: DialogflowV1FollowupEvent? = null) diff --git a/common/src/main/kotlin/actions/service/dialogflow/api/V2.kt b/common/src/main/kotlin/actions/service/dialogflow/api/V2.kt new file mode 100644 index 0000000..ca227a3 --- /dev/null +++ b/common/src/main/kotlin/actions/service/dialogflow/api/V2.kt @@ -0,0 +1,281 @@ +package actions.service.dialogflow.api + +import actions.ApiClientObjectMap +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import actions.service.dialogflow.GoogleAssistantResponse +import actions.service.dialogflow.PayloadGoogle + +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// DO NOT MANUALLY EDIT: this file contains types generated from protobuf messages + +/* tslint:disable:no-any max-line-length auto generated from protobufs */ + +enum class GoogleCloudDialogflowV2IntentDefaultResponsePlatforms { + PLATFORM_UNSPECIFIED, + FACEBOOK, + SLACK, + TELEGRAM, + KIK, + SKYPE, + LINE, + VIBER, + ACTIONS_ON_GOOGLE +} + + +enum class GoogleCloudDialogflowV2IntentMessagePlatform { + PLATFORM_UNSPECIFIED, + FACEBOOK, + SLACK, + TELEGRAM, + KIK, + SKYPE, + LINE, + VIBER, + ACTIONS_ON_GOOGLE +} + + +enum class GoogleCloudDialogflowV2IntentTrainingPhraseType { + TYPE_UNSPECIFIED, + EXAMPLE, + TEMPLATE +} + + +enum class GoogleCloudDialogflowV2IntentWebhookState { + WEBHOOK_STATE_UNSPECIFIED, + WEBHOOK_STATE_ENABLED, + WEBHOOK_STATE_ENABLED_FOR_SLOT_FILLING +} + + +//TESTING IF COMMON CONTEXT model will work for both. Using V1Contexts for internal logic now. + +data class GoogleCloudDialogflowV2Context( + var name: String, + var lifespanCount: Int, +// var parameters: ApiClientObjectMap + var parameters: DialogflowV1Parameters? = null +) + +data class GoogleCloudDialogflowV2EventInput( + var name: String? = null, + var parameters: ApiClientObjectMap? = null, + var languageCode: String? = null +) + +data class GoogleCloudDialogflowV2Intent( + var name: String? = null, + var displayName: String? = null, + var webhookState: GoogleCloudDialogflowV2IntentWebhookState? = null, + var priority: Int? = null, + var isFallback: Boolean? = null, + var mlDisabled: Boolean? = null, + var inputContextNames: MutableList? = null, + var events: MutableList? = null, + var trainingPhrases: MutableList? = null, + var action: String? = null, + var outputContexts: MutableList? = null, + var resetContexts: Boolean? = null, + var parameters: MutableList? = null, + var messages: MutableList? = null, + var defaultResponsePlatforms: MutableList? = null, + var rootFollowupIntentName: String? = null, + var parentFollowupIntentName: String? = null, + var followupIntentInfo: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentFollowupIntentInfo( + var followupIntentName: String? = null, + var parentFollowupIntentName: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessage( + var text: GoogleCloudDialogflowV2IntentMessageText? = null, + var image: GoogleCloudDialogflowV2IntentMessageImage? = null, + var quickReplies: GoogleCloudDialogflowV2IntentMessageQuickReplies? = null, + var card: GoogleCloudDialogflowV2IntentMessageCard? = null, + var payload: ApiClientObjectMap? = null, + var simpleResponses: GoogleCloudDialogflowV2IntentMessageSimpleResponses? = null, + var basicCard: GoogleCloudDialogflowV2IntentMessageBasicCard? = null, + var suggestions: GoogleCloudDialogflowV2IntentMessageSuggestions? = null, + var linkOutSuggestion: GoogleCloudDialogflowV2IntentMessageLinkOutSuggestion? = null, + var listSelect: GoogleCloudDialogflowV2IntentMessageListSelect? = null, + var carouselSelect: GoogleCloudDialogflowV2IntentMessageCarouselSelect? = null, + var platform: GoogleCloudDialogflowV2IntentMessagePlatform? = null +) + +data class GoogleCloudDialogflowV2IntentMessageBasicCard( + var title: String? = null, + var subtitle: String? = null, + var formattedText: String? = null, + var image: GoogleCloudDialogflowV2IntentMessageImage? = null, + var buttons: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageBasicCardButton( + var title: String? = null, + var openUriAction: GoogleCloudDialogflowV2IntentMessageBasicCardButtonOpenUriAction? = null +) + +data class GoogleCloudDialogflowV2IntentMessageBasicCardButtonOpenUriAction( + var uri: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessageCard( + var title: String? = null, + var subtitle: String? = null, + var imageUri: String? = null, + var buttons: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageCardButton ( + var text: String? = null, + var postback: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessageCarouselSelect( + var items: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageCarouselSelectItem( + var info: GoogleCloudDialogflowV2IntentMessageSelectItemInfo? = null, + var title: String? = null, + var description: String? = null, + var image: GoogleCloudDialogflowV2IntentMessageImage? = null +) + +data class GoogleCloudDialogflowV2IntentMessageImage( + var imageUri: String? = null, + var accessibilityText: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessageLinkOutSuggestion( + var destinationName: String? = null, + var uri: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessageListSelect( + var title: String? = null, + var items: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageListSelectItem( + var info: GoogleCloudDialogflowV2IntentMessageSelectItemInfo? = null, + var title: String? = null, + var description: String? = null, + var image: GoogleCloudDialogflowV2IntentMessageImage? = null +) + +data class GoogleCloudDialogflowV2IntentMessageQuickReplies( + var title: String? = null, + var quickReplies: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageSelectItemInfo( + var key: String? = null, + var synonyms: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageSimpleResponse( + var textToSpeech: String? = null, + var ssml: String? = null, + var displayText: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessageSimpleResponses( + var simpleResponses: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageSuggestion( + var title: String? = null +) + +data class GoogleCloudDialogflowV2IntentMessageSuggestions( + var suggestions: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentMessageText( + var text: MutableList? = null +) + +data class GoogleCloudDialogflowV2IntentParameter( + var name: String? = null, + var displayName: String? = null, + var value: String? = null, + var defaultValue: String? = null, + var entityTypeDisplayName: String? = null, + var mandatory: Boolean? = null, + var prompts: MutableList? = null, + var isList: Boolean? = null +) + +data class GoogleCloudDialogflowV2IntentTrainingPhrase ( + var name: String? = null, + var type: GoogleCloudDialogflowV2IntentTrainingPhraseType? = null, + var parts: MutableList? = null, + var timesAddedCount: Int? = null +) + +data class GoogleCloudDialogflowV2IntentTrainingPhrasePart ( + var text: String? = null, + var entityType: String? = null, + var alias: String? = null, + var userDefined: Boolean? = null +) + +data class GoogleCloudDialogflowV2OriginalDetectIntentRequest( + var source: String? = null, + var payload: GoogleActionsV2AppRequest? = null +// var payload: ApiClientObjectMap +) + +data class GoogleCloudDialogflowV2QueryResult( + var queryText: String? = null, + var languageCode: String? = null, + var speechRecognitionConfidence: Int? = null, + var action: String? = null, + var parameters: DialogflowV1Parameters? = null, +// var parameters: ApiClientObjectMap + var allRequiredParamsPresent: Boolean? = null, + var fulfillmentText: String? = null, + var fulfillmentMessages: MutableList? = null, + var webhookSource: String? = null, + var webhookPayload: ApiClientObjectMap? = null, + var outputContexts: MutableList? = null, + var intent: GoogleCloudDialogflowV2Intent? = null, + var intentDetectionConfidence: Int? = null, + var diagnosticInfo: ApiClientObjectMap? = null +) + +data class GoogleCloudDialogflowV2WebhookRequest( + var session: String? = null, + var responseId: String? = null, + var queryResult: GoogleCloudDialogflowV2QueryResult? = null, + var originalDetectIntentRequest: GoogleCloudDialogflowV2OriginalDetectIntentRequest? = null +) + +data class GoogleCloudDialogflowV2WebhookResponse( + var fulfillmentText: String? = null, + var fulfillmentMessages: MutableList? = null, + var source: String? = null, + var payload: Data? = null, +// var payload: ApiClientObjectMap? = null, + var outputContexts: MutableList? = null, + var followupEventInput: GoogleCloudDialogflowV2EventInput? = null) diff --git a/common/src/test/kotlin/Test.kt b/common/src/test/kotlin/Test.kt new file mode 100644 index 0000000..1f04109 --- /dev/null +++ b/common/src/test/kotlin/Test.kt @@ -0,0 +1,4 @@ +package actions + +fun test() { +} \ No newline at end of file diff --git a/dialogflow-samples/.gitignore b/dialogflow-samples/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/dialogflow-samples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/dialogflow-samples/README.md b/dialogflow-samples/README.md deleted file mode 100644 index ae994f5..0000000 --- a/dialogflow-samples/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Dialogflow Google Actions Sample - -## ConversationComponentsSample - -This is a port of the [sample action from the offical SDK](https://github.com/actions-on-google/conversation-components-nodejs). - -## TransactionsSample -This is a port of the [sample action from the offical SDK](https://github.com/actions-on-google/conversation-components-nodejs). - -These samples are 100% ported. Dialogflow agents are in repo as zip files. This sample uses Google App Engine standard environment with a single deployment serving both samples. diff --git a/dialogflow-samples/Transactions_agent.zip b/dialogflow-samples/Transactions_agent.zip deleted file mode 100644 index c22c357ff39a969d2c89e34ae16a4be3057abc9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5680 zcmbW5c{r5)+r}*uV=PG$SsF63rfk{9nr&=jY+1rIjeV?R-zWPPl4PlfY)!VIELjUl zB%rw+)DS$vAg-2oqjDoB{ zq-&%D+6{Zg+1uR>gSccks=^#RZ+;29aAsx!K z$)H*k7&rW`uI^TDh#W^!71cfC(xk}h1fz`H+Pkz5PZU>Zqy#Z=4DlrB(y0U|*(F`p zi<}Ir_kC4O3SSC7{SgyXJVwcLW?=br?*t`#}5H?f0{L*+%1J)U!pjvaB2D|@6z zH!S`WGvf@Z3odN{elMS0cHY`uclPnVBc5TQ6$sV-6v@TZ6Aj?_6}NUNmp5wjjK(?a9?}7?S|~SUHczqmY|H*6tT-KS88FSZ#DX zNIrg@?#ESl5LXfAaE1)9B>9^s?f4Te4IFn$jN!P2;PVJ74-&`lF?L&h2=ICOpMBwUvkcWzlsVG8{d%xh_@lb4+~#fKaQ5f$6yiebu_fYl zhxIxRndCIp)9L2H!i)Ue=D|4#;Va#zgEM+1x~pJj>Ck@u4Nl*1frw;|K7gY%g+vT-AhJc zJNs!$K>%FONsh}k_Gfn3a6zkwr=X)7t6Q;^)P_Ei$*ynDhcJSD8OL!#jA?fvRw}Pi z5N?|ZU9@V+syC|YIh&9;AeeB6CX!DaI#&y}za^C0Ae3;6ZzYSXO4BDcgo`fnrxcz-8YAWEdZ%wQ?xg2_lQ6&SuVWR{P7h zq95FK5_C+DluA?7eJYVW&6hbD=#{*qiqwseXq2%x;QYg>ny4V14`yHavA!-}F~gYGdI;eKVOBX5ukN%c zE5|+FOV6C1vWsLghi0p+p_CQbOU44m8&u~!5*`(gi%H?lr{0=27x;NkN!xMaMR$-D zB9srC6++KQco^`DHby?vZu58~sKQ75DD!GnjKF&N#B2czpb~DpAe=PNL4w!wR)NNWOiuO z`4Lx_r0mj%BBsf^3}Yp1);za!pg%r+JJTAYPJ^<)DZYo%_n|ZpOTx%P{kO*AC&PFF zZIASE#ey}FuCAAnC>OBKua5iGQc1>8!}hbx5l!XSEeBZxpW@Ek=uq={g5 zRH3Rbz4${|r)PdzZGH-`*F@*I!fYca<%Qlfoyy97Xk$pC)df&k@``u1HZq|0$WzW=EC@O_d<0iyr|Z-Xs?pVA3Z_7qsB4>5_5JocdaZ9CrYE zbAa+LOKZkyhEsx!=rfgyR<>q3TQH;1YSFfeva+H{%jkA?Y_*I$^J^}^%;+eYth=&$Mw(D^wcaSWMwl6wRI>%8-BzTS!#ww2Xx2jJ_ia-^6+N+qI| zvlu*Co*B+`(#FpE^GWc0ljEvDXb*mftkqM6CG-}yae5}M<*O_+9QsCV&et`@D-0WR8z65~#>13d z2FuM84U-&Wfe~dY5vT$L_p5=4L5a z-{JG{>~`?i)TSQ$vVgSJ?6uxm+C3UonsfnsV-oe(F)2t!<6n*Iw~_tsF~keEb}(sD ziZIX1u2awVyA)_ci=d{aQAi!QYX!xlr2L(rh_`XqH{d5l6{{6`dbgxhfqrZ~89ZX4 zYVJQc^NfRoG`+69k57|$F&BU!=0FNy8fx>mw7ZWT(M^+Rm2Dl!i!s(JhoNe^c#e7V29`(n`yAd zwA5N!d^=@i7-2Ojzv8f1Ugvj?)4E6V%$Zp=3h$QTYfOBjh#4&}JDydV2Zar(b(6aC zwY>3Ic^V9T%SP*{rJuAGOyNtjn3CvyX$0qDvQ4R8`_X>!;tk7_He#!ukD-nI_Es*B zQhmhUxaDwe6xHW1tu9H%Dz_!!46j+=zmpS2iWaoMS+5dtYZ9@K|1V;{jm^#70~vt% zCqssii2d?55z$`W>0@d^NvtLFgrd^;#3xLGcE&+Y@g!nNI)a6!Au9G8(h4&#aLnb> zcQ*-=6Q=@denwi44Qs;O&WW=q>JH?5uZ(Rm9I9Nc_Nd;VW<#sJQhb^J%4)(zRzu!5 z%h%f|(r_uLit26L-TSZM(S>P5>&tnT{EW-aDGN!a!=uX>E~6}m;_P_7w`Mpqnhs`T z{1Po7A*e*80n?TbC+47ksIxePrmZKrpQqnRnU}iEF&U||B(uhk-=3R@eBbJ+r0wId zz~Yq9Es*cVO{c4}p&)-QrvHTAy@CkkFEzX^%YM)LE=5;LvWawFhP-ixp}LM!u~SX< z3O#mIuNkLP?OQ#OnAb_yFnQZYzg(jt2X~*+PQ%cxY$X0@Ns6Ptd+XGonL15TkRPU3 zd8L=Z1zUoR%gwD|+M0PKNsK}i9j6W!-eQ~}StaXAcd78KXK9gxyQ#su#pkdYo-RM2 zlBh&%)#FggJ(RiH4?TTID3APg6#hM<{Ly*3?pMz;G;Nw+$kEjZ@ENZ`6y`SM-Y=1` z0}1nsp8E)Y^RtOrP``n@gV$^6?PPn7L!umBt?sIUT;I~ANe+cT!`@S6)v$u zjj5QQI_>bGF|ofBU|eecAR7ey`j|^N%2?=_*eBJ-cQtPaNzTk*CiBoK8ul1Bc6-A! z0OZmcO4J}#wX7AVG*e9d$(4(uo6(!0j~UAELh@`=T^Xs9dV^9sUQ(LpI|IzW#kAH( z66$=$=sA!pLZS>&Q5s19?D#O5tx$5}DPbWF zbHNIoNPn3{*~;X~CzDF#%b!-u?X@Q?Ko*E1Bfj#VdK-~CyieEkk@ne2_aCXP2&;}( zmBKEXhPPy0Si%uc-X zV`pYDVe82nlJV!iGm30q9efYYPIjVMlhT_GVC$F>q`Uq+J<3S2(A%HA5B!9_(dIQv zR^sU{M@WjR%2`vYfD9mu6(b%l$Cw4$xg~Ubr`5)k+Dyc$)i@bUoNC4ZJv@86iYtDc zSAubPK{%sDmUK@~!DZ6a#iwvwYmUOQ8m zNx9X#sAyDpWaquEwGpc%3{q(l#|N2)t>=hk@%h^vBH_zhmR0i?i$QVseHI^9-(Y;M z50!gg#)Wosn1#(!ovGGrwe{;fI>Jf`FDPgdVTtP13?qa~FZJ0XMVu;I;t&bz|PA}cP3m_mH$x~Ek<$4zqW zr51J7-$8Hj-OIY*ZZP0Lhb*n5By!l~?^VoUb4HK`-o!-06I4^82r?*q%euDr}= zzxIVnyv9OkIRhbNf$12?|4}g1;wK&oM9!Oo4)e%8QkL8OW4hxcwTNh|5qX z?$loI3p3zWYwQj;Sm^gRB%%iJ$67Hko|)f~cN~7i9u`ny>^vNra!6gCYwljB z&Q#qNj_2-*iaxzM2gtO*mDcr+gpVKuEagK`Lw|&uPxa~@15UmTw74o{ifqv_0~3iG z0*BZyDR>DdHFTh}%|C$ynezRp`%UKM&H{MGsUN%Q)Nlh;Cl_hYM!Q+LVwB7yI;&*z zCou{40d@^1Fq%;S19++!*eQaA7Pb_7gCG?)K0oO=P?vKe8zz>{=1;guvl}S)mA)z$ zv0Xzs;rreEwotBilq7GVU@e9k%K1F8YIm&OXi6WXgkSG-w{B{Df4;;6zvwJ?iGRRR zI?Srz#kUZsZAbaq|gR!8=w$kF`EP=o6pBE1_F6!fG|0O?iEW7+%m9~D|HaR2}S diff --git a/dialogflow-samples/build.gradle b/dialogflow-samples/build.gradle deleted file mode 100644 index 79a3875..0000000 --- a/dialogflow-samples/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath 'com.google.cloud.tools:appengine-gradle-plugin:+' - // latest App Engine Gradle tasks - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$project.ext.kotlinVersion" - } -} -repositories { - mavenCentral() -} - -apply plugin: 'idea' -apply plugin: 'kotlin' -apply plugin: 'java' -apply plugin: 'war' -apply plugin: 'com.google.cloud.tools.appengine' - -dependencies { - compile('javax.servlet:javax.servlet-api:3.1.0', - 'com.google.appengine:appengine:+', - "com.google.code.gson:gson:$project.ext.gsonVersion", - "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$project.ext.kotlinVersion") - compile project(':sdk-gson-servlet') -} - - -appengine { // App Engine tasks configuration - run { // local (dev_appserver) configuration (standard environments only) - port = 8080 // default - } - - deploy { // deploy configuration - stopPreviousVersion = true // default - stop the current version - promote = true // default - & make this the current version - version = 'prod' - } -} - -sourceCompatibility = "1.8" -targetCompatibility = "1.8" - diff --git a/dialogflow-samples/conversation_agent.zip b/dialogflow-samples/conversation_agent.zip deleted file mode 100644 index 5d6c787f0483a02ac7e8b48a85de57e859035909..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6586 zcma)=cQl;s*2alWbVKx-FiO;5ln6o?8PR)Zn28ypMT-ccL>s+Diy9IoY7jMQgwYeD zClaEUXpwM6-t!(_=X_b;o_}W6tmj(m*}r@5``TMe0}r1LhnSccr?oB>jB_SPvEQv7 zpib^r@47iVA>&$|CPXfVtb2#IEL<`6T4gy|c1ZLptGV@4ZB=C>L*UytY?N${N{9Ti{91H)jrTNZ|AG4ZWy2>m+VoXunzSq90(Old`c`THBlhx|*<4)5^bB(2E@A`}7 zspN(q6E#cE7IeSaas+YL6*-rACXWK`vV-J7G&18-p!{$AOx>C_^P85lbF`?~i-HE- zw<6zivEB10o;wZL-u)b?BI?$(CO3y-BZDR>i9eJ#Hhe&-&do|h{U z1F3Il5c%97x1PkGkj>5iI?xRZ_hcRlspE`5kZ!_{ytjU`YiSS>Z+Db+2jk-4e7=B# zqxFBnO?V$ z1I7@N1HOHc+6E^i!VO+><-T1Okor^eXK8J9)9M&b*QTy1&vyroI8-2wE3Ft+4KF`- z$*}i7LGLQvMNQjn=Q*+!uzsF8gh+ZCESJx z6|U|gpwxwla1|6JxB){ybS*36G=)QfH`s9YN!OFOEPlyQKrciD<{Lopi}<^23-5#1 z^}h>ryV2YpU#fDj5|DU!;fh;evYn8VkIRqPz`*6=)CXcKK{Z@76WqEj?40qbK5p?n zD@oSM7vHF`y(I;VU;;Xrc<`LGiVtC4cdzDGC$vuc%GAB@j4>0xj7jk!R%+mqt%9W; zJzFQJ&$0M*XAICN@{7PD#T6wP)(^f84Af!1kaRiYm9SxB&ra2Gr1w6n&;<7k<-)om zJG=>Vtt@gx)pb>B-hN09cS^T@)Msxcg3Uah!qPFGF6~1FUmk`9xV2XAQHvx&nDq{X z5@GV$9vov45)pg%-p2{RB3;G%6H@N~fz%L+uysa4&k{vyw>kxhTx{G1X!k<{OA|Z{ z$H4KDt6C8G+w%A#$dQ=r_Ls`~$9|jx)cU=g6*ImymgyQdh>_%rLdzHZu2>!#qc(;* ztHR@9JH*@f4ib3haxM@Xx}=5l>ZcWMOPI9x#K|<;UHc9Y)_P^YF&@CDM?SC5rN$!h zQU!YLx#>OcXMzVo(|Y6u+Cz_m1aEYAOyLovKmY*R&T1Dyff#{t=GhAP=A2w)VSILR z_6@$u!_;VGO3e}VcUFra(UsZpO(77$eaP_|>}yZ~E?;!xQ`Y%g`I=)w3|d19gC3E) ztwPN71F%wwuKuwr+Wss)Z1oSA_7Mt7p)!)k)gZmoas#+u)2-m! z zJpr{WD3F-c*W9MUp?0NJ@avF8)vKWbp^3=N8N+Zcx2+o(x7Q1qzE=y?>0-xnj9Ule z7GSIE+U}&zXyP@|Hrn^wAhb<*_os{7JRx~T?Fqc@Nd+nv6_0P1U1MRn2)3R6JpV8>N{@f`R z^bw)A?7rMR+mk(dr12o8yl|j#vg(*(y!O(HJo&CqO=&D>K6h(JNS3@4^>tu!j;M;h zhFkd9(|yF8$6bc7WVd(5!{B;323Wmk5Zr!ixnUwqQi(Aux~vbrhyT67(7U#~OVn~U zUreBAQb!G#wkpl==}yIk8vh;TP=#65x#U|vTzD5OPY`WFJJ~F-h$jAs2yhmWH}ni3 z?OtplP`z0YpjvqC>J?(at+E6v@p&MxchZ<=H)oyt?-K=I)dD}Et$71ZFv%g z+b=uVCmfSl2>~#A&3Wh>KTUAkn@>ftR)dgxF@(IuI>@Qzfew!mR8&B3`W7D;WW4DG zp`qusGyjxkCuc*_8xF`-o-GfdJ$mw48&=}_e6+;V-N_?sfE9FT-}Ad+D~&SmfHO+{B~%)tkO&)nM!6OJ zMX@NCjGyPaPfSBJvrqzkjawyfRRQ&olHZwd{7pUeG=F3KJE!1;oN2Tv$rL0>i`8;+ z=m_FW_Yh=f(BM$#^J&KT7&|1#Tn8ZE!_`wqLJY*{(dSE2|i3ra4dHy7+j zIO7^pZp5NGBy81_t`E*@hj9Vz5ozs9f~o;riRYX)TV&x4!Pl%A4wb zw&PBbeS`1#?IDK)Uyq@csV5q8OL<@nXJw%1;L()ga;~mGV*IwDd(+LQ&(VRn)v*{g zg!wwpYV@tfk<2_PsIiOJzRwy>p9Qoj`ASLo@v{vb_7d(uck7KZ#uXl)op^pt z=}m+}@R{Fke?`uNp`*)D@asgqsYEJD(Uf~jnc)lGI2I6!9}rH268lyssl)uu zL_s5djcoBw*_M-bWN$-@De^wJp+paCaOfiZN&!gtbAKtBV%;ZqV}kovedYFVheeJ4 zEUAh`@#>E#E}c2=ZXON}P&aqDvyf|E(lend^BSJ9E)N3lna#8d(^VR`s`Z1xUY+68&0JhB^!l{~ zIz|^Z{c>7Uh1)}QlJomO)?kCjj;XZzFtCVB8Kao}rsYO+Ogfp#d>x_9qbF)kpjbxI zz{{cF1P(7vg*!+7ErttK;uU~Sm^whT4QGz@S}dPL!0jQhm3u%Ve)6}N;1lz?|x=aq%!RjL>@Gc95wb1 z)7S26R#ZR7OH(--?r3B)LtM>n2wxxc{dm>tNG@MlAx-H+Z}vL%&f5BiwWS+AhMre_ zXlV&pn}I(4cG%fL+~d*#(3rcV2hB$73y{mdjS5fMu>A8$EBu20jBs5 zw>Mbc-qyNZ0qD@+phH(w5JwvI0n;ob(m|5aQBz#YvuFZzPH_7pY}w$F6ZQXE^1T7TOyv7rBNfQ^<$23rlzo? z`&ZfN_q`s-zZtZDQ8l5KZ&%HHhwvbg-^kl*J2~3fH-EN^d&+}%!T*GW{F;KjGL}T` zA4`$?3<(6>?XQ8=Pp36HP=u=S5b(H?Cp)LykTzbv!B>n~3|WXV0>XROm_9c<1H)#S zKry?GsZ!4NKB@SMM$99o(oZ*pKGykCnf;s*4Fn1D2tu|WZ-osU@SE^FRyC$6%efrG zSP=7dTc2Lj8FW$bJ6QP|+T>?-Q~_OQh`h_Hre$Ne2)kD?kCFQzOI~YcPVrUdC@)uy z9eBpLT@T|O-7urJq(QDA!FOBID6u%(w$J0~csurQX*55YZW50efZCTZhHi=PI@kR~ zIJE@y;H0DgD$ZbehLF4M63l*94B8r?(LJfx@VFT4|A?n(ySu2^7le;j4bdN!<~cJ{z}h2M>{Bo5+?9bQ7# ze*wbWxE0k*Djf5{vYxUK*_7Fr&l9qF5HE_4_JR|%f4HP|;$B{lSnZPRGN$XuP^k4fC&`6qsY418Y{V% z%5J&qgC_eaF_Y+@1G|tb+eI+bn{}&-P30f&Hg0F@N1={#pEA}K3>CN%vG>Lwku1f0 z8MOhiPH~h~kB?wVUeuSSp}y(a_!pDKG&sz-fBe?bcBd?TA|vDB@3E81@Er_}W##Zk zR{z6tSi3p?$8xk`EyqDPpLpr*#FQZbNs)Moj2>&|Dnt3bmG1i(uJ+~+E*yD4My^B6 z^|k2(iQbAgJBu~lQm-4|2OoFyF}`A9d>hWm%Ml((*UcD^Z@?>Dyrog=`qs&b38ZosazR$EPhZcgPgjH%%! zy}*?$`i-0IH2gZmM)}=!0ZhCBG!)2kYRXbb<{;XATvxp@UU|mo z^QNYAY+HE~VF0u?jHkcYir}%o0zoHJUk z8IEv2hA*rK(-`H*Vu^RMCyvAAoeUt_r6zAGd0^e*OJ6QavS)zQ7_yq2Ilo%0!A00x z4o>lDgC<$?#Bm64oj8ua%wK3=`iaB-v*S2>;hc=295x=vR#fdRKMv1HNV6HAUA~N1+ghQ=+hyQvzPt4E#oTssfN`BL03leNAr4E zGgJggf*Ky*4y1z7-Q={y=OMN3;chz!1PwjZ6nmXBFPB$EDsPZX0ifOvZ>C*(oZm{v zFSWtEIzVvWqh~RWcZ4)isytV6r3VetB14RZx=#nfc#w*FD~y+vhv=U={-O+)eM$YC zzn%P8e4|KisV}j=xJ9o>Z}(@FgaPyuZ+o6yj*#|3rtJ$GU7P`P{Y7uy$UW7K!rm2%(2{1k6LM3!c9t-VW59^!}q=o;X)x@y?hsqS&(`WF-)%xc!M_+h%1S^}mPsY-(pHHwM(bOAQ8n?t+BAJ=O!wM%dJEV#{Bh9mVL z&nJC{JdTyiU#bNoTPCT%-x&MuI_ZIL z>@;Gqo$S2g|5%Zo7d*RYIB9pMfsb{7e+!=5|C|>&J0+joZ>Ld+&E|hZ&Tc5qOPrkn zPsZuf5GFpA`0wHRyw2GH=AZAAKys>cZhky3a@GW&%sQvRPIfACe)2i5a@N3|^sm$4 zAU{?4FZ+C6=B%waaeJpxOmQmnAMbbm@v}GGKiQa4oj(2#Cvsjw>r9LOXHJP|P9^@G p)4wms^CD;K>z~<(r9Bn-uimbuL4Z9%I5_0kPXzXeGt!^@`WIg)*NXrE diff --git a/dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt b/dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt deleted file mode 100644 index 5614034..0000000 --- a/dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSample.kt +++ /dev/null @@ -1,215 +0,0 @@ -package com.tmsdurham.actions - -import main.java.com.tmsdurham.dialogflow.sample.DialogflowAction -import java.util.logging.Logger -import javax.servlet.annotation.WebServlet -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - - -val logger: Logger = Logger.getAnonymousLogger() - -const val NORMAL_ASK = "normal.ask" -const val NORMAL_BYE = "normal.ask" -const val BYE_RESPONSE = "bye.response" -const val BYE_CARD = "bye.card" -const val WELCOME = "input.welcome" -const val BASIC_CARD = "basic.card" -const val LIST = "list" -const val CAROUSEL = "carousel" -const val SUGGESTIONS = "suggestions" -const val ITEM_SELECTED = "item.selected" -const val CARD_BUILDER = "card.builder" - - -// Constants for list and carousel selection -const val SELECTION_KEY_ONE = "title" -const val SELECTION_KEY_GOOGLE_HOME = "googleHome" -const val SELECTION_KEY_GOOGLE_PIXEL = "googlePixel" -const val SELECTION_KEY_GOOGLE_ALLO = "googleAllo" - -// Constant for image URLs -const val IMG_URL_AOG = "https://developers.google.com/actions/images/badges" + - "/XPM_BADGING_GoogleAssistant_VER.png" -const val IMG_URL_GOOGLE_HOME = "https://lh3.googleusercontent.com" + - "/Nu3a6F80WfixUqf_ec_vgXy_c0-0r4VLJRXjVFF_X_CIilEu8B9fT35qyTEj_PEsKw" -const val IMG_URL_GOOGLE_PIXEL = "https://storage.googleapis.com/madebygoog/v1" + - "/Pixel/Pixel_ColorPicker/Pixel_Device_Angled_Black-720w.png" -const val IMG_URL_GOOGLE_ALLO = "https://allo.google.com/images/allo-logo.png" -fun welcome(app: DialogflowApp) = - app.ask(app.buildRichResponse() - .addSimpleResponse(speech = "Hi there!", displayText = "Hello there!") - .addSimpleResponse( - speech = """I can show you basic cards, lists and carousels as well as suggestions on your phone""", - displayText = """I can show you basic cards, lists and carousels as well as suggestions""") - .addSuggestions("Basic Card", "List", "Carousel", "Suggestions")) - -fun normalAsk(app: DialogflowApp) = app.ask("Ask me to show you a list, carousel, or basic card") - -fun suggestions(app: DialogflowApp) = - app.ask(app - .buildRichResponse() - .addSimpleResponse("This is a simple response for suggestions") - .addSuggestions("Suggestion Chips") - .addSuggestions("Basic Card", "List", "Carousel") - .addSuggestionLink("Suggestion Link", "https://assistant.google.com/")) - -fun basicCard(app: DialogflowApp) = - app.ask(app.buildRichResponse() - .addSimpleResponse("This is the first simple response for a basic card") - .addSuggestions( - "Basic Card", "List", "Carousel", "Suggestions") - // Create a basic card and add it to the rich response - .addBasicCard(app.buildBasicCard("""This is a basic card. Text in a - basic card can include "quotes" and most other unicode characters - including emoji 📱. Basic cards also support some markdown - formatting like *emphasis* or _italics_, **strong** or __bold__, - and ***bold itallic*** or ___strong emphasis___ as well as other things - like line""" + " \nbreaks") // Note the two spaces before "\n" required for a - // line break to be rendered in the card - .setSubtitle("This is a subtitle") - .setTitle("Title: this is a title") - .addButton("This is a button", "https://assistant.google.com/") - .setImage(IMG_URL_AOG, "Image alternate text")) - .addSimpleResponse(speech = "This is the 2nd simple response ", - displayText = "This is the 2nd simple response") - ) - - -fun list(app: DialogflowApp) { - app.askWithList(app.buildRichResponse() - .addSimpleResponse("This is a simple response for a list") - .addSuggestions("Basic Card", "List", "Carousel", "Suggestions"), - // Build a list - app.buildList("List Title") - // Add the first item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_ONE, - "synonym of title 1", "synonym of title 2", "synonym of title 3") - .setTitle("Title of First List Item") - .setDescription("This is a description of a list item") - .setImage(IMG_URL_AOG, "Image alternate text")) - // Add the second item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_HOME, - "Google Home Assistant", "Assistant on the Google Home") - .setTitle("Google Home") - .setDescription("Google Home is a voice-activated speaker powered by the Google Assistant.") - .setImage(IMG_URL_GOOGLE_HOME, "Google Home") - ) - // Add third item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_PIXEL, - "Google Pixel XL", "Pixel", "Pixel XL") - .setTitle("Google Pixel") - .setDescription("Pixel. Phone by Google.") - .setImage(IMG_URL_GOOGLE_PIXEL, "Google Pixel") - ) - // Add last item of the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_ALLO) - .setTitle("Google Allo") - .setDescription("Introducing Google Allo, a smart messaging app" + - "that helps you say more and do more.") - .setImage(IMG_URL_GOOGLE_ALLO, "Google Allo Logo") - .addSynonyms("Allo") - ) - ) -} - -// Carousel -fun carousel(app: DialogflowApp) { - app.askWithCarousel(app.buildRichResponse() - .addSimpleResponse("This is a simple response for a carousel") - .addSuggestions("Basic Card", "List", "Carousel", "Suggestions"), - app.buildCarousel() - // Add the first item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_ONE, - "synonym of title 1", "synonym of title 2", "synonym of title 3") - .setTitle("Title of First List Item") - .setDescription("This is a description of a carousel item") - .setImage(IMG_URL_AOG, "Image alternate text")) - // Add the second item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_HOME, - "Google Home Assistant", "Assistant on the Google Home") - .setTitle("Google Home") - .setDescription("""Google Home is a voice-activated speaker powered by - the Google Assistant.""") - .setImage(IMG_URL_GOOGLE_HOME, "Google Home") - ) - // Add third item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_PIXEL, - "Google Pixel XL", "Pixel", "Pixel XL") - .setTitle("Google Pixel") - .setDescription("Pixel. Phone by Google.") - .setImage(IMG_URL_GOOGLE_PIXEL, "Google Pixel") - ) - // Add last item of the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_ALLO) - .setTitle("Google Allo") - .setDescription("Introducing Google Allo, a smart messaging app" + - "that helps you say more and do more.") - .setImage(IMG_URL_GOOGLE_ALLO, "Google Allo Logo") - .addSynonyms("Allo") - ) - ) -} - -// React to list or carousel selection -fun itemSelected(app: DialogflowApp) { - app.getIntent() - val param = app.getSelectedOption() - logger.info("USER SELECTED: $param") - when (param) { - null -> app.ask("You did not select any item from the list or carousel") - SELECTION_KEY_ONE -> app.ask("You selected the first item in the list or carousel") - SELECTION_KEY_GOOGLE_HOME -> app.ask("You selected the Google Home!") - SELECTION_KEY_GOOGLE_PIXEL -> app.ask("You selected the Google Pixel!") - SELECTION_KEY_GOOGLE_ALLO -> app.ask("You selected Google Allo!") - else -> app.ask("You selected an unknown item from the list or carousel") - } -} - -// Receive a rich response from Dialogflow and modify it -fun cardBuilder(app: DialogflowApp) = - app.ask(app.getIncomingRichResponse() - .addBasicCard(app.buildBasicCard("""Actions on Google let you build for - the Google Assistant. Reach users right when they need you. Users don’t - need to pre-enable skills or install new apps.""" + " \n \nThis was written in the fulfillment webhook!") - .setSubtitle("Engage users through the Google Assistant") - .setTitle("Actions on Google") - .addButton("Developer Site", "https://developers.google.com/actions/") - .setImage("https://lh3.googleusercontent.com/Z7LtU6hhrhA-5iiO1foAfGB" + - "75OsO2O7phVesY81gH0rgQFI79sjx9aRmraUnyDUF_p5_bnBdWcXaRxVm2D1Rub92" + - "L6uxdLBl=s1376", "Actions on Google"))) - -// Leave conversation with card -fun byeCard(app: DialogflowApp) = - app.tell(app.buildRichResponse() - .addSimpleResponse("Goodbye, World!") - .addBasicCard(app.buildBasicCard("This is a goodbye card."))) - -fun byeResponse(action: DialogflowApp) = - action.tell(speech = "Okay see you later", - displayText = "OK see you later!") - -fun normalBye(action: DialogflowApp) = action.tell("Okay see you later!") - -val actionMap = mapOf( - WELCOME to ::welcome, - NORMAL_ASK to ::normalAsk, - BASIC_CARD to ::basicCard, - LIST to ::list, - ITEM_SELECTED to ::itemSelected, - CAROUSEL to ::carousel, - SUGGESTIONS to ::suggestions, - BYE_CARD to ::byeCard, - NORMAL_BYE to ::normalBye, - BYE_RESPONSE to ::byeResponse, - CARD_BUILDER to ::cardBuilder) - -@WebServlet("/conversation") -class WebHook : HttpServlet() { - - override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { - DialogflowAction(req, resp).handleRequest(actionMap) - } -} - diff --git a/dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSampleJava.java b/dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSampleJava.java deleted file mode 100644 index 1ad431b..0000000 --- a/dialogflow-samples/src/main/java/com/tmsdurham/actions/ConversationComponentsSampleJava.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.tmsdurham.actions; - -import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import main.java.com.tmsdurham.dialogflow.sample.DialogflowAction; - -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Logger; - -import static com.tmsdurham.actions.ConversationComponentsSampleKt.*; - -/** - * Conversation sample in Java. - */ -@WebServlet("/conversation/java") -public class ConversationComponentsSampleJava extends HttpServlet { - private static final Logger logger = Logger.getAnonymousLogger(); - - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - DialogflowAction action = new DialogflowAction(req, resp); - action.handleRequest(intentMap); - } - - Function1 welcome = app -> { - app.ask(app.buildRichResponse() - .addSimpleResponse("Hi there from Java!", "Hello there from Java!") - .addSimpleResponse( - "I can show you basic cards, lists and carousels as well as suggestions on your phone", - "I can show you basic cards, lists and carousels as well as suggestions") - .addSuggestions("Basic Card", "List", "Carousel", "Suggestions"), null); - return Unit.INSTANCE; - }; - - Function1 normalAsk = app -> - app.ask("Ask me to show you a list, carousel, or basic card"); - - Function1 suggestions = app -> - app.ask(app.buildRichResponse(null) - .addSimpleResponse("This is a simple response for suggestions", null) - .addSuggestions("Suggestion Chips") - .addSuggestions("Basic Card", "List", "Carousel") - .addSuggestionLink("Suggestion Link", "https://assistant.google.com/")); - - Function1 basicCard = app -> - app.ask(app.buildRichResponse() - .addSimpleResponse("This is the first simple response for a basic card") - .addSuggestions( - "Basic Card", "List", "Carousel", "Suggestions") - // Create a basic card and add it to the rich response - .addBasicCard(app.buildBasicCard("This is a basic card. Text in a " - + "basic card can include \"quotes\" and most other unicode characters " - + "including emoji 📱. Basic cards also support some markdown " - + "formatting like *emphasis* or _italics_, **strong** or __bold__, " - + "and ***bold itallic*** or ___strong emphasis___ as well as other things " - + "like line \nbreaks") // Note the two spaces before "\n" required for a" - // line break to be rendered in the card - .setSubtitle("This is a subtitle") - .setTitle("Title: this is a title") - .addButton("This is a button", "https://assistant.google.com/") - .setImage(IMG_URL_AOG, "Image alternate text")) - .addSimpleResponse("This is the 2nd simple response ", - "This is the 2nd simple response") - ); - - - Function1 list = app -> - app.askWithList(app.buildRichResponse() - .addSimpleResponse("This is a simple response for a list") - .addSuggestions("Basic Card", "List", "Carousel", "Suggestions"), - // Build a list - app.buildList("List Title") - // Add the first item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_ONE, - "synonym of title 1", "synonym of title 2", "synonym of title 3") - .setTitle("Title of First List Item") - .setDescription("This is a description of a list item") - .setImage(IMG_URL_AOG, "Image alternate text")) - // Add the second item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_HOME, - "Google Home Assistant", "Assistant on the Google Home") - .setTitle("Google Home") - .setDescription("Google Home is a voice-activated speaker powered by the Google Assistant.") - .setImage(IMG_URL_GOOGLE_HOME, "Google Home") - ) - // Add third item to the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_PIXEL, - "Google Pixel XL", "Pixel", "Pixel XL") - .setTitle("Google Pixel") - .setDescription("Pixel. Phone by Google.") - .setImage(IMG_URL_GOOGLE_PIXEL, "Google Pixel") - ) - // Add last item of the list - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_ALLO) - .setTitle("Google Allo") - .setDescription("Introducing Google Allo, a smart messaging app" + - "that helps you say more and do more.") - .setImage(IMG_URL_GOOGLE_ALLO, "Google Allo Logo") - .addSynonyms("Allo") - ) - ); - - // Carousel - Function1 carousel = app -> - app.askWithCarousel(app.buildRichResponse() - .addSimpleResponse("This is a simple response for a carousel") - .addSuggestions("Basic Card", "List", "Carousel", "Suggestions"), - app.buildCarousel() - // Add the first item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_ONE, - "synonym of title 1", "synonym of title 2", "synonym of title 3") - .setTitle("Title of First List Item") - .setDescription("This is a description of a carousel item") - .setImage(IMG_URL_AOG, "Image alternate text")) - // Add the second item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_HOME, - "Google Home Assistant", "Assistant on the Google Home") - .setTitle("Google Home") - .setDescription("Google Home is a voice-activated speaker powered by" - + "the Google Assistant.") - .setImage(IMG_URL_GOOGLE_HOME, "Google Home") - ) - // Add third item to the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_PIXEL, - "Google Pixel XL", "Pixel", "Pixel XL") - .setTitle("Google Pixel") - .setDescription("Pixel. Phone by Google.") - .setImage(IMG_URL_GOOGLE_PIXEL, "Google Pixel") - ) - // Add last item of the carousel - .addItems(app.buildOptionItem(SELECTION_KEY_GOOGLE_ALLO) - .setTitle("Google Allo") - .setDescription("Introducing Google Allo, a smart messaging app" + - "that helps you say more and do more.") - .setImage(IMG_URL_GOOGLE_ALLO, "Google Allo Logo") - .addSynonyms("Allo") - ) - ); - - // React to list or carousel selection - Function1 itemSelected = app -> { - app.getIntent(); - Object param = app.getSelectedOption(); - logger.info("USER SELECTED: $param"); - if (param == null) { - app.ask("You did not select any item from the list or carousel"); - } else { - switch ((String) param) { - case SELECTION_KEY_ONE: - app.ask("You selected the first item in the list or carousel"); - break; - case SELECTION_KEY_GOOGLE_HOME: - app.ask("You selected the Google Home!"); - break; - case SELECTION_KEY_GOOGLE_PIXEL: - app.ask("You selected the Google Pixel!"); - break; - case SELECTION_KEY_GOOGLE_ALLO: - app.ask("You selected Google Allo!"); - break; - default: - app.ask("You selected an unknown item from the list or carousel"); - } - } - return Unit.INSTANCE; - }; - - // Receive a rich response from Dialogflow and modify it - Function1 cardBuilder = app -> - app.ask(app.getIncomingRichResponse() - .addBasicCard(app.buildBasicCard("Actions on Google let you build for" - + "the Google Assistant.Reach users right when they need you.Users don’t" - + "need to pre-enable skills or install new apps. \n \nThis was written in the fulfillment webhook!") - .setSubtitle("Engage users through the Google Assistant") - .setTitle("Actions on Google") - .addButton("Developer Site", "https://developers.google.com/actions/") - .setImage("https://lh3.googleusercontent.com/Z7LtU6hhrhA-5iiO1foAfGB" - + "75OsO2O7phVesY81gH0rgQFI79sjx9aRmraUnyDUF_p5_bnBdWcXaRxVm2D1Rub92" - + "L6uxdLBl=s1376", "Actions on Google"))); - - // Leave conversation with card - Function1 byeCard = app -> - app.tell(app.buildRichResponse() - .addSimpleResponse("Goodbye, World!") - .addBasicCard(app.buildBasicCard("This is a goodbye card."))); - - Function1 byeResponse = app -> - app.tell("Okay see you later", "OK see you later!"); - - Function1 normalBye = app -> app.tell("Okay see you later!"); - - private Map> intentMap = new HashMap() {{ - put(ConversationComponentsSampleKt.WELCOME, welcome); - put(ConversationComponentsSampleKt.NORMAL_ASK, normalAsk); - put(ConversationComponentsSampleKt.BASIC_CARD, basicCard); - put(ConversationComponentsSampleKt.LIST, list); - put(ConversationComponentsSampleKt.ITEM_SELECTED, itemSelected); - put(ConversationComponentsSampleKt.CAROUSEL, carousel); - put(ConversationComponentsSampleKt.SUGGESTIONS, suggestions); - put(ConversationComponentsSampleKt.BYE_CARD, byeCard); - put(ConversationComponentsSampleKt.NORMAL_BYE, normalBye); - put(ConversationComponentsSampleKt.BYE_RESPONSE, byeResponse); - put(ConversationComponentsSampleKt.CARD_BUILDER, cardBuilder); - }}; - -} - diff --git a/dialogflow-samples/src/main/java/com/tmsdurham/actions/TransactionsSample.kt b/dialogflow-samples/src/main/java/com/tmsdurham/actions/TransactionsSample.kt deleted file mode 100644 index ddfbed3..0000000 --- a/dialogflow-samples/src/main/java/com/tmsdurham/actions/TransactionsSample.kt +++ /dev/null @@ -1,169 +0,0 @@ -package com.tmsdurham.actions - -import main.java.com.tmsdurham.dialogflow.sample.DialogflowAction -import javax.servlet.annotation.WebServlet -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -// Dialogflow Actions -val TRANSACTION_CHECK_NO_PAYMENT = "transaction.check.no.payment" -val TRANSACTION_CHECK_ACTION_PAYMENT = "transaction.check.action" -val TRANSACTION_CHECK_GOOGLE_PAYMENT = "transaction.check.google" -val TRANSACTION_CHECK_COMPLETE = "transaction.check.complete" -val DELIVERY_ADDRESS = "delivery.address" -val DELIVERY_ADDRESS_COMPLETE = "delivery.address.complete" -val TRANSACTION_DECISION_ACTION_PAYMENT = "transaction.decision.action" -val TRANSACTION_DECISION_COMPLETE = "transaction.decision.complete" - -@WebServlet("/transaction") -class TransactionSample : HttpServlet() { - - override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { - DialogflowAction(req, resp).handleRequest(transactionMap) - } - -} - -fun transactionCheckNoPayment(app: DialogflowApp) { - app.askForTransactionRequirements() -} - -fun transactionCheckActionPayment(app: DialogflowApp) { - app.askForTransactionRequirements(ActionPaymentTransactionConfig( - type = TransactionValues.PaymentType.PAYMENT_CARD.toString(), - displayName = "VISA-1234", - deliveryAddressRequired = false) - ) -} - -fun transactionCheckGooglePayment(app: DialogflowApp) { - app.askForTransactionRequirements( GooglePaymentTransactionConfig( - // These will be provided by payment processor, like Stripe, Braintree, or - // Vantiv - tokenizationParameters = listOf(), - cardNetworks = mutableListOf( - TransactionValues.CardNetwork.VISA, - TransactionValues.CardNetwork.AMEX - ), - prepaidCardDisallowed = false, - deliveryAddressRequired = false) - ) -} - -fun transactionCheckComplete(app: DialogflowApp) { - if (app.getTransactionRequirementsResult() == - TransactionValues.ResultType.OK) { - // Normally take the user through cart building flow - app.ask("Looks like you're good to go! Try saying ' Get Delivery Address '.") - } else { - app.tell("Transaction failed.") - } -} - -fun deliveryAddress(app: DialogflowApp) { - app.askForDeliveryAddress("To know where to send the order") -} - -fun deliveryAddressComplete(app: DialogflowApp) { - if (app.getDeliveryAddress() != null) { - logger.info("DELIVERY ADDRESS: " + - app.getDeliveryAddress()?.postalAddress?.addressLines?.get(0)) - app.ask("Great, got your address! Now say 'confirm transaction'.") - } else { - app.tell("Transaction failed.") - } -} - -fun transactionDecision(app: DialogflowApp) { - val order = app.buildOrder("") - .setCart(app.buildCart().setMerchant("book_store_1", "Book Store") - .addLineItems( - app.buildLineItem("memoirs_1", "My Memoirs") - .setPrice(TransactionValues.PriceType.ACTUAL, "USD", 3, 990000000) - .setQuantity(1), - app.buildLineItem("memoirs_2", "Memoirs of a person") - .setPrice(TransactionValues.PriceType.ACTUAL, "USD", 5, 990000000) - .setQuantity(1), - app.buildLineItem("memoirs_3", "Their memoirs") - .setPrice(TransactionValues.PriceType.ACTUAL, "USD", 15, 750000000) - .setQuantity(1), - app.buildLineItem("memoirs_4", "Our memoirs") - .setPrice(TransactionValues.PriceType.ACTUAL, "USD", 6, 490000000) - .setQuantity(1) - ).setNotes("The Memoir collection")) - .addOtherItems( - app.buildLineItem("subtotal", "Subtotal") - .setType(TransactionValues.ItemType.SUBTOTAL) - .setQuantity(1) - .setPrice(TransactionValues.PriceType.ESTIMATE, "USD", 32, 220000000), - app.buildLineItem("tax", "Tax") - .setType(TransactionValues.ItemType.TAX) - .setQuantity(1) - .setPrice(TransactionValues.PriceType.ESTIMATE, "USD", 2, 780000000) - ) - .setTotalPrice(TransactionValues.PriceType.ESTIMATE, "USD", 35) - - // If in sandbox testing mode, do not require payment - if (app.isInSandbox()) { - app.askForTransactionDecision(order) - } else { - // To test this sample, uncheck the "Testing in Sandbox Mode" box in the - // Actions console simulator - app.askForTransactionDecision(order, ActionPaymentTransactionConfig( - type = TransactionValues.PaymentType.PAYMENT_CARD.toString(), - displayName = "VISA-1234", - deliveryAddressRequired = true) - ) - - /* - // If using Google provided payment instrument instead - app.askForTransactionDecision(order, { - // These will be provided by payment processor, like Stripe, - // Braintree, or Vantiv - tokenizationParameters: {}, - cardNetworks: [ - TransactionValues.CardNetwork.VISA, - TransactionValues.CardNetwork.AMEX - ], - prepaidCardDisallowed: false, - deliveryAddressRequired: false - }) - */ - } -} - -fun transactionDecisionComplete(app: DialogflowApp) { - if (app.getTransactionDecision()?.userDecision == - TransactionValues.ConfirmationDecision.ACCEPTED.toString()) { - val googleOrderId = app.getTransactionDecision()?.order?.googleOrderId - - // Confirm order and make any charges in order processing backend - // If using Google provided payment instrument: - // let paymentToken = app.getTransactionDecision().order.paymentInfo - // .googleProvidedPaymentInstrument.instrumentToken - - app.tell(app.buildRichResponse().addOrderUpdate( - app.buildOrderUpdate(googleOrderId!!, true) - .setOrderState(TransactionValues.OrderState.CONFIRMED, "Order created") - .setInfo(TransactionValues.OrderStateInfo.RECEIPT, - ReceiptInfo(confirmedActionOrderId = "") - )) - .addSimpleResponse("Transaction completed! You're all set!")) - } else if (app.getTransactionDecision()?.userDecision == - TransactionValues.ConfirmationDecision.DELIVERY_ADDRESS_UPDATED.value) { - return deliveryAddress(app = app) - } else { - app.tell("Transaction failed.") - } -} - -val transactionMap = mapOf( - TRANSACTION_CHECK_NO_PAYMENT to ::transactionCheckNoPayment, - TRANSACTION_CHECK_ACTION_PAYMENT to ::transactionCheckActionPayment, - TRANSACTION_CHECK_GOOGLE_PAYMENT to ::transactionCheckGooglePayment, - TRANSACTION_CHECK_COMPLETE to ::transactionCheckComplete, - DELIVERY_ADDRESS to ::deliveryAddress, - DELIVERY_ADDRESS_COMPLETE to ::deliveryAddressComplete, - TRANSACTION_DECISION_ACTION_PAYMENT to ::transactionDecision, - TRANSACTION_DECISION_COMPLETE to ::transactionDecisionComplete) diff --git a/dialogflow-samples/src/main/webapp/WEB-INF/logging.properties b/dialogflow-samples/src/main/webapp/WEB-INF/logging.properties deleted file mode 100644 index ad9a38d..0000000 --- a/dialogflow-samples/src/main/webapp/WEB-INF/logging.properties +++ /dev/null @@ -1,13 +0,0 @@ -# A default java.util.logging configuration. -# (All App Engine logging is through java.util.logging by default). -# -# To use this configuration, copy it into your application's WEB-INF -# folder and add the following to your appengine-web.xml: -# -# -# -# -# - -# Set the default logging level for all loggers to WARNING -.level = INFO diff --git a/dialogflow-samples/src/main/webapp/WEB-INF/web.xml b/dialogflow-samples/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 9e5b267..0000000 --- a/dialogflow-samples/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index aac7c9b..0000000 --- a/gradle.properties +++ /dev/null @@ -1,17 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 13372aef5e24af05341d49695ee84e5f9b594659..91ca28c8b802289c3a438766657a5e98f20eff03 100644 GIT binary patch delta 41671 zcmZ5{V{oQHw{2{5V%xUuiEX~&#Lkms!igrf?POxk#I|kQ&fK}T&aHF4(^b2x8oPgV zb*=8b_Ue#A$e40Sl&=bqP*`AKaByH?U}9kLC?uHw-Ac1484&r`uMsb*Dv)uUe&=%I z0uJ_{9{+~HApURluR#4XCl_lL$p1Abew+;9zgLZaqQm{~)|HQ5>eWBT1$Zzpro?zC zoJ4^Ed>}?k*K(-u0L9;r_a|#GqaGD@aWDNr z({TlzpWnm=Nts7=`l;|z<9EjrkVsN24SF=YI|0mogwmq#t<*d1A#`{fI?3N820Mmj zTiakibP~TYL_D>&t@(N9vUmo6wXC9GAj5^)8|sXfpp{)lL*p&P%MhaZgBw$gfR<<# z3xBK(g3)KjT}pRXGF*zpkWbguG}dH_*|L+I*_@V#Fr%BJr$k7}nA6=2Dt2^aXK>!+ zyZ{oEQmHgKW}9tS#xtV?mTvDAjh*v1Lr0D2jgdP9ZNT)I}JkWWlA=6Y02Y;POH;J%;Ovc?`6@KTYVD`(Y6ny9vR;8?lp|je#CW zdvsPGY3CMO=dLi`fS$HH9W47ji61$oIVN0|Dm^mKI-*m|FQc!96(J!iSbjgI%3_W1 z6WVpnI^ht6hstnWm_+8`+nXo*-o$%SpXGZb{FDMWT1&cGOZG5ZXc2L{ zE&Mo!XJV1-=>RO&PZ8hP3~Qdc_K5dpZ~ssuQ58EbZn{&~xjAN1FG~5`64UZ;lo#g&*Iu`G z+~)O(504`SXKQ)9Sv6&aXUbD};7keM986UrnomjA6pbb4BD*~$#P6zG_zj(~Y`V=k zMT+bKTXl(_13?~i-EyLLC4iK;lIYrg1M)P{ltWDItn~}4f9^{zDnzb#BXO~Qut$)` zUrFppO!5=s+^d1L@v53CH-^bEAQ8~HP zYzL&H=J?Ly7=MW5C9>?}$Rqde^`$B8XpaACicdJ?^xILoSEL}OKJnjdlKzlQnzIP) zCT&X68Zi%i98+OSO9zlHD$M}so#Jw9*KYOQK(Ax#Xhq}*8ZQ|7F9<|s+uIaSy`RP; zKYCgIe%@h)v*(+#psKK{N$pQ%_aY_e=LEumXHd%yo%sDAbuM$==ME;$B4Z73Lw`~# zaL-HS-0IbZSXN0Ek)eqXZ%IrTQzm~F;Jtd5`-J^3Y=!+VI8LMoU;Q6gIqJmkiuw<1 zMgQR?=l{dX8f`dm%0%YgFF>-op%aD}mJnppfF;OTvu;t|!7j9d@fjO=FvLVrF#@FK zVD`!x3SYHy`P200ZIq(lEbf}kF6y-m-W8apIQ)Wtn(tAL>y?nF)#FjElL%PS&9XEG z9|4LB<!D$ef4(-k!S7eqEot`P-T_mN()W&LwMq?n{1cE{Eh@C?FK3qr?r}r?!DQ zaJIP<^wsHEOccF^nLu!PZb8*)vt**Bxm{I5-co*luw z#qAnQwZ&c>Xhz02$}+T9q37X2`x6rl(DX=SO!=O)T`Zce5OG ziS#&^?1832A}yY6W&lhaVe%K3BQ(5o!xeSpn^~T{Qsw-D_+8RasS4*<#;}3r#cZ>o z==WxZq)=a!AJ@l(e<4cSVCZyd1zO`^OZp@bzRg>E>ckvxX^~lQ4}5tj;g5#y}s#eY8Vb z!DD)~JM_^$jE>}bwIfVp`4Q13<-@7acsD$Y*xUQaMs7SDNvdS$_vJkzs*#@p!oYxx zKmumP*(JFEW-LJFKAS+GCz!yq8k4enx0mgFO8r1sDQPTr6g{oC$+@l6g2J51zBy$) zf_2fX6Wf5Kq?#G!h38v(m4Xolv_Wu8rA55*JIsGx)IV>~Cs9$rz^Dnqz{vjV@Sp(M zx`-xNOYTA{s~dPR(j;24btczle{f#$3BEHSNn=1jC7|h1{xY$TYoq{~a#2i8Lb&Mj z#7gXPDy=s<3oDz^DC<2LpNC_c))sfVE1is)+WV(0$In?o#{Ddy zXG=&J$1h&kzsfi8)4Fdo^I1ymC zeRciR^bFhSxJ`1SNyOoDn7glRoXBB3cRi(+4#ZFV9zEQ$xV!rGg1X{o$o-cN`;~?0 zufsOfr_2zK+k0)86aI2|s+(VwanBxg$j>hNRap%JUUGGSVc@ggm?wLFK%m7T=m9#Cn=kSroJ5%z#!~54V#2Qh#+us}dN*Vcy=d5ilxWdeJEAHSfy8bZ_;pyLOYPo^s^_ z@la?!gc^t3Z-)9vf=9wfO$q~j`f5mXp&u(^TFmaz)L1C$u=SiT0STC+4#KFQYCu+J zAr!Bt<7IZ(6S{PzU*b*47oA^5<#35O`EE$qI@bmc-b8R&tB2;hE<#rdSn_dfux%;u za~N>93Yz+!6rI6wPWoO(TbIsBj5In4xZF+3XOg(F@Y5~HN2kQQ{+{lVqdB?4J+?EH zs!qin-U*(oTA}9M#HO7+);iv`~zm5*b(+LpSVTraL2>}KvOLn6Q`z5kp3)ZvE zO9JLcrgAbWRwboW;uVwksw6ZVJXQ)DXI@%*LnObl@qm^1Ws)GL9V{0nb zvVqkK(ZS;04Um{&Q%tGXIwen2I@;A#Sm3Hv!MI_eh&|+1$GMZoaly`~s0Z?WssXo_ z-+5bHL})F?s*d4k&NaUca{v~L54e-2y&v6v%(lDQ74bMo8RRXvNH}>j^9p;%D$WkM zT-NMu1|AeABviD8RKR6I?Brnd{=B6SIFskqxFk?R1on0Nys}4&7`KR7GIml%H+2H6 zEV*SYS^aYajNF8XsXFZipcR9fsnOfiXPsr^{HFjEwBd>9!hR$1?p~~f;Fs`sO*wfiFME}eCI$v>`fz`M`TA@ z0D|gFsraID(jdzB8cvBMW;yf@%LW-t&&*xo8S`BVufcvqulTT^r=Ij@n zW$=;+I1xsTvojcj%;mT%`zzr}Y~-u&M2yyR7IsF?i#SX$O@BGGsyTEQ>Ux-d>JjLsg|%0K$=Q7Q_FFYr&KhJ0v%$G ztVz|E*9a%abF!KL(CtwKF&5)f-~1}$1_tVM zo^RURBf=& zc#?2roiy`B8IX&q&sXgKg;7y_i-0a?9=(EUt;5T_^3;qVC3kS!oP$FL(6y!|$SeNp z#7Klz{Cf)#&yCNh^tYG*T2NCRMt|yFt^h+ZE9>F*z-lnDn>IQ%6|7Bnv|6DAHkCPU zR^C~oB%&Zd3A=>O_yFBSvtq7jsQbb>{G9)wKnRH(#ldZml(O(HQ+TX+Kakw)q-@OWjhj<02on9Ah4p_;J_oLi&ZU&wWdRM;L@e zipbt@{9f$j6pArNJ+0PGmrXl6a5b;XtUc}i+6pI?8Tdqnlo&cq-j2n7?NP&y{aMwDvW>e-4qhqZmD-w=E8{>R z=eBdFW~9v@OQ16*%gI{gPdeLUE-hRoJ`K*kikExUzEAMQ(sbHDM$WW*$llTnR_S(A zlnrrY$S<1{_{Js~h$tNyh1#nb@}O^&1(x+>7{g}fD&LeCjAnh^_}W1&stu*hRw{;+ zUuGJXv9=7=9~cj7OkHt!0JI4fa{SGN0j8yTF5=DR2;hRHWu9xvp!spWX}-eALE%Dg zonQNI(|UUIQBEUVzhT)~UTM|WmJhQ%sP4Uyhagq|R5-L5ji18D-Bk(aVhT9R{t^Co z77gVj8VA*IeA*e*JjvLeJG7V+HhPv}5Xag19^AWX=ao(EOJuCMm30E7*+5(#mW5+I z&Az`y08t8(Rc;GzJ+P;UH8j>oW|VjZ9>fx#Tn}5qmI=Goec2 zDJE}FZi!t$&U`M#gI&ZPB5w@K4pMh?!!rVL9*(nLw(Hg(yq=aoxLt75UbRbrhpT*u z!3#DZ5Ty%}WKbYdGX{fY5B7#x{D2JRxdU$(;7WR=J;<@P7#x0+@ItkvyTO=xB%Z&a ztlgElHo_||r~#vSy!~dz0$WP28dZ8NtbrK0Pbl;C*h@rMbc``bDV60z@K>B_d&qvu zS*y@y%7AjuADy?Gl$q6eb{GA$m1-Io(^tKzdOw!E~1?e!Z*Y$2SBO{qwiXQIM z%DF74bYM!PL{Lod#3sd9-1srDyk;ET_2HEgR!;u3@mwZP0bSkVlA^L{fRFx0OVyuD z>OW5E8k8s57TM>mHpb;Af%^R!DV@f-?k|SD5+Vc&ELa0ZU6l4GN zTW7nFpJ0?KMs#N|ruHy?VinDp4h6VsWGBrxqP?5zkmx&g7InGoVZy!NY=@mg8n<4O zL@Oq5S~cCsXWnIwB}v2uPSMX%=*~wGZ9@?)Ly?@Ig13{GhoWcRcq66L>SxtQ03u5_ zj->C-ZIv&Bi|2`#=wt60{?RPDF4sb(q?sn_&|fV*0hj&Y6RR*xC+T@kD@&oM=L+4ao?;UAg`V#YA%~E&X`PilF_tA$`DayhT^J_{>nPx6YTrj z35M|%BYlH1>W%B^D?6Szpq*4(xzD2N-PAoSM3pcZc2z1avC|;m23zE^1H1AF z)r&f!!fHRFLMymZ#_)tz7o;QjM}-xqG}Zj(YlsjN#*cxAN1aZ#`5x)BXv4nwWcFoY ziKd)lagu|k54KIeDfDKNBcf+`_aq9w&|4Y!9ju19#!9(3K#hoMJff>YIu@fx%wpjJ zm+BmM1<@sUqjk_IA}LobK_o_3lU&0zV+AFq{r$I*Z11zke}WX2`7F%-cQEGa+-4dNrJbpf4 zHk@vEcs%XzVgc%LA$d&m#=wpv%F#oBAb1t)^|tphCUt#9l)(sZo4cM5b?#?@Gh^W${MXe1r<4k)glKU z`PDF&xy(cIxpXUPbhN1ugC>qH$I{<8@qx3(4;bxf&Xx)v9RF0?c$nWb%4k1x$Fe)tBUA{ zJBfb{rna+EpF1)lemC8;x?r}5H>m2Xpa*F8eOYG*I%snj`>Z0_ozWBE7C?V)77$>Z zPJUX~GimEdI+!mOl`+vS(ncM$gD4=aD?jB^?m;dB7F^~{UHUyPwj)Hz4QVY(pmx1$ z6$dU0E=JWKMx*a(s_|s#0izL@62>j9w?k9Gv<48B{{8#Pd6iQ#QF_;*{zAol!%$6X zmd`{t{gAy(Y>NCZEdrp$z)tHGDx5|6+D4QKtmf8SKPtH=V8RiZnOflir zugy-DayS(VmMbl6r|}~rI~4Ovy5zdZ_AX%>>2=nI3}tWgBqZtM)k^pAQyLY+a$yt= zLJZ&K*qzrs2nSM|-NKSr4eD{MEH-a!Z|yfyg8JMZgznLeB&BFr1mqR;gN7F4O*t`* zHdwgM+TLc)3Dkg5n6Phse*y?uStB4Jr0r~Axbzfn+zhB`$6C07K zgk{Zk25B$!pmjTK!?uF9xwziZcy!OhxhEG49|%(unZL1KEoA>X@d?tsEyk8@uq~&| zIG}<^PZiqIXk=%>Oa*Pr#1}3hXZ?{2q9K-|3Q7Ye{ty7q^Ec_ z1&~ei;Wfd`b=X(v1dLeQV@QIOQzq|??df8mNmI*XE6^YD^Sup)Ln}BWC=4ItASqkSZzuP zn^F2x$iX#L4tpDoJq~Ygi2CK?Bx#(*J?gXgnEM!4fCtN@1_H?c;xT0y*SL6|%S4r) zMPZlrTXG`)*C=khaQ^g#EH3xx<|J|^Y;|1&Uu6`~ynfRngiqLaT})A(VG!hEmX9-x zP*P^ zID4V%m%{qKU2fkPkSE)0M;fpv+mm7=2tNb9^xn8@YVatWGah%$&A;EaF)hvN79LPu zHJI_2S3083J{U|0Tf;XX_=E-^IXGoC@|7U`j!BFE(k-=hD;|Ah&5+xyTYvtIRFUFw zU1s90#Ir=lO#k-Vcw)SP!z(EC97J4mX8xc;;e7rbO1 z^=(%NhGCwt&eZ$E(Cj5YeDAN3IDH(ZRbs98doY|@@k?aTYr2Ce_9uu}{ZgzQWTS}5 z@l4NgKE(uOMhe(J!vu4Vre@4Fcv1kap)&7IxvQz2N-_ZP{Ya)%?xD0#An$|uwZ%l` zAa0CMCG6-(VqBVXuD`TW<*WK%#v`3)jnC+sAm3%0Yv$d7CvU=16Wk5y!`Gj1##)3d zH}B+5%-1WO>t@{qrQh_VrX=amtpEOh^8dfMf2eYw4TFDVziNXgbP~k>$jY8o*(R1C z{ND^fodhS~hq;9JSLCPv?Th_)dscEJF)$YU(D;z$kokJ#FBSy$=4P_uC@*zVl-cph z(N^x1L~@zUZqyqbax`-KD=~>bCmT?e`L;TJ^R^sz?x6Mib5+qx7D=x5HT27il=pLz;Cq6_ zeG-XrN_6+`kT$lT(yB{~LHFel(d`pKfS>w6%e4da*3Di=!m}@ZcO1#^K{$Ot2ubBL zd_cvvH9gFYYtSmu$3=F0jl>&F`zz|j`Pm7;Ki^_q*HNoYipEz#vef4+#D`B@r&hmj zlPM|{p023xGmAgFhbKX*A-TE2wY*7mayouf?xFg4d3K3EE|xkGjDw!+7(->g$Q|_Z zfGh#gjp7Xu|3qM{5z(>##bl@wlVIF5R3CWivRPaTMNbr+hPO!^ zMIcyBsFE(&XeO;E4waMy(#vMsO^H1#Z|sR%c=3_mtN#|BE_*zJ4mu|$2#+2uu)5{N zlM7ZrgojZsW}>L4p`nix8{)+Crac5&vCZEFC0AXfZ;vCoNe%y`FuRC}69!7yLA zd0iC#5}1IxV2sHuEL2;G>MTI3N0rk)5N}t;pNY1_0Ag@IKUZ{SFAQl42OIeoUWaA# zQK7UJr(y@svyrM!Bb+&nR0B7^ei;j`;eKJqna9n4*;AA&*I_0~2*ci7+L{13#Q4Vk z=>wFhm_95fznsWxkN=F9Uo)^RvBXN+b%yOJhpk9ppS7aK=31TWXS)yiQ;_AjF>(`q z5GYqcG}*sP@gY4Q5u?w?nd#q6O>oANMJ;t`%tcdhcM!sFlDRWKwp$SF5D&p+5Ou~G zy{m=XvTcPdy>*lo*y2s;1 z9bbM2%4Jn`jH}-U#}M=0q{b6DDb20%H+Xe!YdU28f+czZKGO!_zbs3b8uP#B18gHVN}7=s3`S+$IQAmBxJCSamZTtKz&6@SBg&%g`ay zl8+=)s!G@mHtk5rR9B{(x}C9gW|LU63$su98HJH?iJ?K3NSF^K;n$|rL~@x`Q!hsH z2aOH)U2x?WZP<&SI8)#YU~ou_*YEQ^x6l?CVIsH2UaS;$vAPghg}F5dab93*8%1$8 ztD-Aq=&)qy#s=H>Wwb)IFqnO>iqk&{aplI8>rypBy=nC}Grk?99LsZhoz+p_Voi-| znRk2WT6Y!XMU4WwPlSDPn&*$$SxDyQF3M*Vdu8=-)tH8~C!u7_3e&L=?Hp9sn7E~l zyr~}N*|hBhhk^y!J5Fxs@wuwr^_@rVV>AV6X)g&WzC92!{}5z8k9I(Y_T`hbtnyfS zfOrUP<@9(6m4T-p(_1(8Y7p44b)AuAEnTr_wuFAtuU`VX!Y4yRf5CTrc1CwGhn@^x zdGl8etwCV*H3yfF+>fHFpig$~c^|s7EW0p25>6l(P9OLDy3W}c(TE(oDb3*X+QF;i z{eHf_pk5_Fb7JJ58fRepNnE`I!YO4_3T`5`_Fl|$FQxO zmcNF29bNXiyY}thMWeX>Jqlf-?J!>y;5N(Pu^Pk+e}zPr&BBc;Mvz}OBCb-LOm1|ja%RX4_Sk549tq$5V51R$( z)yf)7=8f`L^W2LCB0T$1HYxnLV`p+L(?p|<*-24v!1=;nlJ3A9C9`yVP052O{R1HX za*Pxw5u)sVQTs|;nca8vic90n;W8YD51lIOA571EsvkOq2$wn2}1gZ;8=6uj^IPfOuR|U8B|P4lxW$ZTHqx z_E4Jq%>li#kezCH&}=M<)3UGA*x}XG+^bu4WbB$pg*LgH0B=ugv6MJe!#xyR>z2Cl z;g&t`tIfr2RZkZ+p=*#aVA*jcA!UJ}AC^h|Z9sR_2D#C){=tYb{?DJ}Zkc+(!7E_z z4`ofpACAfP(MFZ+Q;y~;==+I-8fpew$SbrwCmODmFn+#4nxc`HAVN>i}YWGAe5P32)D5{I&dnp!^*t~u|QD7|X17JXM@NMsx zOTptYT9S?L_abxzQhFkKwyn3ct}~Rf%9da!u?G2v;<>96r^=^Bnas#l;r>PaPc|tr z1Zo@WzeRyYk>AZFV8OsHP!nUJ@DnflVG_rb5r8*O4Q=dCPJT2+Y3MI5iKK52Of+RY**= z0>tqdVkda>cPt3mmhq|gBKAU%2wz;xX=VSS#Cy$R72g!o4Y0+kJ7*21f0_KTPZr#kXgp|H8>yg%f(jI2)ygXEX6rpA5dK)#DG4jll^?v_wP;{iN zf(O?j&!q~ERRhVWT!Ma;awq{LASJz}jQUFLx#OduJ+H@SXMX*sn?twZ>x7=)?6q=+ zk%?`&c}ClApzmtEA;nOr%t%gw^E#o8McidaXteie;|S|zarLBgSbOlMtD&*!!h2d4 z)BNu2Or6EiyV50&eS_$~tsTEuAXgn34!Xg#(h_9CtG|uiNfp%F==hosOrox2GkNEn zJf8#%Y6Wt-3hbtIR^f$6)>;+G%%|P^D=&IP74-(p<$iO;?=IM@e9nm7@JftjTCOn9 zdG9S^i!-r`5$kwDl(w+tIdY*^p{%GCe2OX;+`WJLZbDPv}yP=*Y4Y zc5C5A$j^8Pwa8n|LZm+q;1n$0gUHc}xW_`8TDpl={QCv>q$x!O{|YT?4u6!N*;IPS zQm}I8M{MqPDSuAi9e+SruHAEJEbg@e^6%N3g5?*ke_AET5{Fl_kPved!z;##518Kz z*9oy(JC?}5mu_I+RsW?cl3$hJWJ>Nks05aFS_5Q8yoc%Ce$o+j17pe$wEba9g~$B< zobNO%tGPEBvA^L$#NZb*29%K;cn*zBFA7F#gQ^(IA-(SwK7JDGPI11E#(!PjY^3C3 zqDEA9rlni30Bzo*;zKZyW)0r_WCL-}`q$Y1a0oAL5LhV^WYS>Mhfn*I9 zzL?v0j8BeQMG6VRwrP`Ibp{N7Z;H5R9aYVUvSH+T^R|<< zqWPlToIaV27HE_>1fl1DN8Oq5lirB5(a&6O1bcH>$a!)oK1$X<@jlb?F&cXhMce&L ze134+@$8PqG`(D_;E)z3zrhxhqVdEjUM}f{zoS9U9wSSSo-NJk4!=4#Z!adYM!N(_ z!1hP0)~~itcpcGu{U)FQr@G}G8NI&7s3UkeeqO3E38>#k*p*?<=lXJD$>?A_SQ34Z z`s`M~sWJG2u4?0}^c$9zYM$g5#dX&21T0VtYq^0q!g1ehaEEsAstENsLKCB2b-B(; zS+d|#o#)bYa(m7yDlXvZ-BO)7l1Fuj6l>7$BCjp0kjcGzB{wlc5IL^H0Oi>p9eIvGF_7azmN?i_3&C_^o*%xpx7X-tW0 zOeXU=nf$jmP%p~gR_IcTZoTr=ITwFWOmDJ`?OZ#~Ojalq@)QrL5|_2WXproI9!0y= zGwZkD)Xbv)en46Z_w#{XI3NTQt?396rZt2q{xrNO;-yn4)%RLM+u+2Z zTpKXMe`QJ?oni-#7MFh+NH!?`)|7ihCupq22sdqDM7tOD-l@~AAPKA&vwM03Qs1$Q zEDd{lgV%1mLUblfA?JDK^frO(AsD6UQz>P0K8WXw(N;a)y|Dk1-jNPvxxNbxa7+kl z0_Ts*EY`){e(;O$CBSlwzZ?YPx-9{#-kCsXfw8InYTSqW)}|C-A73KAQw?srGezqs z7sx&GGz->rYa`;6cm;TX=pm|{J97I1Vk7E&z&*c}mdzhnOLPlJCS)VXKo<2y+n5#d zPQruQvAY>X1zL^p)p4k?o3WIkY02#NIu*FjahQA|*2jGJkBCnUnNd~>udx;Ti@5*A zbh@|;335UsSXE9sh8^Xgz2?`!lo$ehZHLw6)*A1%*VP!iGyoyf!=|J0v<&B}%CTON zVzVs^p&c7~(D|%3foc~w;bP)Q zlb%6?Wu-?UF#W9;ne<5Cv>(}yYOa_nH*bl?&c&r(frrEU3l&N0tv9Vre zswVgo&TeKR12lYfpSN_%zWq-flr_LJLtBIzqGZ@`??VA%V{%={TX^ZsCz7@vooA## zH#R!u-H_FYQtHRvS@$lPRi}oIAvbZtzo2{R8i{5HVw{JE+$(+N!lW7LMh$0YiR>8@ky{3&RnUnyD|Ed`ohz3vgb!#rOzR(rFfSJthCC+vNbbba0>MU`cnQxZZfT* zxoP(>r6H9TusX&5X;27LqjQfUR!QCL>xcQo-x)#4^fN*tW9!q+neU^UtMjQ`f`|e$ z>zXMCXqZ-3$dp+|Z*8JIOBtsZn!Z@YlMOHBoF1c<9XS|=+Spx%K5;3S(}StYK$Or? z6zN%BLByP7w`&r_*)J*;7V<1<5n#ZZ*le(|osmCRhUjuWscmT^q3 z1ijd}Cz_t|foS)AJ2>i4k@Y*wXj_thd8SeTzWlGJ?f2J{MbB2wBeEcs3S_E>h`!4F`Q6DI2kJ3)kXI+8-0_Qur`#VoC_4aoL1mieG%95Hu1NhLf%Pd}NlxrXqadIue4| za}ANJ=1~VR$1ZxbzU+}sx3ZU@h*)Hrc3)Q)G;-YhzBs(w;>&yfssjF&7dvsC7WZCE{9c%LT!_F~H_T#ca4 z?XO(y?^Z3JTiS(STzGrrT|4^rtQYz;7I&uc31M7&i|i*9dxXirW!;VTRxoP3%OVkK zfQ&xDWM|8uT15Mfo$Rzp&00{Eh|Yca1n`{X`Ge zUQm*M_jp$L;chWa2+;%ToUPgiZ^uKt&@ensvI9&MCDsjGbB}ipq2g_!;x>-XE{?Pb z(~0?By$Jd5jhqz3v%6h7R=agdvfPyjTtzCIKa=6yNu$E=i3w-_{l9uYZ{MV!|MLBP zsp;xZ-RRRDq*)!TrtmP}$!_Q(PBz<_Xc7-MAe;?FFVc@%>4w|GzqKo)Aq-XdE!EHp z&r|?B9D|6A2alhVm)1qvxs!JjCc3>Q64aH??2t-qyY%2SJZrY$ViN8_prx(pyv{s4 zp)-6s%gE_tQ)AaA#53XVWHH8C&zi}Oilw`RHQ=C@ z+I8Tssghz=G$A&kW6}fq)6Zq2aW{JiBw8=<&hMVja)b-tK@E$XO-3Wx^d$KtmFq(v z^d!lf>eqN(46*=9Bf*Uu6oOyQ;E7)Wgf-kbdy{8CD?^GX`mS!fSN$lYU-egS=>zK* zzR+Cl7ijQ3%BNLC9{1F_g>?0oj`xCTAGwUw@Z;p_35|fz+5vPHtt2?!6kYDdLA4j( zU-pMIsk-Te?37eR*esO_MFr>rZmPcIlNb(79K}G!rl0OB&R&eP8cyK>u0@NApZwSdX46X=la*`_-1foeY{+!eNQPnb=*jA8Ll`CY}^lOcB(=+rSgk!01Fd!;T zo(EzKa{UF%dFyK&$3C>kDTdPWn*@^B6Oij25mQBs!?U|C2u9&f^<~Ulu-&3Olh7hk220B0S8}pbS2&P{<&$)I@}@Q_v0S91m8Ae zR1geH1*SomX{_T5cCrjb*HE3%xfkK@b6{SZG>#d<=1r;4t>12xmO?kTe2_F4Cx~N8 z@WmWQC;GdxyPhDrOg4^tQijH^OIOPs)mNw0lyR>8?aIMt^zSaLps-L(e9}5d8rYje zSC_Hr(r&uTC;NEQ-ffN70cq(E3_+#GhVdVBy)zL*L?ezXEs3M*l75FhG+w=SjllX} z%xvXHo!lCU^htiI*D(%WR|r|P7C{jQ+mX*FsmXp90a#8d4+`gk=`Z{79fQf?!3g44 zx=YT%-)tL6x)WmG47Y$_sy1n&*JrhT{-B?yvk7*XC7Wmq=ELJ)<7KUz=EVSt2x|jd z<)7$Df)tkKId5xZ6bSQv4n_AGWFSnCEgLQfbHhf?n?NZ-_0E%`;mi%@;VT{bf%;G8 zQih0=hUa7%ZMA%ZtQnRh{eKd?kEPFD_UJ39stuK;{11o#Lu3RazoVoFb+HvN=v4%n zm{RRGIU(`FvC+7nYFf@AewN8HHshw5eGfLJ38)wL=SVY>{Fv4 z#=X=lM*Ie5`toI@hPQ{x{;kRV*gbZ11g8w0C_*>G*qhC{9_L=hSWXe!adhnsOqaig zP9jS#JeP2E9Lg(gi?TCT2}FNJyH?_sU4M4A-$~dREld% z9}~loe0zL1LgXz7Z$pyjJ0Ks3Gs9F@3+p>}to6#znF%9=I(?zTm02=Jbo_EmuzWEv zDNqlaswzX`*slY|@rF=JSiHRop0TR6sWO)#q|muHG{fL7dg1=$Nj<2Udlupu)SvA+`Hq%VukT#~VFhQY?mm}_5}f{pu)t?^psHO*KF5?oaveJtioX$Hq%+Yyhk zQWcmeW<|ozZz#t+WIgs<6(g{r(UQDjkWN(%_F?nDPH%=6$jdwLhLxtzL$qP@PrRi1 zO`FYiCftrHE#7ak1bp0s6@5|YI2PlFYrs)UAnrwBv5`D6eZ?7X$1orfn+m^@=a<|H z%XC40rxi+p8RtktFXKw>sd<@5R+-U7+ET>JYjX&t+O#fjoKT-}NeaBYJz~=j(s1$g zX?J;UJff=@E#wRooJfW+U2{@S4ZTJ$N-PXAx6P3`2 zUI~2BbYK`BPW&>ma02&G?CyhugI0r_JXBUwRgha@*O?sr>fJIY4rUf$w*xVN)74o# z5fv25x%WACBPbQzJrxxi*2bllE>*i9YT(f zXdt~>l_*_<&9@VEw|$rY<3qg6Eb-SMj}>#9O7zX&1Nf<2Y(LXZ5tMtK(1i%tI zz>}=EGqty|Z}fQrmww3lhQ{_3tT{LO#Th}jFlUHu!H&OgHwGCMF75Q-xBuMCteRG#FA{l_S?YI1HkEI$gS{$fMCm<|14XC^jyq$LAVD^vU(9xoDPVECpDr+Q z1TIV0s;}p0-i44mtT#1^hb?<;owPDto>mXGd_q%8h{Ee482;$3X(&dEeqpZ{@RA2nIYs0h+>i-%l~@?@i7A+ z1WKgs7_kuNNT+_l|L}Ud-9lV@LgfA29=Ld8L+F4g*ur~-r~9YN6BZC=_Z*l1;5+;J zGi-}c=#;eW%24QBaWv-(Mg|~~a#L?V2VXaW*O49&^YOCE4$Bq*)fzica7+9FW(TWl zPVa+C#XB+}|Dee6qj=qE83GBfrxXAHVr0Or2ff7g{vFHbG?MF8;oFWHFKF*XK^NUX zxyENJDV(pt^uXu)l^bD)`C_1rN6nrvny3*&|1t z#wm#_)M-DqUw{}9YdRsQ<@9V9v|tA$wuAAay;W%y14UN=JIAKdK_PJUx90+bI(j+T`0VP59jk?@@!3e@+~gL`F~#A{}WE%U||3Z zaaWMP7^HNxtL*7ad5xsZ*VdwuVIBk+jVfptVHVbzdzdKgj(dm$vuGTKobYs+?Ir-n zH}zBk1Ot>eV^{*AnBuQZku#(3Ygh{Vt}K2AL-y!~;d@ccWH%~khA4-O6F2D059$fs z7(*-OpAu+)qxW=~{c!&xA2UkcZc%kpQW|R9`lAafIoWkI)nHP}k2Fs;N7@2X=^%8L z8{m8k%XnjVskq#|1MFOUY}~DlZ36y{+c|ujXPpIjUA2Y%UV#CsGidIW@!I(yl}r^o zH)3NhdRs1O|4fFIoXi{o9wW*lhF;4_A#`UjW5`G9YLhv{2RKbrS>m$9gDFVjGE+|t zRAzJW^fZt%sSe9M+}4|-GsXc&nZ}G~w&J4iu+QdO9On3Tz)kq1vbR!M590klA!5+L@nI11y?WrbLF8#Xa3_=(`X)Bb;{a z{A$_JV30L9~kdJyyKja5b*FGqlju3#=*GlS~Y zA=-{c;Rw9fc~Sb#CO$u}1t+{NBe_h70cZ4w7n#_4gL-*S-lUB;&VK{88#QW{8_muT zFs6Lj6w4eOvYavH^ec6EaYylo^}plc$z`X5Cf~CEL5{p^OK^7DskDj8f408^XtoLc{;| zQX7DBRvx0op|}x+U%6=lmNHcmM_C&jbfvPt|MX6tT^UhoARDVm0-m}aUti64uQsRbx!v zu8s+{M7^dBx`$0-@Ub#Fz5nlxC%oskQM^LTPjl0qgHs5eebe+VczQTW)0h=^EUP6F zVCAKc!W5~$oNEU7GzltBVagF3^4X@@B1s?ARhG(&F|t^3z&h_lM(mlI7#kStJF?;1 zUR)aP!a0{|sXDVbaaJjHv)LzJNm~B&`fXn2{0w2q$a&oR0XG{4}Ukzj~QkIu9^xC8o_qbp^-q?2qB4Rb{W-uCwHFQRRwV@VYois}xGBlm*}7K?;<|NO`;PU`kBk|qlzC!%1& zUVUfeFVA)?omX#KK^iXx+Wed;0xqzNF#tUZYDNKub2tc>BrPhUP?|dEVf&I?Zed(% z&P~ASsNJ`Yk;l{Fr&FJKrF|tc%n?nMt=%grczxb~PCiJx>1I^HTrv`h#PYMEtNnGD z>*$1T{7oC_B>YwA0eJ=%4C`KJ6wM6rsj79)KlF*%QH$=NRgg+@2D}ngLNfibL0QK2 zLb(8lMd5W_k*Mt1+16rv!Gw=}*KFiBc&MJ+1F3iR-%?sHE;Pl=yTr0xkOMwD`#VU8 z?dzNDY`loPjxZ<}w^e>tF-QJCTwN$6h1)o@&%NID+&l>;D z7-u|5DAOymhHn=Voj+{%6Z7X!ALg*Q8!-UXOU4LjeRgqYI5}fx0?#Wlo$txU0Xbs4 zfUG@rYmM8x9XeRtzinZzt|W)+>b)&^gFOQ_MHbbCrfkyv#@w$EK+9DDEa5-CvPG>v z_1e*wQ>5pHa(WM+(Gk&hV(Gr#VgVk!b?h@(e$Al)_&7>zY%JMyXRGLv1k+YvbNG)+C*{x^%BwKx z)s84cW{`Ve%c_o@x6kMF-h4mF(1Y9oMvQCLx<7sL{G=Gw(JC?`fug04on${noVRf5{BN+RpUNg=@fU%oqnsYcp`* zF&!_m%<8&?45Iyp4o~$)!K%aXTq}ls6za$lE5LYKQ76Iu{{Tk*!t%HfeDf z6wE@EX_3giPUd+haLn{%J@r=)94_;McIgg@98>)?DZtFwhq9&=e}LuGb!)*BfGyRC zx<=X}LD_v+JTNx#gEZE`HkLd|FhyWo+d*E`dmS`Je2}3rRZfFoAdP|h z-zmxyGp_L|)xIz12jTJWLlDYu`<8wC@Gp2~Qezv1WsB%jOIQEB^zQVO=6#>Q@Z3^0 zKB}~ews1^vow%orB^K$cVxk%o0GQri0#iOx!rz#6&p>d5f4upaZO4dW-$U)t17Uh2!`<$H_T=jqbJnk&F5e#g%k|N?Bpe=uHu_UR+6(*b8Bjqtg%xjODmNa zT`!QaWux)NV1y>!ix+fBhy>EsOvyxBVSTyfBFpdd-^FM8)#!fOwpZrCfR;skt$h9I zT9o-s;z)k=I!!)Vvz*#rfbq}P48n0$K_7D+8dOWcTl1Ej$%V4vKi-Lx*(Dw&!X#a+c2-)U+&Agbd)~$fe13;1tsu;aJ(RZ` z;pt!%vWK-K_%{h+PZ#X}$N`;80L#Yk3OQHn03Y58@I5WkuBav5|1c-hkV*i8sG=71o-O-FblGZb65^zI7KVUF^ zK=RC37j;8jlk~Cgj7+;>p$9Z`r6m08y22#Oq)eyK=b5tJ z><404`Y2)GdvEwZSf3VQ{y)L}`ezu($aj=p^7kU0>i@vK0s>T0&JY41MKi(|^&8_? zC(wCo!;NCqF-QCW6G>$DY)eGLRo#45qQ|va7}l1x^^K@PuSDNrvlj6wI@MoqBJNW3 z8EG<_YlG%5kiUKt_=*q6@%~e#VN&pLfBdxFnemjhKQ*b_b(e=}2w8{!g|J(XM1Z(I z#d3Bd_ET~E=Uz4(wBjvbT35u&7RwQK_mU-dnAePL2OB%enIXh;Tr1KQp6rEzV0&u7 z_j$+H+l$ckFX1qhm%t1!;lWZ^zgOxp;{8nmQ||r?Xk*^-lH|ZM)(qkCE~>F#;<4iG z%_))q>agY7ubKMiWAlqa%+bWeey(2P1z{kpOqE>%u26ME2CwdWzg`TXF0w_d5=r0BKd%~_SZ`G zOoDQOOgWGFF6lKngx(*>y~J%^v6j8;J*)=nR&(FR?+KfcSgzBNP%0{)1eEqsu)#jB zbC|bEZ$$AJs_458S#{NzNIt;|gy@K&({5=}oUsKf&VU9?;b~B=E=%PlD7%iRsameD znf2gzp{X_ufXFRz=>U{w&X>VZI99X{2`lJF$fVq=){?;aEm?K?Zn=!)&(TgE|F~M4 z_btLyl;bZ)B}<`_Lt-<#Lr<9K+Cg|vo#A1h9l}!Kkh7|`XTnH&z*7NlNDd3j%e6tQ zqtm&0;#mQUcH>Eq#{7yAmF288ga>Yp-AWA?mte$nO8KR16Si2|;=Jmbbi~MSfIH$M z=)YqTsP(9=sR@KCjA`l&#}nr)a8VbkupczOMVYA)H59*ygn}?SI6_ZIW!L zJsTx2|IijO850Q+iXQwQXcwZ*!Dy#m~#Ww7J z{nBSS2x^reAGA5JZx|qM)#%6!V(XT#_=wE(X1ryp+A-Jr{i)~dRhHcPfIU^s1T8&M zVg&)<MO|G?!7g#p1%i5Pby%1?RIpd?jL_Y}ux52l zJ~YWVDs-^@-l61>knU5|mh)C)EIK7&(;WcJq`%$M0O8+ZE#4EcBnVYg;>SV(KaU>^Dk|0zjZ$SdpEc*JO4RSPX*{lFEY|E3lL10E?r~DvM=#5XRE7ye@JzC zalu`kpVK|M=9gPb>x5DA)+rsHU4mG1#J>5qViq){(u^hc^ zMpfPzBUw;b)|FPb0;tCB;h=T*NWVRJTLFlhdl`m|558JsHHGAU4o@G^WzGP?^OJJ` z^T)Wg5G+A&uvk}Q8IK+5YkZi2xLaD7fv8(+Sa;aT0D%wx96x~%DamHOHU2IEy~Wu& z8zb?S{|V(7NMVPvB5l4o$ovWDnZ$mAxH&im5+42U?&#UB&3IHS73tJAz}2+v93{84cq6 z)B6Il2S9kfeh}jgLTtuio~)~qxPTODnt+dpksUi_PYYFX1te-Yn=H-|@~^SoRhysc z;ZI$n<%5t~P)5Ss}W6uJG7 zFKS4nIL9kSS7!m_a#iH!yV~8YLtJ2!YhIr#k{#EleLm@j@bv;*p|%w8&D}^drRy^M ztUZ=mRN#O0;!t(O6j6vE+m*D(_!*-X_E$AKl+>Unl+?&Pm74@9Ib^030DNY0GS`Gz zaS2=QEdlmZ{1?tl7hF`r14XXg3*3YU_swCYd||;?yVP>L%wq|2!rhZa)gQf|LXw4{ zHLp9xnO=e-^^*W&ZgL{hs|Lk(XpF$vBoWyVGFK7^60)q)MwSeFB_&XYA6&Pmu%pg9 z`AGr0ULr6`DNCy%#a8g6#1&+@>FTauK(C-XcZG@*T}6OaulAjPs?4i$-@cZ- z_9~Dv;wzal_Ogcl|2?tvojftDB(c>Y&-vlYRk&Sf&BCcRs9Q&$`3v?EV0xXLx(@Pq zxsPH^Q%hS%C#jD>^Aj+SbC zMn;~2x<#H*Ms7@cNq&0lfQDv@c5G6<8REYO!XHUq#^nD&qBfQq2ZH{GLtxi?m`Uz? zTs($J+A0+TXySfPiwZ2pM(HjQMd$_S@rxlvgRsTT(sRiwxbT?r5Z1OAWZ3<)W)#zM zOz+Tt^(Q0kPB?<=Y?9T0b5$jkxc_W~*$JsaVVr}sf0wDX zpsVh?MNzN5Wez!go6--(*3@Ls*_ErTBHa2K`#+SPd46(96B}Ai4G*B*7d7$AOrY_I4fr5 zqO@yr5?jkO5$?sQ(Yb}?F6_aPy)0@)rDt=17M1c!+nCI9om5!rRoW~8`&^bSV;WHi zWxHS~QjXwyAF+M$5u&Aa^&`w!&zh$=Oj; zL(Qs#JHYGG@9~twN1^WN4f4Ro0Rv&NFelna8?N~4tihlwg$L7svy1z;1ICgsPOUPa zsz<@#pv9~+LK;}V;9=ewgN@yoj(i&v?U{giTOCbF6vO>l^s6u&1yC5dnxs73{ZoDz zBsa2bv`i$;IA6l^y(RiuNFEv+!w%aW@9xkS2&;cP9&Qp?v)X=y68eFY@hIadRXpX= zRdMF=HqJ8HX_Gz67sGd_LAgF-#ytRd9`j0hLO%z`V88GyVjLhXT4GmCBmF`ZQxs$> zdab{lv-NFT&m)sZ@Ud^(PrO5lc5Cs{X!M$hadX9jY+g<;YF{p%WfllFV3<-H{|j8N z+j_bX^>IC8nER-)ZS5%go=)o9N081^BH{90+*Nw8Z*88q<$+Z^J&R^>VTpjT2ft$= zN!N2foxhMC=of0A*UG{xhBEYeIVZB#GsFcqzF&Hwd#^c=34Xh^<_E(*4AD{=2O;!r4ZH{AV``ZO{Puk8ad-xd1W%@#6<4LJ~+Y zdXiHdY?6X6BES>%yDL$^XRu+fqgXAtV8RqZ+b`+}=?GJ`+AvDl(u#*zvy=oc$fe7* zg-1S}Gwuv=9u7e{L066IFy#5&SU!s`UdxpvNmC>+5c*i;O?*CjK7Kx0f4;x1{Qc4S z>)K>B5CYqA2&rF$w`Jdi7sFXv%Q0%#1@C%C22Zmf5@0MX!4S*GhJ8IwH8`vMPX{BF zp~_ad6LWtBDJg|2(qsfpR2pt2w3Qs#0H-S<9%Pqlw?&sq?xtX%>R7fGS&h48)VtcuntN&a4u!BwoKVkC{Qi%;sTK>xjaycoD z6hx4?!oB^mblF|*_Vyr!*Xv6)pwB`3k7Jh^X{tsIR;RY1(UX}t=UwLaeyv$;KJtaS z8la~ETcyLXba!LI6iy{s6xr)wpbd6Pw95kw3o1LGPzv(oH^w@W2Y{}tfZ6p{Z!e=c zmZ!l@d5XE4J(Gz}TbeT`e*XZj z01vGO0p%QASS!v|nwo|!-luSp=&agD54cdTlY|2^Icy1fa+Vy1f)N-@4vKTq6wx$g zHuJ06LG>G-U&^Qa$1;>;M+^n=R%h79?N>q+jF#k6{+O$;;RI=kj#uWexUJye7wZgR zxFfs!mJ(EZ8x!OxezG+qqlSN*QEaO-?J>yIBeAiT&grhf$LD$bZkXI z1Xrzvgkpg~L1w2I^Oa^A!nVrnhxCqv&j}x_7J>wU+l@ne1P?!RoA-?HsS-{^+yt>4 z)`+wsDq^tRnFmk{GHu*^rwF<01bnc4u}u45t{|Ai-xE&R);w;q4k2BjR! z8<8hQ=`$B>f6xW{`@jvj46evGgKC|NC7#^_d|Y51%E4ro3or{!V*=$`1}NZ>+z&LN z2UOBZcD{AVol_}Sw2r$_OxqzX5^zB^D4-1O2~b+0n+4|lDYdTFrcn2E_izrx% zQ4n}NMRHGoxhe1}@h_PYXs%Vu#Z+pYKD7~e_IHjehj34#JD2cxVc#|j5gXv9VEo#pZsjzSTqvc_(jmc56@{FQP zJt%#wEC@)oVOvwQAz@L?rFpay4Gi2FU3tW6n$6(h4T(4vl%qU^_b>xIH7I1WwT3xup3aH9$G%bBlTY*n=Ui;RsE?b=Y^D z728L@lgCl(e<_*XvWS_Ukk1xpW^GWaLzichNYGmJR=1K1Tc7xt8^x{T$g}+ZKmP+3L-V+jZ+Lt1eW;S= z+{ltl&FcSS$G?iev&jec9gg;WsRi%<(QG5r z1{$nli1m`_C^4w$NTq;((VJJpny1-e-lF^c_zQ*#PZM#Q7ZJB7igkQ}L5I;18vlGe znVrG?HzOk_gI^E;_<$q|G>5K^&$5n?wF;(7up13C-b7_4*%MfamPTS`*b5AYh8B>M ziNBE=1ehXI10~LzHDHFYzs(KW@vtQg25N_X%1Na$)%4Aa*6*!N^FAk6R0Yx_|T$J1;=zlO%31I zS)7oRV6WqEw?`&p7Wc_EQk@MQZOvRQCU7v|N2W zP!qRWYp7ao^|VVQ$z}Rwd@mx<>FWjkhbyGjxtr{nWe}<27%w=P)nl@g=l5+Sw8k3T z9pK@4E>JcAe3oIaoRBpgo%wi#FPHhD%{S>IIH2`IC>FL#y`!q-!x2X>DWC+Ke|-7oL1$s~l6 z6?U%1zk&B8=**7=7syGUjU(}v{zHb{}WgXfRG zHe@m+fD5Iy2G0W-C@8ZiD@$y*dO8uiH4n-QJ+}h|nASO22d66pXHW=y$)BFP&`!yp z4N=-KF?nd0>1%(}abJu%R6!UB0@b6ih`20Vjd^XR#gUpDaT=K+okLI1%=1$W^tQ;_ zr5{o?MF^F_Gf%`ofA1((gC`a}A^ZRQl#(?Xr!@++TBrT^pMlfs?R>o`38YXPfb92k zObpcw*&to7g{NYx`ZV%8Li5kF2ug|=s^BleaW4l=NpoG8VYXBL<4sqc{8 z5ljeK7Dr9aM#{7zjZA;22}owao}R9%tj0VOU*7hQ=i4nsPY0Y!JYSm39I1>o*TCEG z8}9vKP7n@DZdhhF|Q$I6Qac;?Ztl4)+z^tsO0wdnqB>9q9QAf7N9t9B}#XrgGi8cI? z?d{sX9MS>9=(aV_s`5v*aH+gY7=(;C(nIc$OjQK?>HA|t`RK`A+%GgN(fF3o!7W!; zKIrEK^tz^PQW^dR>ire^Z!TX+o6yw56u|GMQ#M5!RqNN63i14WPLjd_!dWJ0{gKB}*dwzqX z>6)cOQYDGN?sV(XN5W)&aTP?gHA}No(o1A(m>BFFe4)7*MyZRWiu}Co52@Ml;}heo z*;Nb|GhBxb(l}KiB5Atc$81266VRA>S!qAJdX@OJ8}X2WCM+0$_B41jayBA%oHc~F zUITl(bjo2OXQfZm-_YymKHi8Rr;Vn}*drp{gkXTU3dZpr8nJO?d*fxDcE zNyxy`nlCL`Pza1D&5CX|+%NMp5Yi(5AE099GPcza? ztasc-yiXyJ1YnMKkL`>`;^2b8YsH4Vync{yi!~;3)LBwnQfal-sZd!^wYBJ~!P)TM znsunu5N&h`F<6G*>YjA+U&sBV=x28H+;L&ef}785uV&6h0>)T$RcU)Jy2Q{GbZRTx zW>pkNc~4M5cfjqcUlv$fueenjV`d$uDncHX7+Wpt0Oal2*n;T26Qdv9#3a5Z1ml|Ld?Y7vsx{a`$M;z#Mn#NX^-98guyD}@vCD_%Q=(oy_I_O!q7ytO7 zLiO0Fhq~#1o@`_wB+_Z9{m9vxh6~L)Gp0& zyXVhB1<32L-NVfVJTi}pH(IMx$%`SxdKg=TZo()S%k@!hAGZy}^Cd=`-0MSRJtywd zLXg`ri*=HzIUzn_v*adR;l#n;m(P)6E8;g5?a)zxS2|+tK|yKNS4?$StZL?|H!YV6 zZn$7u7mGJYw1sE6CX|m2FVcxRF$%&SO6m+90iHDiBOAiCjN4AUi~fNju&w(FKNr6` z?OvV<3x;gQ(<-XVZYZAQhrawabn4LDKJ~HMYa;^w>yA|FNt4l_MX#OlZsy+Z6#^M)!e z1vE-LRa)Q3Q>gV(v!Bz9C7$-(Z|}-9SGu>27$9HgwNecb^gvz%dcVjW_NWYy3!v1~ zw~gtr&<=AX0-nX1OM6zJ*!~E+3jUL!`-JtY_cDR{%(J>02wNn;w6y~PvqJ{)ARtVz zPhS2R=X?imDYleq2S>QCH*x+KtN+KpbpS(=3SXZGQyuafb~h%LTqpR`E+U+HG4rWn zk^X%>A@X{tUgQEB5^3k1ALc;utn(?lLh}3A9xS*g)7=|`2zfmzH$|63_fx0*6C2mu z6w(siur>m!9X7NFG`C0Sc2p(8hj^M+RyUAZ4%MDHvmgNx#EuvUj_;p+AZ>!70ze|u z?r?7dt(IDJm85SeUCwtJILcvS#+*kOU{*Y1wQSlsA(x2ay7r5Mjg5=q68)gD_Dswj zC>=v74p2dvIi%Zrpixkc+d&$1^@iVL&K{!g4=w-FyW0i%XDE9I_;1#rrvr=~O~^1{6TFg|j!b^LGN->Vl`^=PNF*AF zN=3J0V$9ljJ?%#MGx{enV<%b!)F3M$q-}a#14*7pifVlN;(0QId;hld`daWu**+B* z{t%qTVnRQ^`{qi0Z9h3aI=(tSJJ3y)hsBDSOy&?3Xtse518lBw0}S4ewJ~;@Znsh= zUUz^w`gY$$%2MINy%KdQO6XDF9hI&Edz`~fYUDC?o zs=kwBV(xCgx+njxk_yA&MxilZ(C1+c_;lioIE=XHDVDv$0kUA1#ps95;HK*SMCXlylEb=7tt`v$MFp?XMJ%39JXQpYIOSUXzh$g~<4-;82DTs6KSMqHIV;(o_=*4GQaDMs=X zV&gExPDmmws7It*9w1gB@daB{3b5wGO&JYTa~vUy8?~voY0+{g2AzDB-R1B&@do`v z{E6@=;)}V`pUaNpoKa!7i=lm>5diw%mFB3&-ShWbQ(TAqEui|pc>`@653r?m`u`ZH zuP%;@!$j88)t`;GE#JTXW7l7P_xQggq9K(a%pu`7K!1|b z5M%s8q){a}Af6WGM8rYd0Azd-LqiMtkez_g0g-=28|3m|glU7raJk)yUATkxBZ{AC0Rdl`v zHb)MrY~u2qE5M^!QJU-}dFXN@MW9%~+BV|VW2(X0QKA%M1)bMAaj!voqjJk#WN!c8 zc6*j~&Q`UyIXtFdJK!9|wRYKU$^nDRFeA%9Q+YJT&mq4Q%3{d^#IO>Xw28qqRjR=< z%f>;ag*+U^jy#!)@jI@?q1j&+vWm8kw7_Mrwsa36F2F%>kR$h4^h$ePHrzlf9 zsb~->(xRsGGB9q~EveZBvsRAQ{ZV%f)&#oLqOLEpkglCb0cJqsJ+I>4eMWLCB1@*rYOLci36e1$7-3 zSu@ETN9eZn0@&t7pVz5Ku%DT;Zsn z`MVxto3zRd>qWXs=1PYawN8Ww;KUh?Iu!bevBR9j021Km=6K>^(Vnx!yZV8L+{D+j zbWsiCQ+PZLo`7Vt;>MZlgynE&>ez8F!Vxk*qJ2@kv|D5Z87|^|Q$Lb@RRjrFNfu*U zwMy$tjWR>_CF=7pxIEcskzwiK9klN3UtPKaEZrunJ;U)K#(_#TCW*{J3!t;=p znI`Uv0Hn;EPz~N{TakPV9(DzLPEU6jwS(^I&Og5#3~^wojrd{ohiMy|5~?qgV1s#N zQ?HZ~t0C&|LMlcs9Y!>8*?&dMz>(0_uacc6W81(9pJCERgv{kRU@t0?Pw7m!d(90x z%~035!x))8u9Smn6^Z?>Fi&A;u+7(Pb{}t<2k`U2CMF@K%we4zO5_)JZ24>dn%VMa z;du)6A?q@sv!`6sV_^qzi8X0i^L2-$tz`L|13ND)uTQ=obiUHbpy+QNbklZ4I9a5k z;YN!gC_iev^)gvqH7-YkpiRf|_!&QzrYldn_D6i5EQi0(taKcdl@dv6P|Y{G`@wmF z5rFZ4ww{GtNGNFh>Z~44#L1Hh(Z0fMXyZAZ#*=$r>>yQ}cy65=ram;ZDS|)7cU9Kp zidy|hoJS=j-{$kv+n71%{RaEFLqdruq~B=@smSRP>3vt_FOo%wYy=M1p_N^MGcuXa zGoFypg=7R*IK&=O4N90YLu|ed-Vn~7HUJ2^9H&tQk&XS9b3D0v?`JvO{g#dGYbdn6 z6{Nc$AcFuPNr2z4S#{ zlhD7IWFVEtA0?O-jgVMpi~=x&eP6~RN-S@0hcE}-QHXDgO%*)Qy^p|q^!Z5TW0jTI z^honc{-LqtJj9K?E!-s}Cz+svj1hhH2_Y1kWQQ@>6l*JI^_?$h?da&QUPbB)BUTve zoyrm1;LGOtDbs*zn#c80<)GrT1AezReGvM>4&LKKh%j{4c>fmL zdcKoq5z&v5sKAlY}Q6*9B?2O~DjuMl{1 zVX%3eeE$&}3Z-riXgtB*AryYbt7fc&L}P*C&gZIK?!Z-%M*8N86BG{JWejC0m=+6fjB>6It+_4 z(}<~06LWbo^9sWecJ6tY^VQmqI3jisGvJ3{^6h5JBz!7dD#ayt>+$=v>H7ciZc6j@vNC6#Ns4j&cj zQ^>D2^F)fS9enXI4Zz=9euJj=GRzfzX$RVNc_3Aqd&=MXG`Qf{6CpbfVYk4?m5*f7 zWjtprnkDAHP+Kn7_$91D>&W&LabhtxGe;bIZBsvhoc{1#t%_rY(W7D9?zGHuIfJ3X zhMpdWEibDoQ7j&l78?HsdXeVOTC9Xdu))luakcvK!P1=8dI2mHdqm470N+6-*Gvr7 z$-M4BxTLO)J|_R5UGNwMt*c#x)6ZT{JJryPiCiCJw;uFA@Ty*L83xm%vru%<%`&7m zIAqr0WzchDOxB80QM0TmmQdjbu!6{2l$J0%Qxgr zO2RZ~INi2Bq*Ah+qMu`$OvpjkKxhi|beCwt?|h#L=CvRSU2Y2}da)FLelg|P+OJkc z&8rJol#9wZR?vYTX^`^9G$DLs6IQczV09m)V{Gd*c4CgJ?mf3M9f8(8g;m!XzcT}+ z2d%isv6%m%(i)?kVQTcN&r_a8xa|@CH?#|WMJmtuuH=euc=!LH9ZeF>3xUft`Ek1}Or8R319CJis1!1D}2BP!k2MUB3 zxxlYDkx6-ZsT88L$h2t7qe<>0Ue`-P!5)98y6`{HWX$Elk_rOy)(@`o18jFVFidKb zR!YpJCI+IQurwIz$ykZ*txJGCh2M7E6rwE`k>5F)UIQFa?i(}$d;P4qSpX(mIOea6 z!$SOI%IyVsWebd!anTuT%O@}`MRBZ}ABQw#t=m30jDlNe}B zXSlu3=skC&(5Q7AddRi{qli_g$7Vj@FO3s%e$h7V7<7FVT1@w!J>Ql&k-0NNWy__Hnrnv-132b{;j zyNKO=JSCWDH1VWL59d|MU_u|QLMVKJoh-zKW(&iU0_lC-L;#b?E7DiyGKeLWT=Rl@ z=^`xzQ?v=CSewyYC>})>Qju&-CIY6~L`G$1(<9d8C;e`$1D!)(FBAP-EQURlLu>|9 zlAW~yB`9?k0b&_7QL{D8!EF-PAMTnyETTChe~I0H4La=D5O!o{ni;upQ?7-oQ4KqnCCl5L-xCB%OH&v3FhECcBKuHfpV zDK`ng)$*J&2UhL4pRn^dOf-uSQsmERt5iB87SX*CmP~KymBbd(PdLC&!*@^#lmW}H z808+E8GYPrI~BQ>ZPyv^Y1ip*{`T>_cE<1r+O3E%4lB&-&~L;>mLoK&bj{HgB2(qz z#Gs;8%6d9e@!q^qt(1BSQOgtUV~!_ItUYgldzvr}_Z!84Q0T^yM`OKZhhsE<6q_h| zsfE@b;KY!Cn#?Ef6|=7+}7$tq*oM|9;`j_N~A&FUVy zZ`@=RI-~%|7a!V-Kd2vl+~_&Nb;^0EJ#ebs+T+siA((9CcP zjgnMroYC>wFh8({M2)XNbDYOQrloX1EV7*ASL6-GD`_PZ-0+ zs8l1EbFavhd)HVNf=ojJErkpalg4VqTm6?B6ccTti8p?~{-hKArRG`XPb`|mF!vOk zbO@yzjCy#OPWgUc~t zy>m9%YBy}zdtm;K+e3ZELA=?PLCe$$i>~ ziNwKH6@?^6o-R^eW`dO+%7#QIH>T;IEOl1Q)>pa}8WIJ9BjUiVrQm-?=rTOv0G55w zxC~4a3T7O|W3Lk$54;qbCYkh4_*OEg9hk@}1GX%%^ql#8-CNtup{}1(ZKD(dV*cRr zIf>y>Ce5{=vYgm982^C_t>vFVs9-=8&GM*57qrrf`L&|IQPCc&{x3`ZYDqk*mG9>z z5dcRKlm(vG=QM;q4WNA}f5xgu1@J)4jD2sZ-9rY$+SZe@bQD16hCRH`Wu0{5a*$mj*f({X?!wjB9%VE18IzO@1i|~ ziXWwAg2ik2I#jd2d?_@dN_XBC0S&3K>u|bm%$Uf_1rU+pHPnoOtlgCPcC?sJV8v5lad(i1w%#M9g!I zO+->JWG1!~`?wCE*{dYyyU+58^wZ%JSx{hLJ=fjL)UbR87QwOOIUG1@k zo$%vxtp<8@y0OMF%EIp(d^7w_O?V=2z}x+pKvrB| z%IsG$`VtuepFa+h!4aiMPfb?nzSQ?fuikY5FxfW2@WdRL!7EY(&|x;I7P0vkd7=Ap zAz7ECl&nh3*fT;y$=QK74y17*3B&lCmqrqMj~%H3797;FwCSlWbibUv$zisx{Plu? zx=sC3U;pD@Z%>uv4frlx_3y&{{}G4M7)Fx46*RzOBeXa)QVE@&M8k@@0S!q+CcG#@ zI!Qu~iOdIgya-O)W9%yRxwdyK3(EHvG=gHd5s-X4)l#U^G(0f<#{Ad!I*Zfs@w_!I z4&tXUIaloq{~B3eW35niiy~4KW1S$n*l-@bd9a>57Zl0O5vltTPfL&QAgvd=hT-Y-JB;!s8#WXBCu!V(g;$yW#WM8bJMVJ~Y@w zp5jKk@iUYSFi+5@mupp0z^0lg26!X1+EBLf>&W*jCE#)6poJ>-J?;rE$;?%0J^h|R zmv^s^^yHJb3BH(nrv+K+rR( zc)Fl&q-j+=dRfmuJL6y>{n;8PNJH-IeYFhrt%_{O^C?Ar>!DLqPPpVlE}BXFZpx#V zul=2wD^@;%VOG_2(9vf^0*@TWI@2r{(UUYkYMJ9Ya(Jz`7ox?vFZ$}gY)X+(-}*5i zP)l+wbSQFg^C+@r{s{`B=;=ffZ_i107@D6^3P|D55U;fKL|0nD`39aiCDo_u6tXH> zdjHp}cW%sX`7RcRi|NqxqKN->(7_aC*Q``sIpGqKISCao0HX>>jI&aHbK?y z{3zC6!`sETEnY5J3Z%XnT_xMlo|URW8J(X0MZY$eT=m;4Zdu-zod)Gb2*y(& zjV%(r=ol6*xAYAXlxENj9ZzQi=Up=fQSA-g-13QPqP*b&%bej6Zko)2`jPy{T4%av zNjuK{M{M=28TmTa`3f^TQv%>PDRzdVuqntk-|TUs-OuSAS>0c2acM|IUtm>ZJ{3cY zHixbf&~`UhwPrh~lih-MvkNZ#F|&ia9@x;1W~x0#3jUeVh_}L4CvV?*dWHvlUT79P zr+TauW&{sk(2RJsv=+-wDObyH8pJ{EeOQn!@#Oi^#u~8@wVP$DVi>a}y)gBQ?6(9c z#&8Bde(61Sh3Iv7ci(e=mzzp0&rNgMSzEcZgrIMv8_=bq6X}KJyysRhL(Qe4u zDQfAeTdWw=Ir18Llrm0yD)KK%GvGtZ25AYD;U;iawLy31rQlb2%I<|29hQgn&tPDu zGAMH+_DMKc;|nfR>4b4K12Ai^J3jo;s3IZT)a=%h^>QMEPHzOnd7Qcj*&>A@B*1#e z1ZI7w!_Bf(1;%y*EhJO2B{&~5ey@^{xO-|02oR^u4^n3usAI1#91V#JGM9yYzx912 z&LNi>zXG(U2yzPIj+RuMvp3tfA?$uE3@zcopQdtn#1mIsNoXY(i!KAR5!{M}u942WWFu03G3jQ`4a!!yl@v5_A;H|T6clG$vE?qRv4_;Cf)oow9-{XKM zrfwT|epD60WiqT~+P=dSB@$YSF1&93|1J2h_usa&71m9qBcf(thZ3%t3BRHG7lvERKn^5)pA@zB$N$~ff zPWyLO97>?*`*^RTj3M1L7(4y|ur(nOfr4-KqH&StLkpgCF@Co|^$ii+{P^8(3lnQl=51R!cP#IR z$L1xY;YFKZI?(f`&M{oFf&0XR)5F95Exr~SLh~tcHXr%lW@o9W?Nr(i7f6f!STYo2 zkND|N9_}s19`z;go{81MvQ)4NH=(~ayBbrf0;yw$wzzfK@$jdK)>Q{g5BQSiVF4V& z6nfh-!@aysos|r{WSMaQ&D(3m!*I!|#+z^s)wb$zcC4dGR()3~!VX>nJEqa_bgKA! z5>=2omU_y=w6LmFr0(5oaFDX;SY5{4EYsFkqVIGmy-`bVs)1FczejhL-hbw|ziqSO zP($O=k;p6n8zUXJa%KRBFY`&w8`*LDPtm)W#SP%Tjr)la$9)Qd-c8FHYY?7K#^(D- z?kc&>wIt(M!Ej7=QtUY%e%4l$)i@D;rqbpnvzQT)*8=&_7hWhi6yChALaAgav2G=s z?&?r%$hm~9Vg;TSQGlTm{zUS49ikfeVZ_FN{Ke7MA`jQ}PD!hSEQhW-nVvd%Fme2R ztjWtGVwZibd&T@#&`2UZHCykF@BkI=p+Ycign8=N<|gYq(_Q#dXu2vtIo!1=gg*E< z0AHvTGnaUTq!Kx~f9amTASldoUrq(@3`Kx}xtNy>{g~M0DJ?pfASJa<$kcbGMU2Ys{*ZR_&(-ehw$)Vs8 z1INc7bT02Z=e&*zk)qnOT$t%Ya9p3y<~)>tu_vcPOF#OL$q zc75wiZSY&a@pjj}Vm;Hys2b;#TW8(BUOI<{(kqSTq&|rGWm{AIQE$r3f6)j{X&xjp z$Xobx>v8`H;nv#o#-7mQ@^%=Xn)1lf1Wf+9MVvv?OJeBVU(r?{zu^#_b~Z=Cwy4;N z|qoV;5bzYO3p0^^B%1KS^P`K zgeogJHTDSzUf&X3m6J4ULq8T1l2a%kBsZqyy13d}FVJt4#Y_=S99s62HXDg(ERq>a z7Ui8}J1hWAT!{9t4N62NdO5f}PaM-ZMDh0M&=xZrf(cF$nf|FV!nXG9(>@`*NTX~-Wo;3>%?(K8@h~&^$@5Dy6_TH&89hRyUR)67u>~+%BEzMdT zPHuNnOh**Xa5}-x>X2Q!E}2 z$31oC>v_xJ^DA=R8w_zZop1N|71FI=P2mbLq^pmoz~^Wz8S z&2`P7Le=!(Ni-}RR5 zuQ?A7gF%Z?SCMz;QHEz6qtk3#aXm+pX1j%T!?#ZJEm>ppZ5=$5MagF1r?rW8R`c^A zlZ0Zssv!-dk5GOOcDPNg)cSn&R6>%OZ+#%!vo|MSPkIMuyJ?!daE1PiIyGax2GZZr_9t0#jL}|bu>?GC`1XcpjiT*gqllY$55}$8)&qAv=RTf5 zQq<-C4~0eMxL}-AeU#D(f^VDA$W<|48buQ9aT&uOtkLcT`S51XP#xeH-a%()Y}Ahb zz_4~7s?Htg=Ik9%5=hV*tcqzVQt!r5;-x2Seg&~Kz6 zh^Y1*3JB+UqvXFBxfAa9^w8VnWuI_}AK$^TEd7^c!Tymu!g5^&qt?=FQf|(NXkAPn zYl{qVqk=0PaaAk@vmfJPVWs|{#_)L^S*3i72b#SMC(_fgeO}JfVceZ8A}0PoWmAbisc}aj)E%4LcHrk`+jA1)dE#`> zn_Ey;V+8{%1)Gku ziuLM4z1@&wx^hn#fJ$M=*5Ll^WtuLxn)^pSVo+n>s znvq7&&BM)hoqIh$MkdeE2zFZ<>11q#mx`U-wzB(F8!EBOlt+zv)~(h znHY9@=040BjiH%C!P%I%K^Hy5?3+#2vVOCDCXb}2^Yq}+S`3ocgP4=@KqCsHqByRZ zwpbf8tf+bc(!#3ln~W^{V7I`NRhqHrc_`X?ZLGgi+bSp9lx(npU~{=jtWkTnk&L9l zs(i@U7^(gW^xoG2aJD4heF+;z?*QpZ%026J!PM+?dz3E|ECEFcyBZ4WI{nWGwE28h z*oG}UDcUTn4NK>Zrc^AoGNfw#5-VdgYcjDZW?{CPacokmQVF_MIT7FTJJy zm7vxUjk({dedE1u?2TsL(X=&UE}EeLL!S~2i&eEweJdWdp7#?L;*b3l$|d@=SB>16 zqNDd%>nx%}yD*!_j7uj2lGRlz$Iqawy;k2phN_BuqyE(QVOfRQqc@9L9HlPbZ<0LC zQ)9_yCjDu^-dK-pGbW`%)?9`xYmqBNqh2K1mhY_#`U}ImG9$)8&(u@TGz?sdCAW>@ z$W5AlhO8gTWOl{NCc9MbBM&aqdMY@1CWoIS5X`ypVRLklx;`J7r(bWwF&5T^Mr-W_ z3x-j3%DAfN(pYEAZL#Muw&3U46C$f+ShIiiMw?CZ49%K-x3kEXxf;*Z_&xp0ayDf5 zO;2%9HP-IeFn3SulHb+h)PbkY&Ew zH&i8PZ}thipJEHDgO2A^nu=qhp+YisDskDVe4%M+tHSAr=MrynAR`KuD;>P>=)D)w z83o>~}hNC!|^jv%WgAF!2tYsD9*0LL3kUKOL!LMhk@}<2t zUuMUd9X1q?l8j>l`F5X0v6Z9kDkn0oEOIxsd_|)aX6!qE^W-~!@7$_28?@ZKrEtqU zFY}R#b%k#8=e|$Wt5SWdS^IjOm>x%vAF7S5n$oBAY<v z=I7!w5feM)HNR0u!wE-?THhJ;RXxxw-e4=b*=KT(LHQ{hTrevO{(rMCqO!b!0a3TTfkx zDm}&Pw!5|Y@$(s#M`f$_-hS9yls`_D?oHG!B^s`l$Mo1rkxhhUru;OA;!oHac&f-P z5uohaog6QX7DuNAhwK-vMsRr@4TS8Z;`~lQd4DRb;kXzFX?wK3-Tiyny+n4w7=Avx zeqSQ7?q&ifg~#pU82e3%SEJwQhzR_{^k-p3logY&`ghKiGTkW5ej6npd|oRzuw_ZH z4$D`++5XlIFW4ajqTR^VC{-M`NFQ08yol_01gRa$U3~B^2I583exKJncrj|~>#8eZ zdoG{uVozf^c_Ho3Lvmrc>d+Hf-Tl>H!icj!rN?i2QLit+4aqydo@2H2Yj79B0$t|H zPGpj+4Fz$2H>&}^knn+n3JE6HPji)wVEMl(2+;maGXmH@1?H_!3BE7G#?spj1l9G( zNwbx3_k&S^lm)10&^s_+AlnlXF!KcbM!rFSbfp$%+dw4nj}SR=Wf3+h`DYyeMa3Ft zwh99%W#G7|r-}!@!z1wkt4jMve@7-AV`(Xr*Gj))wNlfTv))#0NAHT*qH+$@yPAD*GjVs|6J%(}r-n z{@qfH83~CRK}Rt69}fO?9T{$%)v6cX3VeB@LcsS+UgC9#u>LZXCADRE88Q-*DzM&? z7lC9fb4l7I!G@)@A$SBr4rT<7t=u2Z-MBiQ576G*8 z6u9+>chFq}z>~w^%_P_H2)W}B7y1kLL#a~??w%JYsc-@`}Y(9$=)@wlamnp8YuK?>?uXF=vp5_2a=r6(=E%v?y zaFb*Jdm#2E8XH(~2sx~vlN|Hf!vXf>>qQkRY%ebsmf-v)@has4(6JG!Kx}_WlK1%A zR}j|iB9JIw0wh{ka0k|PGb60yMZjaYzzk~tZs+B4M4*k#z~;4xT|L$-m5murlBZ4V=08!uC3!UKf5D zH3?My7;sp`%9Osntjt^oLS+y_(-34Azk}`dBFO$X2ndkPgMiJ50Izs>kSMvbJ7VwIT7yVV~NrE+YJ-d#*`ik{mzs5`j zISOehM|9(tRcV9?r zuZK+s3;ul-x$oj?d;^T4@5%K_BMz^wE3$0@23xe6{~H$lGqAcoWCC7S*UIN6BqT#; s3u|LGM-w9x3wtMadq+Ea6GtZt6X3Oa3viwbt3N=}14dgU%@@D^56W$M00000 delta 40994 zcmZ5{V~{Q|ll9oPZQHhO+qR#vZQHhW$F_|-wrB3(es}l#vHNbSl1eJ+{?*kv>2nfS z1sYlcil8J53I+oN1O){|)0`%mgg}V;Kdbe$Ocg;OARzT5A!S~i3v7^=M;BnA|FOXM zXYp?v2;{$pe+}$kcXY921pPl}l4giu{=e7%vPgQP{$HyUGl(tB|JfYf3tL0`=g;Y% zFR>J72tt6Wx2v1Ey^@QglevqVwYlrRnU}Y)yPK7{gPXOfv74g{gQ=adt81C6y(5Y+ zQUC^3#Q5S-l~G;V)|!vnNwnjl5e{@*6g0DZwY;35y)md|y{DOD(qqGOj6K@}=KfF_w&rE7%sN6`a+Be8+nV%cukzVkX+GKqg;tjFu`8fbhuCg7I zxt8#mlw9G}d;?j1g?TQGg`SghjWyD(>(R|uodha=GJEd1t z4dBUm4IVI&lk)_tft9W+a--U1K$T;fi3tIRtI+fl1o-Vhl*-FrWpW?@D%H=bD%({I ziORccOf@5I#)LRjZx^YVPoQ`TLSs#h!J<`)<7&oC*PeEn%JXO9j)WMVuTd#j*7F{+ z^T5VzTxfGhly3>20M~1%@e?p?KJl%=4FIm4%LNkk5PJ4raEb88TKbb8zWWDGSHYi7 zT$<5JJsJ>!l`k*-C28ZqB0-|2W$UV)mYfn9s>)Z*{JWx+tNP-~Aj?^+IYF`cQ`aD{g&>pSzvqjL;$SjK!0FT9~wyLaPqzbk{r$rs`18364}^G}LeyT=0)kvR zvUDQpiDZEHb}WV@;1)d%kaoU=F4VlX7Um{T?n1D-zzWDjSu2gFxlIZIN@I!(uEX*uD8^KWMsMe+&KBUP<2|u^lgj*1%D-p<3;Qk@=LbXVbW~ZK2>WL`{sZP^?a94k4WsTme(8})2h&1rk zDoN9tYISMKEi-dx=Ww9@=(QQ$Vl;a;5yn;JWz)BxHd_%Xl4VZKwLz{_bcRCNDt5rj z#zu9azpb;f^`SEb;A9n>SB2xtQgt)%wX@B{{CPj{W;b2VEFjkP$eG1TKu&S6kRV&> zN``>93`ZYUdI>%bGLDUut9m+QW`#A5Tu23(UHOYh1Py#R&)z(y5?jlC32~LoF~51E zJ%TzYJ8`;0C!FKNm|CZw`8Vpz4xT^{-`JLC*Cq3h@S5l>U>gTF)PJ$&1a6c;XXVaD zemukC<=%gF)O~4CeP~PB+(b$K+(MXNdqqvRfau+K4KG|*wmm0-OD@P{m=DTT%DRq( zm6p+Xmqh|gt3kV!rHo~*VaMG!tT~qIk%eGL0lTMBHJDFO2Agp(xzYK-44>M@N2ARQ z&1jm+B=)8WpgA8qfrS}L#W0aM7!%M-c5L2DV!SLPo^jALX0A6<6QGy;fMbx6G^iTT zOMEOZ*KBzEaZ8P3;&;|eT*Pt{?>d4P4Tb0E{7jNwZ5F<2XQsDkXA%dOrD0azMS7bn zZpX?Z_U2sOcOw!op5STT8}au2E;JS~@%fMxn~-D)$j_h-3oZZ5c19RJ%1>6pKxc25 zs(OVMe^#`%DTa@Um{&}4Fi)L%SqwiR;3>FwG>f9?PVG}GQ4?aWYrjY)yVhzS#l%9v z=iy0StqlhKnF+4+p@eDYnF?o=51~@XD8I_4ovEOjU_xmj?YHMhRuA{Pss@>fv6nB+ zJ-Z14px31lbb1Rd4__mnR`(Xx&|F=`5uhfmil@|=SBD>LL%^0Bw63B?^Uq-GGpzf! zRBHO*o+lt?^mnGZHoTpt4I2%nSJ%h{Nvtts`9u8XL-^8?d^iu;`#N{Tqod|iUJ>vj2FlmR@+3VJtqOPxAD$jJmRm=Hv*78+PI0*Fid6qjLZD|r;l*met=RZT!TP~n?i`cV9k!q6PZ%(SfA-VS zlEIxd5b0CjlleyFx-lrnsnQG$nfVX`;46FQtRwvVaJ)o@OX3M0Pn2Zc9|`FU)sQ{0? zyTtbpT>P-60C&hR*5KTP=U=K9PtKy*m@NyR+rBgR`Hwu;`Ro0^Umuu(-|yPP46&77 zqN1o0Y`G(q(VXn>eiF#=1IT;s)koYR1Ia@E> z<)v#8*u7t)73J!TvZ|f4K0VZjLEENk_(kRv;IOO*{~30O|EcT+3lCE z6F2h}Gd0WF!m`??iBNN78{`ES^g#PMqy`{r)=6vz$2J^umu|9X*{AAYhSPiu_rgD0 zMLvy}+>#eg`a^Qs;kr)erd}^5^_vyxjj#$TsRx%n60$F{s`x#^=bUvru1gbu3h#_) zS{@doWjpK8jNo|7*5qfai^im7XZ1gOJB1Z!ZuMXRUXK}@y?lC$i1!n?Gv+YMq? z(8}uoNFRzU0%pt31s(&YR_<1PBB&%qgVA<$qUVOJ-%D=^Jy=h8n z-1d2z(VhLf&^ANME=#J9guNJ^r1BtFp7*uaPtM>Af8Hy^uTq*f=jk4xOu&npA)U>vq`ETZR*VQsmjl^5@ukSUR!> z+?ZTE1W!Z48lT}<5wg*7F4g_D0zes&<{Xo!6E-mn`Y zaGsKrcsI!(N||1$$XJxNb+yfb)|AA+fxfu*hLls#YVRHT8np)?X%~=)2o^S+c*EL8 z+xZ3E1)Fqo2m29oPG|CIM1)3Fe1-5D3er!KkE@6B+s?&oy;{h9yf1kN2BIO2*PBFG(8 z!GmxZq3$CRRSrL)lG|)IYeE@~aUKCEC*tdpQ9@{*s^BT_q~7SV)JimAj0^jb#V1Sw zEFVfF{csABMlHp=@kh_he*Eyp@0;NaBadQ~{iwqk#}~sIM()*> zf3o2WF?05jE^?UtWKSK(@AI(wamU~8{eL-Ah7*q5i*kEYM)$xV#A?OpI8Oka^tQFA zy28zAlw8ZJwnM~co!umVCCR3Ii;@mMv8oQIJY|eaMx0fYQ@WaFppi*9SaG)5DYL?E zQsXeeo}pjkx5|yL%6V$grn`ZEQc#Q+;1T5R@w7D<*?trY9G}0M+iJ7+#eVZEZMgc-5ar8GT@4D@tUqh z);!bt%x!6DyYuoEcFF=I+T`SO;t@(cx-lF-VY_=+37@Kb+VdYQC46_OQtjm3<~;}M z)=?d$JAd0b_n?Ej&#t&v615j{|H-6?iaoJj!_2XpHoN*Bsa7gk}%^B0w@&I?n!8Z!)z4pA#kE8h%RZ$|yZI*d0X2>!7 zgMjcd35|~Fq&(`)M=+Y826sG8lRwOk?&_s8s)}_izUQDls(2qA4NmtcvtEovg+1Eq zQ1f1O{skv!DbY+5KwJa+UKVW_^=#W)d@$2v*}3s9k2avr98>|&?oLs7C6is(6KC#s z5;b%ydC!a9KSu0*FA+_Uc#uQ~3>B!?9;>4Rei@>-dP$~VFz_0oxs=yng1y)lI{`Pq z9yJGtxMvm?)^+o0v*?>@@4s4p7OK;nrj(yhWJv9l8rP@plq%*4H0c{lQ0)xwtL==3 zM-RwK+{W~rZb1O5j^KNxUBL1ZFk40})-yP-sR%0HBhb!4exw~>Sm(&4`$`YVWKUts z-D8ZB9WzY8EA|fM$-C7&>Ddw2T04Ogoan2%(HhkA@2&8WH7yK;?|8cpfCozTyVlg4 zhrah++cn#&Eg^v994gXv`kYYJ`yieq1N^EJ zr*DCWg}>Go0mqZx38y5ce0{zWo;Tsl7c2pyaAnpyuK?hHNF5lgmwIO+*y2q*M?OqRutMvQ_9&Ny` zmkjBw#VY_~dltbB*R{*p$CuLqD3o?FXin=Mz$`JxUwb@Ljy)2sN8es>wKSUW6HfjP z+ua$09vV~3w@r&KUqqS-P8wVh%ji@MKGlRrSZ8oua|(}h9~H$H zB{NXSv!%MjH7RiVE8W9Z;vwcyrS2v|Ydqt0$i)zK3r&%p>ySN|8x98N1ifFf6HOTK zeC_~LMHQRh+9`@#rgF1HFOr$TOgGn~RAo@?A3NZaoxcDgxd~-ajZLwl=y(LOc+dku zC9ZK#4VFvL0iiX|IZoMLeg(N_^7y>`JUb&WP$Ey_P}yJ$#gupD6Zk z_X|`hYXWP_x)S3M@v~u(C;aGSIf|*ye*OSAP<_`Z)Y`>K$o!LII*+sX+80+mAyj6z z6rMaf56o%$_c@k+s4eCw>U=8`i*jaBI{j43hgeMceT+W>ejB3uM26tNOSUT*#cgIN zh#Ah8BA@!9tXElMuPiF7y=1*s`6h7^R^F*y1aDuI-z~ZXI!>ccNM&Q{d{>J(1;l_L z#+)sainxz+f*a)1-0ltG2>vU6{GzjIDNTL?3o|1%V~J9ha*MGPq8}Uet@hq_V}ki* zNvw!MZ#`vi|B(T;uzjwezZu>NEG((gNW$~@BTEfM#{4PgFB-EVZ({rWX0%>+-KpdU zen)H(x$Pg>&ERJ zQ-A+YHI!?weHRxM2xXvICP>+{xk)!ni!?N4D@NiS!HI(eFP*r7lz7iX zbZO?99D7ZAJC`h0rxPQy+OMR$s8O3>La(kYy+E~L8%AG>_iCYGyYS3B#?vcoXmKZ%54 zPR5P`XV1%)0;&o!CS3ttk-q7%dH97U^)F8_-t}|`u3qYa^CwRrUNx#-?t$qcm}8e^ z)`{iHRJF)3XP@46&ur9wK|=+Pt}O-Y(vq@)bH^`Bc2M_Wy~>AcKy@b%0efWgvrB5= zUa*ep?<8T{W=rirb!RugHit3jd&q?vhucFL?;k23opRYUVJ`rnHs_w9A|U%S55b6U zyZ0{9-#2sz3>@M$)8DE-Q?_9U1w58Hixo`^#4yj|wQPg3c)H|q! z4q3Qo2HFdh(FWKDHSabby*hgW^a5Qvhqjr)@Nu@69Gs5btwmMt%VXuMIh^cuj$Lk| zyX9?iVY3-mJoydNT37Jp_di~A))&mSF$B`WkG5HUNnVx}Nk-X=c#3Xo zZWPZ>Bb67@=exTS#pRm>BQgN4J=Bwd1gMiP2Uw2Z zbH9q0WA~KE(%3w)ZD%5tF=4PLfAjE{Z#S=YDqHa#f+PZ->ex)n+oCU$ml77Qj@h}p zHq3Q1dtV+Jf3Y=f#$wY~S@k4sl$t8>At7EQ(fbUg-nmt*U$UggvFdZjIFcYs5kir} z?Xuv^l#aT!*FfmzQQ~bGdz7Pen~#~&PT^JLJm54%b&{m=&Z&7!l@=;vU87p~%Jg$m zlE|UrJu(A^t2cX_pjD$?Dq1}*V$vCG<;AloB*k9BbA`hiL_MD-94OkTF+lGk5lV)b zWEE_ly-Om6ki@~PnNYQ{BjgIVn(bJ7PH@Y??P49Y)79Qt?@=H`tDtK0NdN9E9jZ<3 z1WzuTKeIGN8KUBC8>h_2kce1tFQ-UQr7_j@XS)LeDV#QqJaD9CH9VjoqMP}$O?Iha z-QfA7mBZEjZmQxDgah_oSE2e}1pq*rSW=mK@DY86EkG{iTr`aMRF>_wd=zjAfcA7d4aVRH_&xUl8G%cQ@wl>jL?fM9+ z@^14r^d6K7&beC$DgPOkyC@06q=)-dELUn{(PHW%s@Vuu_|wbgfo>9bP+u`MM0%7O zXKVp4`2ksQ+XK~ktf#=`@nR)`Xlj)fvSRJD&#IgQyXi)GVOvG39WGidrLLQ{HWGk? zB)oJvG^UJ6S-SlC2K4c0n(#8%1R8W9zj>GaeprM`5WQz9^vG4ulzJWcLt;ke+1%fF z8(Y>kF$Kq5EEx?iX%-lT3!CK1^-oya>=G`AnW<7}J+*cVSA>fx9Xflnv|blW%6qh= ztD>lz3Dw?iMoLI#wXD8tN{<@Cnh}6LA&x>(j1F_bK4wn0(FjC zZ4@(q=&0#*wRdk+R4*Mm1Krfa)1lQ&ik`5gy}5H$;SAwu^|{w3t9?lp00|L9we zSAj|_+Y^QENas04y6|!M%RcRvIP;tcAbBEbgnrvhOV4Unp-;b8)HS(KG%S3$ENepE z#4)(yuAp|e-2JQ{zUF|%JiAn~+iYpeU%slYkJ2LhET-1d?FJiHH0wz}cxJmB#f72c zk3+Xh*^AexUiM2Pj{p#{mAz7zofYbgQcQ}6nogdbA82(E3K6?;y)@kxFUD7Wk)0+* zK5C!VlBJvytrVVnTRSRx@mRm+fi_{~?h(gfBXlAO9+yz% z7fGo34xLtjHcogNaJ?p))xwap@JZ%h%_k(N`T-?a_PG4W0R<>n%nAN2)PpSxSu}Wt zZMQ&K?HvA#K{enkqPy66g*g92HlzBB?hctoQe9wdp888aZGh5{WQ%OV+zBEW?;%! zNi|ZCEZtyQ4i{k1SoH;(#qoJ;%TfOL$BPD~U6kJ&1-wbuF%rv1#i@LVDM=$^{t0a%9|xH^d=$Z6 zS_f~%GQmYjn7nOQDG5#J3mZGD9!8TZ;>bB8A`XdAZvb^6(2h7nr zOD|cDAV2Hcci36O?`FYYTG={ z!ACkCdWbHN%90Yd=m0AzW*Cu|e&aerb-69sGp=4h!a4c7oWE>87`{gFvpCL2K0R~gr4LL#t5_&n`chJ`68UV`-GN6 zQx+i6VC}o{z}0`fqDiF53S#wnT4J}7H_gSmnMl1s6ig7#I?wfyhN&eNtnlJPM<7a# z>71Iaap?kWbS7IUV64lso+#=`m?G&uHCCE~(Qfc*<|=bPxzhxu=;e||>ZxaB9$}&Y zhkj;ObEp}+ygUC^yqa26^emtB{D&Mb=LT?9m}V++S}99DnX$=>J4t}MR7SI$RbiHl zj-AU5Ojf1KP{q+<@%Jo=wQ*<;c=mySOaTo?l+Wd?^HE7j7_0A!R{=>u{`Ey`$$8+4 zUb&HN9cY;fxE`3!XsWY=p03u6|aD^&i8nUtg_=QY&bY}gSCV_u8%!yar zn+UhTYmQW! zhhekbdFp zEe(Qa@F!Z@YKY3pf^vSz(S*3f7C4^t5EpW@x?*fK_({wSmwNY3^AkOB!%_gFaIqgx zPQRS5Fu9QIImgC&NZW}U?=JMLh0wge8>Yo~HyfNXtO`mliDNHej6XgP|L?2!`^HR?zV7&^Z$P zQ>eucwDLH!1@jeQ3il;+tIq{bdT~2c520VvjeiWVssb4b%bwx86TSe&Zfmui3*SsA zBoH+Og^^1uLrp2~b5*TB8x)z(o6h;7G&UnJgIUFism$AxcTljf)uzWHK` z^$HPHf_2L+je$<~wLVFg)3lJ4>fq6XfJK&bQ z?fWgO>St9uaq4MnBaROS!q=V~ICcof8-4225Q{@(;!EvXOSevd^5{1&3h}oFTf<2leoUPq)mLOhSS zZ#GL?zmPoVwHx@}2!D;xo(DixMxRwI;6AJ3ZixfVy@$g+^7SmrIOpu&Q8o%Rye^Qt zubr1ZtNOZ%nN}1Jdm*XzeHUDraDBo!5=sW=nX@5U= zv*$w+RT{f`hvFk__+s7j)mvzqpmPlzhHG5bNDgcRdz*udbRY3{Zj!Wqt%Qk+a6SAb zfqMp^X!XS!d4W^-qElb9lYM1aBd?$pr3dOmTlC2fgl?cB5hO40Yq?T$r><^u9vqAen7JcxYYeCb`7riAi??aaDhpZ7& zDf|VJ0SGyKlUn(Q@>~%LUy!OH0p=)*yfJ7buaav#!PE7gdzQbc*e>-W;-(w9Pe9 z_#xx}VjG={qg6;?I0J+~9hF`isLX#*Pj>c+E&=92K*id~vW08Fx+5r5ul;=;vrV3M zh(;=Mf6dO8Ya>&>p63g1BR3+s3HShMk1%#tKSe4dmZ-VLtShP$I1bV)l3~#`? z7;Dnz7h&9fa(>3+;@=LiF1{GQ4Yy`+jqs(}12VB+8qX4G$t$cLEU7<)CpR@`zZ+Xx zay~EahCN;Hx#xag&hdG25Z=x8xa>gJGP&mGFmL3&LdObw)A2oR#PA3`IuPvs60d}H zs%<`7{0sV@oYn52T-3-v4nGY#rH~LiC13;x5T~K7yRCu5Khz9fjWTG*4CVxamNTlL zDuY|d1|8Ojm28yGQySCAC?S?!Nr!r#&S3qC`)4bopMx>H!B2kwlkv|AV9}%AEQIrM z711**i`R8-rqA^IW8RSwxHpK<{M}hog3*Gkm(f^5g7(yGXSg@^AA?{l9S+HiJ*{;J z827;t zW36*zv#+Ag6ED!Y{1Ip=_LN_q+iKMYXt0wy)TGbWN(1lF8N!?++K;}jfU;NDNbulv z(9cRKcB9P3&RO&1xZPK3WRtY6Fkuk&5TDJ$8F&5D*$IWz=&R9-6tKbP;BT>ZXU~qw zv5!h&IVobz#Md{B$*6rfg)8xr0MC*);Ugo?zD&>Tu~SFnkwai?FKREvck?s@>=+ey z76X{Q>(U%5!ppnPHiyZ!JJ^>eWDd$U7Gu@qX0a#rEx65mM9{sf%@}U26x`LOFDW5) z)qV1?OOY_ZR;*hSk1gh8nz_%^{uS>?c0z)Q>Z!dTJHXuZ5_y1Ssw93PETMRyTWzG= ziv`8Uf`lLnXQI5K`@zTxW4KWQe9m#icdEsoL5?T*E$5r4CJqA^o>oxnqOYmFqD6t_ z&yGH~ebu0$C1C`H&&18b*cQUp+w9|yV8IQKXu;?2*&ken6EKDoB*F<$y=8|uVfsfs z)vlj_YPg5jSgvc0KrAe0a`Rzu%JEmKt~p@0dg#topfLO)Fz;$1*h{DY3f8Ii_Ppc# zV33f_A;{qK5Bw3YA%VaCezcy)<$}@*|8ARoQKxZJrPA}+#iW>~ZBuHDRo5PyXs#n! zAJyq7&%zg++M-kaX^bYIQRHe!-b7T3!B)F-YJx-~)pv^K3{LK@ztNE^v-G6SYUwOF z>Tjc~r9C-lnaQtu_~I1>G(fEvE_dJmK#Hu+Rzw>G=`@k=)H_?$T*|$x#~n|J^Vn=< zI~xfU@%q)U#rp0~521-2+9U<`M{}rzl%_y+=j+Ym8dK@5%94@v6+c4g<^Qx$?5a_h zuwt*4M+gyY+myW`BkwTNvs4plktVQ1<%`!}_<^pU|6N1;c@jDR(8rBkwZ<&bEnMUC zgx?2axSy9SoWm=l_qwX#h({@-J;h<8V7E$ZoJ*- z5_)rAV`J=1-saEotx+9as=f6dARo`ap!);g*3XLXrw0J$dBwDc13F}W!MCQ*U(Omq z9x$*lsHMA9$i2c>&QtsqJo3gNV4lGfUd~yU{|FMEb-CaB5J^q2tNMtJJjf90De9XOUl9g^Frsp-h=muAJM zchgCwRdFU(?Uu5O*Cub-v^TCpH#Z5OV5q2Qit$L$#Kh}5gfAc>1B)?6aqm6_9)>_2 z@84$SI9j&t;Q`kv9<2X#ZJe&q%1po?K6KokKE z9JIT}6FR`18VDT`kMO-Lk&N-qw^A`uT@z--GB;^3FF@%Lhk{1NqL`UuiAnFm?N89Sc55#-+n-bPzN!@99z>?S%W##hCl(1=N-MOSt&hw>LQW7x;J^{5(4yzE)mNm6l#+a>A8&EcOj+Nh>O-_{xB3xl#%a zYON*v(xvqDW)G{$*m@)L{J{D-s{~1rpHro?36A;G=-%1$_PJf$IX+uYw^qYnkNSP0 zJtd?e!~9_={Jh{t!OP{$bvYU$inLm%nfXm9lkr76JhKft2V2=vOFuLbtj2Co^a!`h zGid(!Gg`~ow3Jg4MXo+Nilcxw=bR=!i_%vz3bfiQ)|seyXw?|Xmw5kj35pieil>`) z?|&Q^c`O>@>NT?*j$0N%OFNlde7LvJuhH2L4Kz(}K7Rhs7p?H2%As}pkqa$%Ly|H? zv+^-_SFw0mzPQZvouVx0qFwQz*|u=vBKP{iB9PoEPD&N%D?jiv^fo{n(uJv4qiB$b zv3vea{x`G#miV}(JOx(Y*eG|m-PTG4yXt?%FH33PmDs@zslY*FFQniaG<<(dRY#4g&kS@ z9HXkRxSz0=`qILYXg)y9UI#5ZSeGct1o?7HO#yZOxjeIE?vX+;;8&&Mc{(Oy@UOI9 zI<{}($0R#X|l7=o35DT)|$%7z$(KeqH*cw{<^Gnv2vvdKs?SIg8S98CGnpWk-(ju{r8|w03~Yw5SWJk|JK5ABLX46WdN; ze^oht$Z^@leb|z&Ianq;@vYp7;OO10GAClfT@?Mz}%xVeMMK($fnW^ zsMOI=QpuvbAz&HzbS>c7viNlc3@Yd3ubG-S0evt?4)TvBG7W@PWO4uzwD_fBv9@3Uq$a?sTt-m^j2nY zoCyNtLu<+pcruR6MeP`>t10wjyOcsxKNfrEE~7#A^mq?7{$%P3=WnHDdaQsi8w_na zhxYIyAann)bFf(Be7Y!(!9+)mQMgwfle-W;EoL<5PLsW@>3aQIKiMcz=pXe8G^T5T zJDTdWd5uvM-Y#}+7&FH*v*^B-Y}dz*3Xmnhs5Z&AZp6fT zl+p7B#)|= z8^om?Jmy4Qy0#7X?p`z21qReB1H+y3Ba?81xD|nE&kAE_i_GXyX!61w5zI|ns2sDx z0AuO6XIgWtLac7_)48e}rdNqsR>tZ^B$T|s1GB3blO#@<8Z$*EbZF1~|6YhoQqRJb zEn1J6=W%H2nqeyOb!bZxSUh|-+j@X?v(w73-Y&ehDUW=r<0(5c40SYp`9(^+u_dW1 z<4_X%2xU}j-q^vB8K01Vm|u0?HIr!|dDTS{(Q zN?u!I6Au}Tn!Hifyiti9=eU;kHErAG^=!l<2F^_d^GOKRnqx56t9w3aQQvYju; zi^nNnU^d-W*U~SzsiW4c^e})?xShRj)i+6Hs~bDR16b=~TXF0Me;ln+p z!kdRLJko|}(TlbnS8$mtSDtoH0EXqv(G0eZyM{3Wyz+@h`FUiWin~}RO6_`HHjTb;I@KNMz~(HXJY>-MePHg$emq-twJXu5?9byIp61V#Wf=;|=i zOH1c5onwk=_(@-efu6kM=swiA#()``2Bz9A48E$NY#h0% zHtq;|hygmxu~OqA-ZwQTctPIg#a-X5?>W<*E!cmv^V1w;2yH%CRrfQbkoFMDd(d6I zkY&5`gn#?N!fojFPBVYlymM&loEIaVEFqf#-Nv&8$?<1P=Ms?h8uEr|w$DEDsFQy0 z-UX8ClF8VEWFY>G?(4x%s$w#45VHPgmuRssrR2vAME3K=dBoGWNk1x7DsFtoRkjdu z#ZQhgVGVZx?@=qhBwt@zm#TItWkXMKA)#0ppH9}o>7rpW-Mg9Q4O_+1qui*qiOym7 zy!shm*t^HM>;nKZuVbyb6%!Br=(Cs5Ug*ef7U~I3)sojH?#&|D8H#z}pqRPY85j;R zHJwWz%cYO2r)Tj+RfLVFr8eG>xLU*W5xsp`G2%QbV(CCm__)4wYp4LhyL~0vN?hJO zxYV#Jx!?a0{7(oRic?zC{0{<)VEy}qNb}!R!Uzt09{6a295-xOfS8Kz$UU zSN_qjM{kcf!?U^*@lNI50sQXaH~`wGA^OCtAo#6DD-5wxE4&4UKuMXjYbOGc<~@-R zvAS|JLcNrkc!1*MF;S1;)pRN$q4NG1xeK5M_{EJ*IBH5mFg~v4hgYEVAk9~Fpb8^U zXTqAV_JHlTmM|}!J^%Rt4sMuQV3-`CI62HHEAbB-qfegK1o+ASS}&vboIJq|*kJ$+ zT#R?9`Qh#>-|GwZQ$`Im96`Pp=>?P?jlV}l7aUo_1k@KJ4j@%-c^9_z)f_tk9LIwI z!#zITya;dCS6A1Yv`FVXTlqD;vn9ixq@X z*ecSj#p4kFXx>}>!g-uH3h*_Ltf(Zwy_5)HJoaG z5V?EAqkMbWRTT1L%{>=}lKx!JOQ=v)2r~OHZ!vR7McFZQN`%IWluTq`GLw7_zs$~% zGk+4>dlQfDyc8Xd1MB$M^LrzkM?svZgg7#5KyWPCFY_+2zKWD|=5|I>niyfgHXF7# z)oCZX`4^wqmP>fcd89%9jIk^x_iI_L6&)XFh6hjYpQ>vH*H{mXv6&>~s%vor<@07l zY0Xm+9tG^ARCAPpF<5{TN4lHucvU2`y+W7(U+xuXP?~#739~OHXbq1EUYzFd!u7K; zm!ul`_Sna6J~m;4X?&xd#-VQjB#*D+IQ_Spgz?e4shsXdo-{V5diN4Ks}Wf;hr~&1 zY;KL$kg(G&sJb+kG;3NUR-N<_)}PG5qgaQ$hlkXYKrqG$k<3^{0QGJ?{NNobhVK>LV&M$u!G0ARl8?||2qZ%OZVw)P+dFG zip88eZrtU=PRRPhWEOMDmLp;LKcumixiQkimkj?WmgW}){>|O3 zH93RAm(MgUg38%J=C=;DStqm2u`IKmPcoGlSsH<9QjvkPHc3OngxluqqCV6+(H795 zXRxq(%O=Jp|6LpkD6auiml}Ly5M!_^zK%OaKH)seamHnL|M_6s6Iosbyt&Lj7$IQrFT16d%MHv&yJpYc&EYP3FusV?ieVPErIFsbAIeo?|eQ3i?@9oUEL@^c}X- z&!q>q+Ld%EbzF$53KOfFbC{1O2AISNmltMor1 zVn)OOtYz$RTE1ZCiI6ec#29|78(uTYME1+jE1|tggFA80{Dp%6k+bGDhhk`~aU?Wac@-jLyZ&fUL!yJMMlFKXW+y{z~yH(yL2 zL?y#Jf0yoYoIK}zc0ICA;j5g-if)a*fi#Q(pzXl-#F765)MEYFJ>XPF0aUgPE&wK5 z!=dk@T7PQlP`@>&zW79@-<|MiY;r<;MkRQsI#!^X2R`-LAwc+&@4BH-;Zfoy&f!PV z(7t{su-!P6O^rD*j(2D<;S@?6N3egElpsR-gC!3Lb+D)|@gKog_SmAA7c2(JQS@j4 zzd}^0NX@-vg&T#I7-0V3EJ3xRDHIorL(_y}C=?}A#Vl+6Kd#<6IJ2nf+l_78o@8Qc zf{8J)GqG*ov3d(gjt{Fta-2uoZ9crVoo8iZ?T^W-1 z+I%r~-ChjsZ32@hSU0Y|ZBT1-X4~^O5K>m&JOq?3OwO(@?2160D8DH-7uV|ap%nl* z^U~#^g4+BlmU~E>f0v`@MSW+-3IFkkH)YdI@7$>M6Jt&0==S9G=2NxdG}IgV2VLF~ zB|WH$OhKZ|AYPFpxi@}Ma<$$UGmAz7`VIg%LGECq3L z>RjZUjz01ku)-8qViYrJe9a230>l`X%Bn@53vnMvK#nnSl+k$I9@V3!!1EUCaaR2` z_q)Ku^p}?dQIFV%H*TA~`hcsbm)gLyC?5%+FEkh05Y@;qlnmPsR|LV3#qE#BE6q@0 zqbMusUMP&#fDuBzU7nrspV;2#{F{L`oPd~kv!XRSjNyTu76f98e&m~ejt>|?tXn&b zn9#Rb93TH-12^rx$h|O{tjImu(=3$Rh6wFAxw6P?hQPt*iOUxK*Nx7+aVJ?i=T6p`SZcgJ0PP$YND>{ zJ|~gUJ$QxI$yl2)d&*O6iep}!KmQL?=Yzz|({j3lPagBcP0MV%`MsUFA}J9>JtB2B zQIQ|;I8YU^LFZ!g=fn)lc!u^Z*g68R$uVC0K?oN^oy?-05@?dYrpf4`5TW2os66ww zNl@R#V#s~;$J}A!;R)YRF~m)5%wgt+9#<_ftwIqL?k#7Z$=@0yf{K0lySH{KO1oLi zlwR4huDrI38BoWh_W4IHe8a$*PMZja<=w?&hO-rJ8U0?epVz>{@6}ZhgjaLx_@i~$7EHU2CA>vS<3c>1203cU z?2ir8)Kn$qbB&+QRF7u9T9fFC(0wp_J~asCZ2z4i7`>MnmVahd0xQs1(QiI5p47Yb zVDIKP7(%;pscX_Q(tl3**D?-p+$rYq3C4D|>QyDguTc=M4%Mo8E-+ZK6N9sJ#kYS(8}|~zorTF zgbO}Ce<>^h1pQ^ztTb?HljHlO@^^La2vOqM8iq#wP#wO$@gyYPL*@be3!O*xD%h8Q zafBc~PeBzlzBtxr(pxKHl#{@xT6m0}-^85|vr`?W=ECm%>-2$noZ1RLC8C;3(nQh2 zvt77b{30`a{31NOJ#gqt-)2Zl1eA?pS5~h#LWOnk86z;qsOqvK@SpT3+D!*P$m&Zf zg8n_v&}C*D6kj)-d@Kt9RFl?#?TK;`u~1EltxXY|?5*$moXK%;vtyN(b?gk3Ttm?X zodYN3Du?!qC+UzDq}2Sz5jQL_!83k@IUcLeHcEH3F5e8N;*h7aNAQ_)-V{t~-@&dK zeamSUld!21uO#@C689I&{%oC!EH(mvM~D0`RGL2&SEaRQaFqat?J{SWlV|pJL=M%z zwp>nQp)K+2uEBWq{)I*z9kp2k5!Gh>BjKuOB*pVCUERq!Z-nS{0=&n+f;XAmZ*#j0 za)WCt&kB2i0;`K3EMbgG4xW+tgQWL3I%aZ(rM(?0dMsr?C{VJNe4v9(6+J%R|M~OMjQTP+ya2Sl~c|%rmS|6Hm=T3CSYoByvXE(DX3JK7?-1hs|LN@P1<%< ze*%-sYu5xYDF`;fT1L2?*9@xE6y}B3Et_BY*=dO>AmU`%LOSFe83*GC3YuUME9!=| z9Fy^OU98g0c0#`o6*ly>q@ik@o1P9ygQaUUacvor8X{DOnWE<;Z_!z!=Fmn%d3` zBio{QsGumjOXQ=%RpGL$YhbS50nkSdM#(!?X^HvE?tz4Z2aX&^=fCXL|Kw@J5v{uhoR-cSl37X}1G8W{wH^!q^~!2gSR3Q`LL zV3^|inAEqk@*;3!p{div79m<)k-^0`EKtO{th4pf!|MF8uj5^%-<+^AHGx&O?ksz> zX(Uo9(8bh>Noum9nb}iO=F_ZH)%w8xz+N~`-@HIoonU;8etzHD_sl-_JRVO3WCI|3 zTt1YH4TEaHxo0;R@c>%J`!sec2lg^Ud2o=!Dj7ZCbOM3M5l7?((*blued5MmGDE{E zZ2RbRX*ZIX$oonLuk&z33g3E*DqFVFt-F`dAoeZgEFWIp1QhH{OPOcz6B23oulT$b_;A>_8o4S*kVTkQrMQhxL$H+=pj zF0$B|k9>a^jYKFSwMak4#Ce#R0G99;J=&7~qPa3dza6)K_v9sPw}aO<#fGZ1J&7UL z{%hfYQ0aZ|mOS58PJV+yC|pvV-y$`-JpC#%YZ4!kObWJKtY~=XNtQ5d80j+KOshUn zZ%L{cQFE2c2C#bS*HBqpH`J3?d3<88x1mK4KQrL2$~B>W6xgLF0TV;K7;_4)u_=Q* zpu=le)XJdUXgyRz=;CB=IW*DYNf9Ypy}z&NxGdFXLh&MAiLuEUWh!Gx*3D$O0{yUB zfgPK;P|wD_|G%j>I;r=yiv zL1Tb2#k=ZxP_DqR7{bFDH$r5T(U32+>d(C%TB{T#HRiGzqF=SCSWL{h;>}`nFqnf^0ATgJ?G`?i=FuBOCasD9a~k^ z6y>xy1OzE49{tp8ysHXqa^M5Hb0)i{dWihZaTatOa9dt>qa2qZr}aNX`Wt*+Y5bX@ zQAtF_HR`468g+U|Ls=2!vX~zy>wx3_bW=7onxRN zO?XkdulM(C2mL-KV)Bh6BJIsd8JBo=h=1f?vlmLA!rf&zl_6uq?p|Bt54nEK58ZxZ zQ2-Nh4{_>yB&Dg8bJqU}B%CZHOeNx!rnubketjfl62v3TlUE3vK2EF8gr zXD(Q4Zx$9-E8m&Uu+wrup?OP{>;_In>y@YarJ^Ky_lo`K!7B;d*-)joeD!#BrtEdt zld^Bo`igccJ=xa1a0C+jO4`_J_(x?(5@Lc>L7=Z?ZId#ss)e@n!o(g=i#ia6|f8H=(O$MOPd zJ=VG|A+jiPjMJb6jiX*yO9M}8GbGsf{hE|k!raGMBzn2_)Y(~Q_UsaDzLd-tH*>x! zzZjg}zvJU91QaFUPuo&eqRi#X7Jx)WDw~A_|HUO1v9nlx6VV2O>FiX?LHb0)fB~5= zRF@5nya~f_NvDQxY^1?d9kvsZzH25q0nuL#oU={VjgjYlm#)pNFc1zsPAG1oz4n<9 zE$;40i!NyWTkl;idI4r#!LvuutJMf^t6?t3*5zp*?`O1vtE~DP=jW{7A^_KIjTc(D zjN6LMUKenGD^B}olfW9tD6?Tau?8f<7T}M~-@Ku_Kd&p>w(c3-$x;2L@xyTNxQ>Ra zFnV#04VKsJZU_#>%{o9RNf}6;kSqp0$z4G+y&P-{mrITnew-!pNwq+uZ!lQNIX16s zFKG3Yfi(nd@^?zBcg|@ePXZntHjYy*8OsuoX96WJp0(L_J5%yZG7JSNp}DejU8p`I zXmutN%jW{wa877*?3vs^Wy9djUkTOjyzLPO_M721XItv@o@y((&)`YTFC`A(*trp71P)7Jk+-f zn@TP1_k~YxmCP=EP`hqqAve5c(DB+Ax@aS^x9{^cTs?At63}`I~lxQ?0Yp%GP z-jGh2L$U#ypUxT;;tkTKZVMoCcR?WkbROOe$cRbs2LLhxEUdn+`j{>TkG;13yjh$jXsy83EyuUJ`uKTN)X0B`+UaL ziY`HQ%QT(=bV8I@d=ofD zs!#%e)ofHXXJjtVQb@WXzb76+lH={AF+FhI``~s&-?_fC%4erQ1OcHRv@7FSdxTL_ z(&`Vba%fb=_JOWm-g8xlR%M$@%~0JX9XAK2f-Oo&8*lb|l378KsWN+`T|_IyT?K` zzz@h;Q{ZN*^gs?8@9qO-dGrAI#oU059e7!LAe`EWM)P;)lxya{;9CFr1i%?%%KyPE z{>QBUGWG-eFB?ejviCo+-hXZ@3d0hXd_zBKd*-|{58$d zR(WoeL(;{9ozO{Q80zaw<O#Z-ROw(45z^{_E z8E<6>W@;{H=_Y5yjZZQYvU2|AnU0NM@fa}Cd=lv=QM}`*78-;_ zgvXh$3B|_)Ozn0AQ$~slRlNRt3e_)5#$ug#+WHkN^X$STLuAP1lW!R8*dkKKd84D0 ztZ!1s&lq{uXi!}QpG>+riEIAmJ4mW#t}Yiq0ZGbD%7aUGDPT_OL3MWllIyig-S=J) zJVIbZL^bV-qj#NKhs-5un%~7O7Y899uP(N19tk-EC6s(rubSRX{`p8l&c z^FI#VQ6b9`_wCRDkifV=YT!*Y6p(2aizZWfS{_{p?qBU+O0 zTw_5PY%MA}LfBT(Wf71h4IAK6DQs!M<+PRl+~t0~ZoBm`Jk7Wbf^j?1gK~t3V=-Hs zV>s&@Oxc*ilcbVnr7#>GtrG0Va5|!wPMVZ0s5diavuS`+DlzP_$XBJgg|E;^%c5y- z*(ZRKrTk7)0vR%ADsi0&G3WdQF3%HH=jlbphuT6UVz6vaUu^}y-3)+f*0ApkUcC|B zY??@8knJOaFRn`K#LBXDZ{13iLhxYNP?&G^I+VzOo5zytw<4F`jCyUF0X4_eLq(&xfFjHIdLco~*I&H*Zs{V8H5kV{F7Bdg_Kv!&!I0 z>(ze=Hp4S{%j{+07Y-2H!{XOK)P|LA*I!FDGS@`;+XC?=g9I3csRXARQId$uHUqcA z-~Z$I`%W}OkW|cGuh{OpMijK|302d|^Y(hPEr~yXIX9DhN^8~eFpIRRu}j!<{3j|S zibu|(xmWf-ksfj8iQ(A8{ggxWk$XvuR}58mDvE|B8$49SEs7%Hc-|HfB5H^7k)5Bj z<76S82j-=OWLZX0q1^>CkyZ}5H-v9wpFf#a&R!o`t@VmE;%VeUCgT&*Rhih?6?SFo z_~L<&NvxYtPH;n|deL{xd`P$TDe%@rhDNLy#KNHY2mB-v3nZI*pz^V=kpKU#_|H0q>#}>pk`x^endxfBX`|WRlr5nZ}rcbvKP=g9QI0(c~wKy%-$PpPdVy1yK zuORprzD#7pn!c+H6esI?>MF#=pp@3-rtS=fs%I_CnunhhnsCR0ZcX0fQl9+RllvQ= z_uF=MCBLbOOMUugO_<>Oar%Ac^+uQD`_$FoR~7*D7w=YLEu?Ez4kc+mx*-}s2A5Pl zQu6N3UDryNKv%m+UJ?h{P`D2jcX_7-0n(NEA&99<-H&m1T*j$cX0N+%-IKygWyr&e zKho3Ks^6RCyG{OXwAtvpdO^SMI{214fT`k!zyu}+G3Wsz?abtG zh!?gb&~JZgHR#K1U|};x)yoba?fUi}XcFB3^?YSue^s)((4h10s0&i2bDjyYS$ap< z+y2g2EVt!2g4e@+$_fVq=26}LZV6LnE*p=xU>&+a1h!A~ts*4}XTd7q8I)yU3r*b> zXfB)5rSh$I=x+G-RU81cR$1CFzq7VBZD8$Z_x+1C8_KYjxbAUY_F&~J&uN!W=i=Im z3^S_TR)pnZPOdRW6I!~O+jixyxO*~GPES&)$#r0qVo^P76&)AO&RUKPQx$OIgo~Hn zLb!C2j18yOx^;)Y1x8R{W8i=7Y=0r2YGkx+O7F&#TX!_v&-DVvv2=OdSI4~dU=3*W zz*WbhPdRZij?VAQG`Y;+o^sTB5nJMNsUemoLh9C=8uK?yUrv_cTyn*GRjt(Q2wiAa z!eVGogq!_^5MbGU+9>e=U5LX@g4ELU_rAxIyEn0}R<;ww1n!1c$8F!!2{^jh%Tm%U2 z3P)dm-YML$w0};!{qFtUL098LI#`tu7kbX|xB{NvR<^_b5tO_P$x*O~8;!RNY$77h z9#}LX^8l}wa8v5lqW`e|Q0d!-STIN|+dFl*T7>`SMl<>t@36i*1Glvd6i{oYW>Em~vvj8l(4j7x(m1a*==C>Xw23Xi%4N z%}9Hi;;>ldmtIQ51%Y#O*e$%%CB%atH9swWXaWO7GyZEhjDn2d?@{iGw#Po*=wO3l zi8kQCiEM~_3;xJ;F{COv6-dO~s6mZHc`!Rjh>9~#T2CJrSzkH{*v{C~| zu(XKlhgfT?J2S-RN;zQ?ed1l_hr1A`)3TFY_fx)JKID+oX<}nJ)?lJmi&t@=GMayA- zWZzP3iJm9Mnho%QYVd{A-QsYB16!mrge%<$qV`}PP-Usd)CHalhlvDqQ1P2}7S4w+ZT5sL%v zVqkyTW(=mGA;f)CTUeV{Mu<@4h0x@IkHxhb8A8c!Se<(nt^v+nPZNl5x8?}3)?mjF1l0!cY6(?N0twm!x@U}~7rJ@lLCp6MpHsH$4Odlvmosx9B}(~A`x&prXK z1{RDt0XgxGD|{h5Qp0Z&{cL&k)_75IRKzC2{zXC^4F9^Ev8*-VI0`Tup6>y&p;h|} z?_U&uvXJ|nF`z=>)yZ{>Dmo=<0hrAZ%S@!Y!}hmORDK#GAJ!@^We(jAn==9?V#Kl*TcLP4}M0dPuoA!_;v zQF;sK(80yKOaf<=8r)60I8{NBG4s#pr2p_QaE!fSZHgJ``qkyPtNp&rd4q?A@BW)b z_MZ)(z!Ix=@;gvn|2}zf{-2ZAe`3|MI2?e@@~i?6j;+!Sq$mQut+6i&0&0c<7B*8V z>8&B|B>k!8oXbG=F7j@~-yR8rmx~y(taT2@8mV0o&uRW+?&;R&js`%L&nMKMp6E!n zBcq2qHRSIM`v^)cjUntfny!?3T-@F}hOVUg{*5#2Z&-XZT~;S+oTOcA77B+~Zzw>m z5%C#ZlEYW%SW1Qh;I; z{U&W{+WA?adfAGcP9^VJZfQCD{2$o$nF8>>4oe}rW5gAnp9wmpdChJJ|r z&UmlEyS0Z2^?JsiaZU#x>KU(uz#KrGW?`YKQ|S?{zZl^cMWWQovA@+Dr+XisiRT0N z%@A`gn;Bw&gjGg*ajMn$f#JSLbq!{8QibO%eV@jcpZG=Cc#2!}R*isvtFcC5(Q3h& znbu`^(=_4|n0>qe$8w@}1Eq!5gsXbJf+m!-p8f;hdgnt4ZHta(m(cleQW(H&H5g29 zUZvZlz3G5B%{9ww7&AzM5xK+P@20)PWs{I=cir0JQk&y|Afiy1j}>DJPp6~v>`%g0 z^4aR8g|F01bG!+LLk#B8^W3@zv*p$o@sAaPpBk65miY zkwIz?dJE4hen;K*lk{@RrDSOkzTlwk}~6yMYWy z79}NEr|>3Jsy=w~_kV}H2L_AO!0oI+*sq2<2{MmS&G_#b z5UGej&<0H4P6Rwq-VPbyIIoKGF9Bz~_BR^Bz%CJquOa#d7Fa^TADHG}621kJB00Zn zRm7F!v^9?A-a9|xJ02Bb2)_lZOjaKWVi-2KMS&Lblwyxd$ zcf^3NH+IR89t4x1ha$HLN;~j-*o^@I!>yb2&^qi!FrA^0 zm_YQ@S*d?48)+wbL7p4^P|mQOIL&rcFG?Au{SpSUw3y_OCz?_D!AX)v(hR$gcxU+$ zU9`A8w8A2NK`Qjzq^s^%=86O-Oq-cj z;#|cQy%g65%vxPUYhEQ50z)$A!$wJCLqS@Q{pJGI=7E}}xi-kMDyz%tY2UPn{mC|q>F8dz+ z*+pL#wqZqeZj7|BytiFb5BLmy3>M);)vD?OsqR9?s0x_11acrvL$$&(nU#S8L-tb( zxjqdc*;J3_nFF7bT&$(6`1`yiixL=Dssr`CAU?%a(W2LRDSl(4!=Rptmay%#vQvHz zER@rnYi2zl|Fou>Jy!;8$-KYj3bMAT7@CVn>r+h)MuHJnvxlOKM_*H@&xEu2W`K6# zZ^`7!pO${hv^t|UKYD+8@%gX*Wa$Cga)aZ>`?efU`H{2Oo3b4etGNcO-8@ZQBMeC1 zT4^y2zkp7-r%-V*Gdj4dy{yQ0I3hin-uIVZ!mfq@c_Xiq9dfS;q$TZ`bK@r7#k_U6 zC;e`J`I}OIaN#$E?1)S32j;()!rOYpjE!1wb2xgt$Cj>y&VLP*d(~bvdpXHmwj=0N zLcAPyqmx{<6(=h8T>eg|^LP@cX0>}n^TYjxL^Eh}HLsmC_~I=3=NR%>{eU4{`wTyL)ph*wIN}+ftZPI7sr^ci{N}2_BxNs zlU@~d%c*#(xu?&ySq}XjQ^hcjk$C#^ajT&N7CBA7azyyD;PtLo$5|?_A7Ls9ceTGwLcB}>6Z^23+l&LUI_PAueyw_(k7`mBV7Av zPT@w0ra2x_I-{C8t43Lx7C^E{D0@|hRtA1vd8~%$(9ig|7{uZd>1S1=9%=m38RFKa zc0aO<>lS8&9IJMR9kh#ZIo1Zt7=~nQRO;1r2`OXk)s<^HDNLc;y&!wlbav?j{BYrP zjC7Fe3L$V0lz5Lp6itU)XkV{>Eq~*>Z5A-taVDBBGmIJi8E#3`j8e`f-svQvvij?GS~pLej4G&dcW zL1^L+YJ}S+-UI}Eox>5=c}c)ukKsI9C5mll=sp3|thsj@9Ap8y>|G(Pm%9Czxm%T- zDPzW)1Xi1NAnR^e&*L|hVPB%!8h$%D;im1}!_e{~ESI6uuadq`E|7IWMG$5>S=SuV z7}$#w$lErg+v-U-6=V!=YBd=*c_>jR!hNNYqg|Z)t^r0Lja*uv`wh>)Q9p)zfB#oX z05N$OYI2;7^b=j&^sPX@$KaPlbJMGs(sbSfO7Fwh2Tw`lTCPax8JZ?C8*DDO?b=sqIq62IyK)Sh$VGMikz)*T{h>nfKdOf7)tPz90&D z@_tsPR@^$(<5bl0rzQoMABXlpJ~>w=d-!J5@y@(7*Ss`a)O;i2*vcgz5{2R~$oTq1 zY{n_S2sDk2!Oj{{EZ&1#0*NpK(GP$6m;}A@M4Aau_&x|!fr5J+7m*M01mSla&OQOI zQC*SfE1zt7htlo;?WIA54cMk=ARt3@|0l@!Glvbx)PQ$WUToC;anA(=f>XqS1n`j| zj~d2<2>af!h$<&QFu??exJk&x`;E$^q=G1vrNFU}o zK2`1smV4zB-jCzKye;9II`-%LdBA$Ws<}^=iFAWQ9J6T77c;+7Jx@V&z0Z314Dl+1 z5iZH2(+~94rYAQYH4TrHdAwya8=d#|Y8nEtI>9kT9H2!>JC_+e*{3!f-ocK9!@VlQ z1<>vCDhbq!$~W4$5M}o}9w_D9YG-0OHV)l8X^!2q>*m-;$&I_^$~AUKgko8Ch!)=u z!bv-~{V~D1Z^c_abE;+19&+^3rdH*aH%WRoE0*B?D}a6CMOq!Z^&9VRhWNQ#Vaz#z z-6r;m4z+b{*i!Ub+G~TRd)dOPR89?M-&vca^KmcS_W=y=@6kTh>M~TOrhEPa$E#bt z`msZ1^9?3XddK4MWFG9tY+n6frGO1^)FmoFX27TdCZy6#XC!j40%tx&CG%E~Vgn}z zs^8iYApabE{WEXVIw9Uap#MZ-%Km!bWHCqrHN6)KD4ExpNgZ zZDUAJYbDb4cWwV+YJJ2-HYw|dsxhm23k#ZcxkW@818I2~H%5ijg|#u0)#}(!ZLlmz z6B>+F72*x+Mv95S0sIx7=4_)djKUA{NfWb7T*R^K zfgIi~qCh+)0e#yhQ&BHTsp>!}GDbnq*wJ}f>6D{HD*~&*IV**5fOHz*m)(dZ(F<%Z zk`+kixGSgDsP6#LQF4Jor7u-o|85v-LLV%Ec@lRHZyw4Rxy7y04xR<-O4n~DoMK;% z{yL}2H_!xqvTsd7xM>^%iM!W)q^2QM`CVvpgzDdTR9tU*vp+t9uXY!*P~c(s*t%J zQSPDGv#6;a9o5DZ6Ky-xh~(i!qG2$c3OGW9*$84=IfgkJ_rV5eRE09kE46H2L|j=h z4{jq_FbvvPc zsDEXWmS!#VJuM@tF?T+e!D%gco_W8;<7#FYxX<(4B!Pn3R6=3xtwVuPmzFr3DZB<+ z!N)~4FnTJ{WN{AQU_#wc0@fz{s59=tWd5Nt;@0fa*c2{5goxH4Ga1^VN=wW#{R|o$ zF=k{ao#{#e?B7@@o;p#cJ2P>t$Bd9o=XIo-e~8Z&%E5sAHFcE={^NLj%rUs$;m>Tm zQSC4F14^F>#WH#vfqtREAY0UvOJQN#NT=WF3jMIrF}MSOJVhKFC+tn@8KJiM9L5=I zs7)bPmMHl<-9^mni}3!Uq*eWh87`X{ASlorZn?OY!<ryeBm9 zuI3%(PHY|h6&CWQ_A{{bd?jBYfKAC7N zG0w&%tC~KZKP$1Y)1UXS(yM`w&?xcUvEqyj7~Sy%yb1(dV~g1_Cukytey5<@si7(^y`uhdz91?X36B;PdU81Hs^Eidcj7B`hBKs(OCkCIQ9G0X z!I6~ONK=IIW+TS|kRo+lo6>!Ddz-JBe&$cb-QtMQ;qv!l%&u;BJSU?DEw34$cD)!c zY{`YYJKjh6;;*Ntgo=!x9jDQQmC-`Tuut|Kb~zQ(JS8d`f*vyrfPl6m(_E}E{%TzG zi+DJ*{hhWNC%aTZGVr#ZUzi^|Y*ht-2dBdPFSela6Sk$-p_tUmewx7GE-55$?5x59 zOr#~SM`b2^W9SAGE5=K@zg%t@EgLpNcom!Wk2wKtvxKUGV#x_SnA@*}CeNy^o#OkW z>qZJ;A{y;NThuO2sk!P{LUTGK>dYe+Umdb+8MBj@dm9_-%S-BHc@a{oTuFNXa*C7r zrkY-T_^*k}_1jDnBjFSrjn3r>f+5FWOZ6dG2+iv4hdMn`43#Lv)plEHRU}fBKjvAe zm%TJs-NRUaxYTZ>br!WffawspXBTM#{RN36H#emTRESqi1{EF=N~+f}l}6Cm?t?4r zv^sQxXc1zuVL3(nB%zOfj2&3AIXlEaA(nY0zOv0qh84UU>lv6q* zqeGnZ1ujL}sWjiqOL&9;y2EEQ8UoTnN2K=)-NYEhZLS9%elK z3>}J54vk*H0TiE=qdzayu9;8wpuNUvoncQK+w5f9!?^|77nYy`Xa-+{)s*MMI%T0T z4VlEFkaV`6kcO^^BhM!@n_6b(mpF`%#mtWo;XNvcSE`*h(?zM+gsc4I7mhLb2lG~U zS-tbs|A5mPSb9$KFb$6HDtO5Gs3fGcT7PhsFI=R{lbVxHHyG1#Co-d%%;A!23*^b!VBjPzn ziTZ{;g74Atvo#K#KR?Z|pnPt^DgH7@XKimlZmWB@&#>LHOokk_qIGF)~MaYH8 zD5qn__ju6&FTVP`kRxb{EN!~1Xho3iD7I*hS>*vY1|2!=hB~~3- z1}Ah4iCR@r4Sas-%Lg>b)AoiaAE>ft8c||J=*&E(n4ItNH*#4Lye%nt+EVse;yN1= zyzbc1bG zL&Wo!-0}a=-uWeJY>fKVPAy-yB!Q>)9$=l~u~sZaLahB+K|eV%q0E&|&L1dF2}Gs@ zgD_iXEXva!g=}o{)TFBC=X2(B0y>vMGCx6=JkYu=U%5S?_>mLud20rkB_9b~S&(Nv zA>MWYOFiAcZ3xAaCUVD{s2WG2I{PHZJDvI2pz z+G)d=B9H?A$pEPhovCqvU|`RvzH!`RKpg)`nGV^W+ZtRe>yO{rkki$XyC>SXu5w9x zhtWzbEQRH6vg`&vx=}XT>wSdyki=x&My|b)lK4b)dxHT>5K1Sp&f_p3b)?|&kOm_ng zNW0VeY-lL$NS=c9S^`r|W(S2l_c-kc4#((vnsrFY%bp53{aIqKMq{}E(vSAUMcWxD z)WMMsA2bP9qaYC)*-bNgV8EmiHnC*&v-RHwM6&ao^sk1WB#M_lzC|zIayawik9sbF zRLC;&IDFn`3f>hWT(lfBD5>bL&RvT~g_vgdGK}jYgU3xiL%Shf*)8etqK`jDM7XU}g(# zQTz?4_?jpZSElGqiV!pF+HS3#wDM5yK;GV2UAHr;z}=)`B~mv^FzH`Z*svGk0Jvn~ z_Em|UMHqN=b9}M1E8#S$q)p^XIg*Eekf2YFfwS*0$=jrX0>U$1GSnKy%^+dhyIvmY z$1|?4+HXY5v(K$jTe~_BKewd>57bVEKX^U^<^846wvh4+xM=l$FN35|8aa}_Gkd^y zuuF7jc8S=M^KBQKgS1mKzw-t@0iGAa7iS)6`ZlH6jYJZl>kuJ*@Z=TE?Ga{Hpjy5J zIwNY?cS?pRN`U5mTi;+`m{)C|R3A}6F|?OgjW<{}yIHF)=(Q~|n~Mv`w^Auq$uw>= zYkok|-2E|#iq;Y%lgYgs`QSc(LE%rv@vyh!WV2joodtQdo>Y@gPsvwHzyX7HeO*ON zQxP^58^1!zf*Tc4(FVxW$I&Aw_l0J`F<9LPOjaXQPod(R>VqE@nIlC3)=V`h(HByV zJMpjkY#PWf_{4QvGj8vkj#`K{h(9);KR)rFj>H8)-?-=iQO*S(*Zoak*yAUHJ><|E zLDQM1In^hCfTiF!WRN;>z-cpVtaXU7(K7YeIXHDvOWEe{t1#r*s$X%QE>Ys7<+$#N^~W)a67=)4BD?*tX%ZZhKAa%$Lq3`t6osaY z&P&i3F9rM01>wqc?TNZqztBLp;1LKI7umqJ1!v9PSV=xb(&Pbt0BeD~@e^AbvVU@( zOs))(4)Cn}Q(Vj|zo++0B!%D25^%&9nbQLhP|T)<0M-63*cV=f{w|zIfv9vozJ5nP+j>m<7WZ6+A<1l7RV=6C|KHXZQqyCRJez!qv#Cp<}!!?sl=Lu@<1}jVFZPOr9$MM^Y9ghA3r#is9Od@IL znHB`2ME{#hy-7rI$5Fg-%ieOU)?r_qhmj1lmRtlW;MiC%V%QdJ__?6%$h}G3*}dEt zXh9T75P?fYO0{=Rdu{;iu3p6l#THs0VPes7AKZ4BKh*8tfC=1ZS2f|lRn%rPa?k-H zfOlbwl(h6QEhMcgn6u>IaR5AHJqM(I=0z|(Z^ztCzizc%f0j}`t3kPXE+!E$5=joK zKrvMi?xp}o4{I1G`g*ds~)d09fZE_Da_jHu6 z%w8vp=U=({dzCNMr!Iqq_!A80|Kv#A65H3GNQwREq#gz*gqyx2&UCp2E-Z>_liF)5Rk=TndxTrg?tWuzJu&_btZ zilBr07M%a5v8#ZJs*Bc$G(+c50@5Mff`pU^h;)}TbR&(!pdt!Lj5LxmNJt1GEieov zASoqMk`kf_h=T79|L-rO>%H~PT6f)h)8nZ>NzEQ+C z%mq_Q-g3Bk_!`hFvF&Un#>eIi#VJob#(wZibjMT+JcqMiSz6iUw?iqV~}X>)uqp zj7Z}tVF>>MZ*(UU&G|DlAcCJ{n`SBQftfSt)q(@O z75ugoR|fjFFI~EI=IO#DdwK379!F%Nig}bDztM2oy+V5qGBSuu$*>U8+cevH*xMF$ zHcECs6IA~~@i@_vJTMdX7P>m^>6dQb>UOVoC8^q>F`%wj)N(^{Jd@u;jLX$VP4vdN zyJ^|>%YZvSQ?_MQ13s_6n_OrSUgS$B3fzoPnY~7)0O1Q;YG|*JyGVq$Y2lVVTa%&W zCEH%2P;30fLU>F1MvTlmiaWNlalB{Jkwmr=D%0~h%kelmB zl9IbGcL#4otote7YrCw^-^f8Ubp(9+wf4P;IEN1-9+y3oo-)GB#9p0G)M2xqBSqd) zomSGg5_S8LQwEbku-*n8LgyyIYk#T5WqYE=cqnZGJZWGhY!GHkECH_#9kb z1v|9|{hD)RNt*3>=}YyF9pnvj8IhTf&+|$Qin8`Aqhd4QyPkOwb&2gB@7C-!78=rB zoYHhlhsF8?EIXbEG$b+3Y$;l)Gs(EzO*|yUJ_QKkSunB#;*~Rz;@~JCKu{)x+G{Qt z;Fuc7WK4TZ4!SCyz8sk+#q&%XM2AcEtky+X^2*4lU5|S4eHX!i2;y{Fs5dnF^3U7b zmq(}@d(>CjZby7<2e4}hpPLbIs{8WfXQA<#%c*iFU&8yH9 z%)Y=e`%|l9oYNO{`~>N?M}1p{WzvB%B`&{LG-=5HX0u68>2f%?Esr+4BkiNlDGsh- z@2N@lvY}#DZy2HcHsZ++=5Y+Y78jFWx*PIOWFifWbuA5_K?<%L>~hL9x~~#)!HoLx zP-fbSCi3r|PG#gt#NIof9=@b}Kb5YT_RSO$nW}ZOy)Z=c1>LhUdN4Ai%pBj)&74Ju z@vz*aBppwVR*AUw>=e?$;!X_Be1*JY)a3X_MD398SAk6)@nL#WT@psm#z9%07}iE= zU2)f1lZO@jW0ya4WQm(f@evE@YQsYE**y7|G8(Q|WRyVU5^$R*cAfn?{O=V@a$l|@ zV~d>tb*@vzF|*z_@^DH&mxWjz2soF8THl$kfBP)MALXx;Quiu3M8$)Xc83fiQ=06L z4tV~3k@?GH(R4R|TlpSY_hfzItSM;#=K{S!?|N#mU!g+5=F$Spy4}W9Bp6oW&9Yam z(J%BgP%69K8O9I}pH2dT=P_#NPbKeMKtlTLEIJ&)+iFyasRqghokF$-Rf72)rhAv2 z#rJkDUpCjkZy-|BpquR#ZL4S%21~nw5_}@IZ;bkMXKsTB{LzBvBZKAPMFN(zd(5Jn zZ?^`oq!(HMTL*jhp=r0QU%>KwnQyHQ=sn2+UQ1o<8Z&)wSmtPUdCjU$1cj<8E&XsI z>L+h>`N#HzjjmcZ+i4W~ShBcsuyn!5aDjtzs|*L+zhLTFXW1^A`=W#|xw)K-bxdk5 z<$4eI@!PS6&5J0CRr|5W+WUqRE$jJ6hOxuW3u=`NbS}qSqt4&sDnns`IcVr$$&Q-t zUJ&1!{~KO8#w~6J=;}|j+^2Y=PA|n5+k--SiZi+g%Q?4?RL@fI6n|A{XGgYfKP!m% zQinr?D?+AsX=L3gSYLkIz8q3>Wy)q8_-z9RialeG->Tgo9Jqsu1 zSfyc;`DEg@w#`uG^r7uzZj17x$O$4U8q$vTdmU;IK5bGy*Sr&>39GyuO;1_q6+3v> zn=aM)f*oj|4?p$sf$!#l@2=OEv-iHTm^WV8v36U5>(FcaKJLWT_MAI^?^R|2|L5df zsujCrA>Yj5Fv&gYMKZjcuYDc}^Wsf&)#pp*?ZT=vYh5Fscg2)^4o6RgQp8M|h{sKI zO~4|Ly?UbY%jx%_YFjJ)(twN-f`6S^*kGG_GzOH4FRdFk1FGoqZp{%oP&Lq!NOc#H zP>XSqWsFL;!Cr1!FuZJB-g+CaxkLP8kwW)!9G6lA1tiNd#bP)^eIaLHpfBAI8MwT4 z{Nw8pVMK5lZ$bwdnf&w5E~*7NnM^!lg&c%x=o$h#VE?k+%HpiYZRuF z;wT=QYBj_siB~ZV&4XIr?Xn7jhJT@eCUY!bdfBvLbq_qCp9!1q7zav!lj?G6Bo$J-pHd~|PG=Da5O{asO0 z%cd-HqNaW&{f;I1rucNu{bRR=o>>!^?&mwOXnV$Vfz2J$COf|(1HSL=zD%X{MIeI< zOwZ@Dx#Bu*23V~`vj>+=em`1mS5SJ7GzqZGhkBZS4iZ;fH80LRf4Amgwb`Ipw1m8; zqY*m)A-7Pe*-+I3si?cxmg1aR_-lpczb%^*G6lF>jp*X zUo84}n>N~6tl!Y`2RnMX^K7*NXz3@KC;JxWB~(MfLn^ z&hb&s&sVwysW`7ldtBYV4c-vs)VKvZH>9s3{50jW5Jg-+I~ppcS_N8q8nvOGd&DKh z*%3@!aOMliH)=WwcGY)azi_zTVI^lJxR*b{6u+SBA$R0)ics}0dFuLGec!hi|)A5X)% zerCj0I5liS>$b8DkxHpDB`H+`^?i>=(i1Or%|^yvcWw(rf*j?9jdAuiIWCI8S_RJI(tZ=R<8Y82wnlU}}1Z z(3}O1PTj!H{WKxJGNK7Gu(*lbTY|~~AHz-prDQQ!wC=;KSjt-2&nz#&hnw49L;R!c zg`6ysjnLNvOD#&Q#thA?O$_5^vOJw%8kd%vgH=V=qdY~#%Jf4}wwkibGtyR2*G!e( zj7BCD*nYxw^h(A}O=066>fUt7i-ufN$U%0@V>(P2leCL!Kqep`2qf|!tCQ2YH=O!Cmyu$`WKRlc3V|w{ z5alroe@%HwzV*4W%cvyECj9!_jGSZD5y+Et`W}IKPR{{#p3aXnBcQh1Kl)PHoFSQu z3NUiq58Ml)@*`{K33gd zjAWD!6;N%q5il1{eG#H4FQb&Fwi$uF;kOu51QD>4XdomA+{`G=x{2LG8G=F0=2{9^ zF{6H^;;sk!7JM6gNb{yG{NU_a(&6Y`-r@3ZqxwL2whNsuOwm*}!42_k4y!f03Inu9 zJ?#>B`=YzP=koF=5?K;$IA(*V@ckdXIY8KNH zMSPXoLo6ddk>bn-dlVjP_@fWn4ouf6VO-`7!F3m(X^r}63J2txyz)lTKNb~Z7$!l9 z>8wjQ`S%Rz#9ml*TnV-E39~}q8?8tPa9WcK%N83Zv6;)^(J4WyX&E2Tk5Z5B)5t z|MJ~C@2allm4+lnPo)23FD#XBAyP}Fu$)nj%SxnHo4rZUvf>}PW7eHlp76oAXn6Wg zyII&;qkHk{s^JIxq)MA@Sayug{DJDjESo16X-h|NWsNVJKihJ~CKhy>wTs@0V` zd_0F_?~D8%^zk>=JqEikCy;)yXRqjPc|87R*pK9cQMZCz%^+9AwNjBNdFPKF%sDwU zB|m9&D?{7vGSzJ>HXp>Lr=@uEQIMKP8pCL$_bhcuLxVR8ob%KtEMZ8+t*zOJhleX$ z?3_(zw?5x_hVGx?OL4y)${6G9jTG^QP(_;0zY;uqWG1>x6hs_2;cNC;BjNqgnMGzn z0{3HR4WhTZDqA1dtQ?m|LPd-~pz5mfR2IZ}70UmWb$Q%UG*hfkgF30TV~S}D&gjib z;V^fPPtEqB=J-ZNRsYp(52%7+A0J%Exw~I`K_{j2$+PqipJ{V;rE(;*bE%6I;}&0f zr$WH|O2zi*8o7d~??UIQFLQinz@9BMYKit05v+mQuPER&$6?>e*`w5{`lBU>sp*CyqqUx^h(vkov{pt;TS*A0wx&fW;C8A9`RLz? z{*KE=qy-Zl&GZ^oW$zt)JRE1m<mx-`J4;MnNv4&vQ0Ysj;Rm z(Xo&2#}#+EZG@|0_JzfQk`7DS2ix(#STYMf*fFx{L3HE{SNq=5mNse;AyIs19aY=m zW+=vETwn*SHF=N#8jeNsYlw?5kdT_RDohboj%V$M#Y$;=R+8lbYewrgWwheV$tC6*WCgLfr_+;;+bc% z*@$7cvJi7>r4gFcJYw8-7VRK534b}rZTr5VM5n0+q?cRQBV{M<B8_YD*&+}N~ijy2ZeF#@w+OkqNj%k(7 zmq%2a7hWTZ)hNDl&(%3rsZrwPRjG672$^rNQCZGh@&SGxHT|^&t%@>!bHAVN#agYn zaV6*TnlE`aWvM8n45V9R2G$}COa-U54MExKbT<7>vR{u)*V}nj)ESPJELRmUY^5nv-&W7uQO~!^hg(PdGQMD! z-ukMc^N%NX=st4C@|Am&s>F5PI2UrQ;^)%P_|KloF{n=Ty1u$A7D0NMm+x%yo^KO=C6U;8@(#}ZcDjWf8kXa5cmUoBE4?mS-cyx{ zR~#~91&B5PL<|3t3*2kqcK86E8S&~I?O*z`ELcyY0r#9kpxGs`hzN;JgvfVtW3`xf z4@Lu4@{`O`bEdyI8icdDECDKj0gj?r9KTVX5WO~HMcDP=pH{svShT?e)6Re<=dfsm z=uc=ac2k|k5BPq3KnHl%dy?be@L=IzF`nSJyBSa8W#8A%Fau_=!4EuXMVAQs-w_ynJ$iwP0PdRhinct9+gaMKf-STxOP{D1L(04#R* z7_&vdAlz6+fms0l8N}z8j2bx94q-jYBJjK0W8j!_u_ERCk^Q??5CtIEq+!YG(k?4}>LQK8;^JPxe_8SQzU7Wf8-|AG-p07DUBsmecs(0VDq8 z|H%DBpOyiR(|9a@Q!M_q{s3MM;WhAIH^Y<{$2?5EC!1N=I#b~Skgi-Pk{b~Hk6AEBBy};^50Sm9*bb^QV<0JF} p=@6p*SbYL}1@@b;20r}?SdX2j#RnX~F \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec9973..f955316 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,84 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/js-app/build.gradle b/js-app/build.gradle new file mode 100644 index 0000000..8ce794d --- /dev/null +++ b/js-app/build.gradle @@ -0,0 +1,48 @@ +import com.google.javascript.jscomp.CompilerOptions + +apply plugin: 'kotlin2js' +apply plugin: 'kotlin-dce-js' +apply plugin: "com.eriwen.gradle.js" + +dependencies { + compile project(':js') + compile libraries.kotlin_stdlib_js +} + +[compileKotlin2Js, compileTestKotlin2Js]*.configure { + kotlinOptions.moduleKind = "umd" + kotlinOptions.sourceMap = true + kotlinOptions.sourceMapEmbedSources = "always" +} + +combineJs { + source = [ + // The order is important. That's why the documented way with a reference to a source set using wildcards + // is not used. + + ] + dest = file("${temporaryDir}/${archivesBaseName}-combined.js") +} + +minifyJs { + source = combineJs + dest = file("${temporaryDir}/${archivesBaseName}-minified.js") + closure { + compilerOptions = new CompilerOptions().with { + setLanguage(CompilerOptions.LanguageMode.ECMASCRIPT5) + return it + } + } +} + +combineJs.dependsOn runDceKotlinJs +build.dependsOn minifyJs + +task minifiedJar(type: Jar) { + classifier = 'minified' + from minifyJs +} + +artifacts { + archives minifiedJar +} diff --git a/js-app/src/main/kotlin/js/JsApp.kt b/js-app/src/main/kotlin/js/JsApp.kt new file mode 100644 index 0000000..35deda5 --- /dev/null +++ b/js-app/src/main/kotlin/js/JsApp.kt @@ -0,0 +1,5 @@ +package js + +fun main(arguments: Array) { + +} diff --git a/js/build.gradle b/js/build.gradle new file mode 100644 index 0000000..5a123f6 --- /dev/null +++ b/js/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'kotlin-platform-js' +apply plugin: 'com.moowork.node' + +archivesBaseName = 'actions-on-google-js' + +dependencies { + expectedBy project(':common') + compile libraries.kotlin_stdlib_js + testCompile libraries.kotlin_test_js +} + +[compileKotlin2Js, compileTestKotlin2Js]*.configure { + kotlinOptions.moduleKind = "umd" + kotlinOptions.sourceMap = true + kotlinOptions.sourceMapEmbedSources = "always" +} + +task populateNodeModules(type: Copy, dependsOn: compileKotlin2Js) { + from compileKotlin2Js.destinationDir + + configurations.testCompile.each { + from zipTree(it.absolutePath).matching { include '*.js' } + } + + into "${buildDir}/node_modules" +} + +node { + version = nodeVersion + download = true +} + +task installQunit(type: NpmTask) { + inputs.property('qunitVersion', qunitVersion) + outputs.dir file('node_modules/qunit') + + args = ['install', "qunit@${qunitVersion}"] +} + +task runQunit(type: NodeTask, dependsOn: [compileTestKotlin2Js, populateNodeModules, installQunit]) { + script = file('node_modules/qunit/bin/qunit') + args = [projectDir.toPath().relativize(file(compileTestKotlin2Js.outputFile).toPath())] +} + +test.dependsOn runQunit + +task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.kotlin +} + +artifacts { + archives sourcesJar +} diff --git a/js/node_modules/.bin/atob b/js/node_modules/.bin/atob new file mode 120000 index 0000000..a68344a --- /dev/null +++ b/js/node_modules/.bin/atob @@ -0,0 +1 @@ +../atob/bin/atob.js \ No newline at end of file diff --git a/js/node_modules/.bin/qunit b/js/node_modules/.bin/qunit new file mode 120000 index 0000000..0981fc3 --- /dev/null +++ b/js/node_modules/.bin/qunit @@ -0,0 +1 @@ +../qunit/bin/qunit \ No newline at end of file diff --git a/js/node_modules/.bin/which b/js/node_modules/.bin/which new file mode 120000 index 0000000..f62471c --- /dev/null +++ b/js/node_modules/.bin/which @@ -0,0 +1 @@ +../which/bin/which \ No newline at end of file diff --git a/js/node_modules/anymatch/LICENSE b/js/node_modules/anymatch/LICENSE new file mode 100644 index 0000000..bc42470 --- /dev/null +++ b/js/node_modules/anymatch/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2014 Elan Shanker + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/anymatch/README.md b/js/node_modules/anymatch/README.md new file mode 100644 index 0000000..62f65da --- /dev/null +++ b/js/node_modules/anymatch/README.md @@ -0,0 +1,98 @@ +anymatch [![Build Status](https://travis-ci.org/es128/anymatch.svg?branch=master)](https://travis-ci.org/es128/anymatch) [![Coverage Status](https://img.shields.io/coveralls/es128/anymatch.svg?branch=master)](https://coveralls.io/r/es128/anymatch?branch=master) +====== +Javascript module to match a string against a regular expression, glob, string, +or function that takes the string as an argument and returns a truthy or falsy +value. The matcher can also be an array of any or all of these. Useful for +allowing a very flexible user-defined config to define things like file paths. + +[![NPM](https://nodei.co/npm/anymatch.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/anymatch/) +[![NPM](https://nodei.co/npm-dl/anymatch.png?height=3&months=9)](https://nodei.co/npm-dl/anymatch/) + +Usage +----- +```sh +npm install anymatch --save +``` + +#### anymatch (matchers, testString, [returnIndex], [startIndex], [endIndex]) +* __matchers__: (_Array|String|RegExp|Function_) +String to be directly matched, string with glob patterns, regular expression +test, function that takes the testString as an argument and returns a truthy +value if it should be matched, or an array of any number and mix of these types. +* __testString__: (_String|Array_) The string to test against the matchers. If +passed as an array, the first element of the array will be used as the +`testString` for non-function matchers, while the entire array will be applied +as the arguments for function matchers. +* __returnIndex__: (_Boolean [optional]_) If true, return the array index of +the first matcher that that testString matched, or -1 if no match, instead of a +boolean result. +* __startIndex, endIndex__: (_Integer [optional]_) Can be used to define a +subset out of the array of provided matchers to test against. Can be useful +with bound matcher functions (see below). When used with `returnIndex = true` +preserves original indexing. Behaves the same as `Array.prototype.slice` (i.e. +includes array members up to, but not including endIndex). + +```js +var anymatch = require('anymatch'); + +var matchers = [ + 'path/to/file.js', + 'path/anyjs/**/*.js', + /foo\.js$/, + function (string) { + return string.indexOf('bar') !== -1 && string.length > 10 + } +]; + +anymatch(matchers, 'path/to/file.js'); // true +anymatch(matchers, 'path/anyjs/baz.js'); // true +anymatch(matchers, 'path/to/foo.js'); // true +anymatch(matchers, 'path/to/bar.js'); // true +anymatch(matchers, 'bar.js'); // false + +// returnIndex = true +anymatch(matchers, 'foo.js', true); // 2 +anymatch(matchers, 'path/anyjs/foo.js', true); // 1 + +// skip matchers +anymatch(matchers, 'path/to/file.js', false, 1); // false +anymatch(matchers, 'path/anyjs/foo.js', true, 2, 3); // 2 +anymatch(matchers, 'path/to/bar.js', true, 0, 3); // -1 + +// using globs to match directories and their children +anymatch('node_modules', 'node_modules'); // true +anymatch('node_modules', 'node_modules/somelib/index.js'); // false +anymatch('node_modules/**', 'node_modules/somelib/index.js'); // true +anymatch('node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // false +anymatch('**/node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // true +``` + +#### anymatch (matchers) +You can also pass in only your matcher(s) to get a curried function that has +already been bound to the provided matching criteria. This can be used as an +`Array.prototype.filter` callback. + +```js +var matcher = anymatch(matchers); + +matcher('path/to/file.js'); // true +matcher('path/anyjs/baz.js', true); // 1 +matcher('path/anyjs/baz.js', true, 2); // -1 + +['foo.js', 'bar.js'].filter(matcher); // ['foo.js'] +``` + +Change Log +---------- +[See release notes page on GitHub](https://github.com/es128/anymatch/releases) + +NOTE: As of v1.2.0, anymatch uses [micromatch](https://github.com/jonschlinkert/micromatch) +for glob pattern matching. The glob matching behavior should be functionally +equivalent to the commonly used [minimatch](https://github.com/isaacs/minimatch) +library (aside from some fixed bugs and greater performance), so a major +version bump wasn't merited. Issues with glob pattern matching should be +reported directly to the [micromatch issue tracker](https://github.com/jonschlinkert/micromatch/issues). + +License +------- +[ISC](https://raw.github.com/es128/anymatch/master/LICENSE) diff --git a/js/node_modules/anymatch/index.js b/js/node_modules/anymatch/index.js new file mode 100644 index 0000000..e411618 --- /dev/null +++ b/js/node_modules/anymatch/index.js @@ -0,0 +1,67 @@ +'use strict'; + +var micromatch = require('micromatch'); +var normalize = require('normalize-path'); +var path = require('path'); // required for tests. +var arrify = function(a) { return a == null ? [] : (Array.isArray(a) ? a : [a]); }; + +var anymatch = function(criteria, value, returnIndex, startIndex, endIndex) { + criteria = arrify(criteria); + value = arrify(value); + if (arguments.length === 1) { + return anymatch.bind(null, criteria.map(function(criterion) { + return typeof criterion === 'string' && criterion[0] !== '!' ? + micromatch.matcher(criterion) : criterion; + })); + } + startIndex = startIndex || 0; + var string = value[0]; + var altString, altValue; + var matched = false; + var matchIndex = -1; + function testCriteria(criterion, index) { + var result; + switch (Object.prototype.toString.call(criterion)) { + case '[object String]': + result = string === criterion || altString && altString === criterion; + result = result || micromatch.isMatch(string, criterion); + break; + case '[object RegExp]': + result = criterion.test(string) || altString && criterion.test(altString); + break; + case '[object Function]': + result = criterion.apply(null, value); + result = result || altValue && criterion.apply(null, altValue); + break; + default: + result = false; + } + if (result) { + matchIndex = index + startIndex; + } + return result; + } + var crit = criteria; + var negGlobs = crit.reduce(function(arr, criterion, index) { + if (typeof criterion === 'string' && criterion[0] === '!') { + if (crit === criteria) { + // make a copy before modifying + crit = crit.slice(); + } + crit[index] = null; + arr.push(criterion.substr(1)); + } + return arr; + }, []); + if (!negGlobs.length || !micromatch.any(string, negGlobs)) { + if (path.sep === '\\' && typeof string === 'string') { + altString = normalize(string); + altString = altString === string ? null : altString; + if (altString) altValue = [altString].concat(value.slice(1)); + } + matched = crit.slice(startIndex, endIndex).some(testCriteria); + } + return returnIndex === true ? matchIndex : matched; +}; + +module.exports = anymatch; diff --git a/js/node_modules/anymatch/package.json b/js/node_modules/anymatch/package.json new file mode 100644 index 0000000..9657383 --- /dev/null +++ b/js/node_modules/anymatch/package.json @@ -0,0 +1,72 @@ +{ + "_from": "anymatch@^1.3.0", + "_id": "anymatch@1.3.2", + "_inBundle": false, + "_integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "_location": "/anymatch", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "anymatch@^1.3.0", + "name": "anymatch", + "escapedName": "anymatch", + "rawSpec": "^1.3.0", + "saveSpec": null, + "fetchSpec": "^1.3.0" + }, + "_requiredBy": [ + "/chokidar" + ], + "_resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "_shasum": "553dcb8f91e3c889845dfdba34c77721b90b9d7a", + "_spec": "anymatch@^1.3.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/chokidar", + "author": { + "name": "Elan Shanker", + "url": "http://github.com/es128" + }, + "bugs": { + "url": "https://github.com/es128/anymatch/issues" + }, + "bundleDependencies": false, + "dependencies": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + }, + "deprecated": false, + "description": "Matches strings against configurable strings, globs, regular expressions, and/or functions", + "devDependencies": { + "coveralls": "^2.11.2", + "istanbul": "^0.3.13", + "mocha": "^2.2.4" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/es128/anymatch", + "keywords": [ + "match", + "any", + "string", + "file", + "fs", + "list", + "glob", + "regex", + "regexp", + "regular", + "expression", + "function" + ], + "license": "ISC", + "name": "anymatch", + "repository": { + "type": "git", + "url": "git+https://github.com/es128/anymatch.git" + }, + "scripts": { + "test": "istanbul cover _mocha && cat ./coverage/lcov.info | coveralls" + }, + "version": "1.3.2" +} diff --git a/js/node_modules/arr-diff/LICENSE b/js/node_modules/arr-diff/LICENSE new file mode 100755 index 0000000..fa30c4c --- /dev/null +++ b/js/node_modules/arr-diff/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/arr-diff/README.md b/js/node_modules/arr-diff/README.md new file mode 100644 index 0000000..7705c6c --- /dev/null +++ b/js/node_modules/arr-diff/README.md @@ -0,0 +1,74 @@ +# arr-diff [![NPM version](https://img.shields.io/npm/v/arr-diff.svg)](https://www.npmjs.com/package/arr-diff) [![Build Status](https://img.shields.io/travis/jonschlinkert/base.svg)](https://travis-ci.org/jonschlinkert/base) + +> Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i arr-diff --save +``` +Install with [bower](http://bower.io/) + +```sh +$ bower install arr-diff --save +``` + +## API + +### [diff](index.js#L33) + +Return the difference between the first array and additional arrays. + +**Params** + +* `a` **{Array}** +* `b` **{Array}** +* `returns` **{Array}** + +**Example** + +```js +var diff = require('arr-diff'); + +var a = ['a', 'b', 'c', 'd']; +var b = ['b', 'c']; + +console.log(diff(a, b)) +//=> ['a', 'd'] +``` + +## Related projects + +* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten) +* [array-filter](https://www.npmjs.com/package/array-filter): Array#filter for older browsers. | [homepage](https://github.com/juliangruber/array-filter) +* [array-intersection](https://www.npmjs.com/package/array-intersection): Return an array with the unique values present in _all_ given arrays using strict equality… [more](https://www.npmjs.com/package/array-intersection) | [homepage](https://github.com/jonschlinkert/array-intersection) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/arr-diff/issues/new). + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert) +Released under the MIT license. + +*** + +_This file was generated by [verb](https://github.com/verbose/verb) on Sat Dec 05 2015 23:24:53 GMT-0500 (EST)._ diff --git a/js/node_modules/arr-diff/index.js b/js/node_modules/arr-diff/index.js new file mode 100644 index 0000000..bc7200d --- /dev/null +++ b/js/node_modules/arr-diff/index.js @@ -0,0 +1,58 @@ +/*! + * arr-diff + * + * Copyright (c) 2014 Jon Schlinkert, contributors. + * Licensed under the MIT License + */ + +'use strict'; + +var flatten = require('arr-flatten'); +var slice = [].slice; + +/** + * Return the difference between the first array and + * additional arrays. + * + * ```js + * var diff = require('{%= name %}'); + * + * var a = ['a', 'b', 'c', 'd']; + * var b = ['b', 'c']; + * + * console.log(diff(a, b)) + * //=> ['a', 'd'] + * ``` + * + * @param {Array} `a` + * @param {Array} `b` + * @return {Array} + * @api public + */ + +function diff(arr, arrays) { + var argsLen = arguments.length; + var len = arr.length, i = -1; + var res = [], arrays; + + if (argsLen === 1) { + return arr; + } + + if (argsLen > 2) { + arrays = flatten(slice.call(arguments, 1)); + } + + while (++i < len) { + if (!~arrays.indexOf(arr[i])) { + res.push(arr[i]); + } + } + return res; +} + +/** + * Expose `diff` + */ + +module.exports = diff; diff --git a/js/node_modules/arr-diff/package.json b/js/node_modules/arr-diff/package.json new file mode 100644 index 0000000..e54b7da --- /dev/null +++ b/js/node_modules/arr-diff/package.json @@ -0,0 +1,80 @@ +{ + "_from": "arr-diff@^2.0.0", + "_id": "arr-diff@2.0.0", + "_inBundle": false, + "_integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "_location": "/arr-diff", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "arr-diff@^2.0.0", + "name": "arr-diff", + "escapedName": "arr-diff", + "rawSpec": "^2.0.0", + "saveSpec": null, + "fetchSpec": "^2.0.0" + }, + "_requiredBy": [ + "/micromatch" + ], + "_resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "_shasum": "8f3b827f955a8bd669697e4a4256ac3ceae356cf", + "_spec": "arr-diff@^2.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/micromatch", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/arr-diff/issues" + }, + "bundleDependencies": false, + "dependencies": { + "arr-flatten": "^1.0.1" + }, + "deprecated": false, + "description": "Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.", + "devDependencies": { + "array-differ": "^1.0.0", + "array-slice": "^0.2.3", + "benchmarked": "^0.1.4", + "chalk": "^1.1.1", + "mocha": "*", + "should": "*" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/arr-diff", + "keywords": [ + "arr", + "array", + "diff", + "differ", + "difference" + ], + "license": "MIT", + "main": "index.js", + "name": "arr-diff", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/arr-diff.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "arr-flatten", + "array-filter", + "array-intersection" + ] + } + }, + "version": "2.0.0" +} diff --git a/js/node_modules/arr-flatten/LICENSE b/js/node_modules/arr-flatten/LICENSE new file mode 100755 index 0000000..3f2eca1 --- /dev/null +++ b/js/node_modules/arr-flatten/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/arr-flatten/README.md b/js/node_modules/arr-flatten/README.md new file mode 100755 index 0000000..7dc7a97 --- /dev/null +++ b/js/node_modules/arr-flatten/README.md @@ -0,0 +1,86 @@ +# arr-flatten [![NPM version](https://img.shields.io/npm/v/arr-flatten.svg?style=flat)](https://www.npmjs.com/package/arr-flatten) [![NPM monthly downloads](https://img.shields.io/npm/dm/arr-flatten.svg?style=flat)](https://npmjs.org/package/arr-flatten) [![NPM total downloads](https://img.shields.io/npm/dt/arr-flatten.svg?style=flat)](https://npmjs.org/package/arr-flatten) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/arr-flatten.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/arr-flatten) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/arr-flatten.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/arr-flatten) + +> Recursively flatten an array or arrays. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save arr-flatten +``` + +## Install + +Install with [bower](https://bower.io/) + +```sh +$ bower install arr-flatten --save +``` + +## Usage + +```js +var flatten = require('arr-flatten'); + +flatten(['a', ['b', ['c']], 'd', ['e']]); +//=> ['a', 'b', 'c', 'd', 'e'] +``` + +## Why another flatten utility? + +I wanted the fastest implementation I could find, with implementation choices that should work for 95% of use cases, but no cruft to cover the other 5%. + +## About + +### Related projects + +* [arr-filter](https://www.npmjs.com/package/arr-filter): Faster alternative to javascript's native filter method. | [homepage](https://github.com/jonschlinkert/arr-filter "Faster alternative to javascript's native filter method.") +* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://github.com/jonschlinkert/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.") +* [array-each](https://www.npmjs.com/package/array-each): Loop over each item in an array and call the given function on every element. | [homepage](https://github.com/jonschlinkert/array-each "Loop over each item in an array and call the given function on every element.") +* [array-unique](https://www.npmjs.com/package/array-unique): Remove duplicate values from an array. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique "Remove duplicate values from an array. Fastest ES5 implementation.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 20 | [jonschlinkert](https://github.com/jonschlinkert) | +| 1 | [lukeed](https://github.com/lukeed) | + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 05, 2017._ \ No newline at end of file diff --git a/js/node_modules/arr-flatten/index.js b/js/node_modules/arr-flatten/index.js new file mode 100644 index 0000000..0cb4ea4 --- /dev/null +++ b/js/node_modules/arr-flatten/index.js @@ -0,0 +1,22 @@ +/*! + * arr-flatten + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +module.exports = function (arr) { + return flat(arr, []); +}; + +function flat(arr, res) { + var i = 0, cur; + var len = arr.length; + for (; i < len; i++) { + cur = arr[i]; + Array.isArray(cur) ? flat(cur, res) : res.push(cur); + } + return res; +} diff --git a/js/node_modules/arr-flatten/package.json b/js/node_modules/arr-flatten/package.json new file mode 100644 index 0000000..99fcebc --- /dev/null +++ b/js/node_modules/arr-flatten/package.json @@ -0,0 +1,114 @@ +{ + "_from": "arr-flatten@^1.0.1", + "_id": "arr-flatten@1.1.0", + "_inBundle": false, + "_integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "_location": "/arr-flatten", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "arr-flatten@^1.0.1", + "name": "arr-flatten", + "escapedName": "arr-flatten", + "rawSpec": "^1.0.1", + "saveSpec": null, + "fetchSpec": "^1.0.1" + }, + "_requiredBy": [ + "/arr-diff", + "/findup-sync/braces" + ], + "_resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "_shasum": "36048bbff4e7b47e136644316c99669ea5ae91f1", + "_spec": "arr-flatten@^1.0.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/arr-diff", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/arr-flatten/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Jon Schlinkert", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Luke Edwards", + "url": "https://lukeed.com" + } + ], + "deprecated": false, + "description": "Recursively flatten an array or arrays.", + "devDependencies": { + "ansi-bold": "^0.1.1", + "array-flatten": "^2.1.1", + "array-slice": "^1.0.0", + "benchmarked": "^1.0.0", + "compute-flatten": "^1.0.0", + "flatit": "^1.1.1", + "flatten": "^1.0.2", + "flatten-array": "^1.0.0", + "glob": "^7.1.1", + "gulp-format-md": "^0.1.12", + "just-flatten-it": "^1.1.23", + "lodash.flattendeep": "^4.4.0", + "m_flattened": "^1.0.1", + "mocha": "^3.2.0", + "utils-flatten": "^1.0.0", + "write": "^0.3.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/arr-flatten", + "keywords": [ + "arr", + "array", + "elements", + "flat", + "flatten", + "nested", + "recurse", + "recursive", + "recursively" + ], + "license": "MIT", + "main": "index.js", + "name": "arr-flatten", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/arr-flatten.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "arr-filter", + "arr-union", + "array-each", + "array-unique" + ] + }, + "lint": { + "reflinks": true + } + }, + "version": "1.1.0" +} diff --git a/js/node_modules/arr-union/LICENSE b/js/node_modules/arr-union/LICENSE new file mode 100644 index 0000000..39245ac --- /dev/null +++ b/js/node_modules/arr-union/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/arr-union/README.md b/js/node_modules/arr-union/README.md new file mode 100644 index 0000000..b3cd4f4 --- /dev/null +++ b/js/node_modules/arr-union/README.md @@ -0,0 +1,99 @@ +# arr-union [![NPM version](https://img.shields.io/npm/v/arr-union.svg)](https://www.npmjs.com/package/arr-union) [![Build Status](https://img.shields.io/travis/jonschlinkert/arr-union.svg)](https://travis-ci.org/jonschlinkert/arr-union) + +> Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm i arr-union --save +``` + +## Benchmarks + +This library is **10-20 times faster** and more performant than [array-union](https://github.com/sindresorhus/array-union). + +See the [benchmarks](./benchmark). + +```sh +#1: five-arrays + array-union x 511,121 ops/sec ±0.80% (96 runs sampled) + arr-union x 5,716,039 ops/sec ±0.86% (93 runs sampled) + +#2: ten-arrays + array-union x 245,196 ops/sec ±0.69% (94 runs sampled) + arr-union x 1,850,786 ops/sec ±0.84% (97 runs sampled) + +#3: two-arrays + array-union x 563,869 ops/sec ±0.97% (94 runs sampled) + arr-union x 9,602,852 ops/sec ±0.87% (92 runs sampled) +``` + +## Usage + +```js +var union = require('arr-union'); + +union(['a'], ['b', 'c'], ['d', 'e', 'f']); +//=> ['a', 'b', 'c', 'd', 'e', 'f'] +``` + +Returns only unique elements: + +```js +union(['a', 'a'], ['b', 'c']); +//=> ['a', 'b', 'c'] +``` + +## Related projects + +* [arr-diff](https://www.npmjs.com/package/arr-diff): Returns an array with only the unique values from the first array, by excluding all… [more](https://www.npmjs.com/package/arr-diff) | [homepage](https://github.com/jonschlinkert/arr-diff) +* [arr-filter](https://www.npmjs.com/package/arr-filter): Faster alternative to javascript's native filter method. | [homepage](https://github.com/jonschlinkert/arr-filter) +* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten) +* [arr-map](https://www.npmjs.com/package/arr-map): Faster, node.js focused alternative to JavaScript's native array map. | [homepage](https://github.com/jonschlinkert/arr-map) +* [arr-pluck](https://www.npmjs.com/package/arr-pluck): Retrieves the value of a specified property from all elements in the collection. | [homepage](https://github.com/jonschlinkert/arr-pluck) +* [arr-reduce](https://www.npmjs.com/package/arr-reduce): Fast array reduce that also loops over sparse elements. | [homepage](https://github.com/jonschlinkert/arr-reduce) +* [array-unique](https://www.npmjs.com/package/array-unique): Return an array free of duplicate values. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/arr-union/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm i verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016 [Jon Schlinkert](https://github.com/jonschlinkert) +Released under the [MIT license](https://github.com/jonschlinkert/arr-union/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on February 23, 2016._ \ No newline at end of file diff --git a/js/node_modules/arr-union/index.js b/js/node_modules/arr-union/index.js new file mode 100644 index 0000000..5ae6c4a --- /dev/null +++ b/js/node_modules/arr-union/index.js @@ -0,0 +1,29 @@ +'use strict'; + +module.exports = function union(init) { + if (!Array.isArray(init)) { + throw new TypeError('arr-union expects the first argument to be an array.'); + } + + var len = arguments.length; + var i = 0; + + while (++i < len) { + var arg = arguments[i]; + if (!arg) continue; + + if (!Array.isArray(arg)) { + arg = [arg]; + } + + for (var j = 0; j < arg.length; j++) { + var ele = arg[j]; + + if (init.indexOf(ele) >= 0) { + continue; + } + init.push(ele); + } + } + return init; +}; diff --git a/js/node_modules/arr-union/package.json b/js/node_modules/arr-union/package.json new file mode 100644 index 0000000..f59ddcf --- /dev/null +++ b/js/node_modules/arr-union/package.json @@ -0,0 +1,108 @@ +{ + "_from": "arr-union@^3.1.0", + "_id": "arr-union@3.1.0", + "_inBundle": false, + "_integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "_location": "/arr-union", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "arr-union@^3.1.0", + "name": "arr-union", + "escapedName": "arr-union", + "rawSpec": "^3.1.0", + "saveSpec": null, + "fetchSpec": "^3.1.0" + }, + "_requiredBy": [ + "/class-utils", + "/union-value" + ], + "_resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "_shasum": "e39b09aea9def866a8f206e288af63919bae39c4", + "_spec": "arr-union@^3.1.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/union-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/arr-union/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.", + "devDependencies": { + "ansi-bold": "^0.1.1", + "array-union": "^1.0.1", + "array-unique": "^0.2.1", + "benchmarked": "^0.1.4", + "gulp-format-md": "^0.1.7", + "minimist": "^1.1.1", + "mocha": "*", + "should": "*" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/arr-union", + "keywords": [ + "add", + "append", + "array", + "arrays", + "combine", + "concat", + "extend", + "union", + "uniq", + "unique", + "util", + "utility", + "utils" + ], + "license": "MIT", + "main": "index.js", + "name": "arr-union", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/arr-union.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "run": true, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "arr-diff", + "arr-flatten", + "arr-filter", + "arr-map", + "arr-pluck", + "arr-reduce", + "array-unique" + ] + }, + "reflinks": [ + "verb", + "array-union" + ], + "lint": { + "reflinks": true + } + }, + "version": "3.1.0" +} diff --git a/js/node_modules/array-unique/LICENSE b/js/node_modules/array-unique/LICENSE new file mode 100755 index 0000000..fa30c4c --- /dev/null +++ b/js/node_modules/array-unique/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/array-unique/README.md b/js/node_modules/array-unique/README.md new file mode 100755 index 0000000..2e28774 --- /dev/null +++ b/js/node_modules/array-unique/README.md @@ -0,0 +1,51 @@ +# array-unique [![NPM version](https://badge.fury.io/js/array-unique.svg)](http://badge.fury.io/js/array-unique) [![Build Status](https://travis-ci.org/jonschlinkert/array-unique.svg)](https://travis-ci.org/jonschlinkert/array-unique) + +> Return an array free of duplicate values. Fastest ES5 implementation. + +## Install with [npm](npmjs.org) + +```bash +npm i array-unique --save +``` + +## Usage + +```js +var unique = require('array-unique'); + +unique(['a', 'b', 'c', 'c']); +//=> ['a', 'b', 'c'] +``` + +## Related +* [arr-diff](https://github.com/jonschlinkert/arr-diff): Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons. +* [arr-union](https://github.com/jonschlinkert/arr-union): Returns an array of unique values using strict equality for comparisons. +* [arr-flatten](https://github.com/jonschlinkert/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. +* [arr-reduce](https://github.com/jonschlinkert/arr-reduce): Fast array reduce that also loops over sparse elements. +* [arr-map](https://github.com/jonschlinkert/arr-map): Faster, node.js focused alternative to JavaScript's native array map. +* [arr-pluck](https://github.com/jonschlinkert/arr-pluck): Retrieves the value of a specified property from all elements in the collection. + +## Run tests +Install dev dependencies. + +```bash +npm i -d && npm test +``` + +## Contributing +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/array-unique/issues) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License +Copyright (c) 2015 Jon Schlinkert +Released under the MIT license + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on March 24, 2015._ \ No newline at end of file diff --git a/js/node_modules/array-unique/index.js b/js/node_modules/array-unique/index.js new file mode 100755 index 0000000..7fa75af --- /dev/null +++ b/js/node_modules/array-unique/index.js @@ -0,0 +1,28 @@ +/*! + * array-unique + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +module.exports = function unique(arr) { + if (!Array.isArray(arr)) { + throw new TypeError('array-unique expects an array.'); + } + + var len = arr.length; + var i = -1; + + while (i++ < len) { + var j = i + 1; + + for (; j < arr.length; ++j) { + if (arr[i] === arr[j]) { + arr.splice(j--, 1); + } + } + } + return arr; +}; diff --git a/js/node_modules/array-unique/package.json b/js/node_modules/array-unique/package.json new file mode 100755 index 0000000..8d7c95a --- /dev/null +++ b/js/node_modules/array-unique/package.json @@ -0,0 +1,62 @@ +{ + "_from": "array-unique@^0.2.1", + "_id": "array-unique@0.2.1", + "_inBundle": false, + "_integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "_location": "/array-unique", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "array-unique@^0.2.1", + "name": "array-unique", + "escapedName": "array-unique", + "rawSpec": "^0.2.1", + "saveSpec": null, + "fetchSpec": "^0.2.1" + }, + "_requiredBy": [ + "/micromatch" + ], + "_resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "_shasum": "a1d97ccafcbc2625cc70fadceb36a50c58b01a53", + "_spec": "array-unique@^0.2.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/micromatch", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/array-unique/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Return an array free of duplicate values. Fastest ES5 implementation.", + "devDependencies": { + "array-uniq": "^1.0.2", + "benchmarked": "^0.1.3", + "mocha": "*", + "should": "*" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/array-unique", + "license": { + "type": "MIT", + "url": "https://github.com/jonschlinkert/array-unique/blob/master/LICENSE" + }, + "main": "index.js", + "name": "array-unique", + "repository": { + "type": "git", + "url": "git://github.com/jonschlinkert/array-unique.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.2.1" +} diff --git a/js/node_modules/assign-symbols/LICENSE b/js/node_modules/assign-symbols/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/js/node_modules/assign-symbols/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/assign-symbols/README.md b/js/node_modules/assign-symbols/README.md new file mode 100644 index 0000000..422729d --- /dev/null +++ b/js/node_modules/assign-symbols/README.md @@ -0,0 +1,73 @@ +# assign-symbols [![NPM version](https://badge.fury.io/js/assign-symbols.svg)](http://badge.fury.io/js/assign-symbols) + +> Assign the enumerable es6 Symbol properties from an object (or objects) to the first object passed on the arguments. Can be used as a supplement to other extend, assign or merge methods as a polyfill for the Symbols part of the es6 Object.assign method. + +From the [Mozilla Developer docs for Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol): + +> A symbol is a unique and immutable data type and may be used as an identifier for object properties. The symbol object is an implicit object wrapper for the symbol primitive data type. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i assign-symbols --save +``` + +## Usage + +```js +var assignSymbols = require('assign-symbols'); +var obj = {}; + +var one = {}; +var symbolOne = Symbol('aaa'); +one[symbolOne] = 'bbb'; + +var two = {}; +var symbolTwo = Symbol('ccc'); +two[symbolTwo] = 'ddd'; + +assignSymbols(obj, one, two); + +console.log(obj[symbolOne]); +//=> 'bbb' +console.log(obj[symbolTwo]); +//=> 'ddd' +``` + +## Similar projects + +* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties of source objects to a destination object. | [homepage](https://github.com/jonschlinkert/assign-deep) +* [clone-deep](https://www.npmjs.com/package/clone-deep): Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives. | [homepage](https://github.com/jonschlinkert/clone-deep) +* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow) +* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep) +* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/assign-symbols/issues/new). + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on November 06, 2015._ \ No newline at end of file diff --git a/js/node_modules/assign-symbols/index.js b/js/node_modules/assign-symbols/index.js new file mode 100644 index 0000000..c08a232 --- /dev/null +++ b/js/node_modules/assign-symbols/index.js @@ -0,0 +1,40 @@ +/*! + * assign-symbols + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +module.exports = function(receiver, objects) { + if (receiver === null || typeof receiver === 'undefined') { + throw new TypeError('expected first argument to be an object.'); + } + + if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { + return receiver; + } + + if (typeof Object.getOwnPropertySymbols !== 'function') { + return receiver; + } + + var isEnumerable = Object.prototype.propertyIsEnumerable; + var target = Object(receiver); + var len = arguments.length, i = 0; + + while (++i < len) { + var provider = Object(arguments[i]); + var names = Object.getOwnPropertySymbols(provider); + + for (var j = 0; j < names.length; j++) { + var key = names[j]; + + if (isEnumerable.call(provider, key)) { + target[key] = provider[key]; + } + } + } + return target; +}; diff --git a/js/node_modules/assign-symbols/package.json b/js/node_modules/assign-symbols/package.json new file mode 100644 index 0000000..ec5b77b --- /dev/null +++ b/js/node_modules/assign-symbols/package.json @@ -0,0 +1,71 @@ +{ + "_from": "assign-symbols@^1.0.0", + "_id": "assign-symbols@1.0.0", + "_inBundle": false, + "_integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "_location": "/assign-symbols", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "assign-symbols@^1.0.0", + "name": "assign-symbols", + "escapedName": "assign-symbols", + "rawSpec": "^1.0.0", + "saveSpec": null, + "fetchSpec": "^1.0.0" + }, + "_requiredBy": [ + "/extend-shallow" + ], + "_resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "_shasum": "59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367", + "_spec": "assign-symbols@^1.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/extend-shallow", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/assign-symbols/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Assign the enumerable es6 Symbol properties from an object (or objects) to the first object passed on the arguments. Can be used as a supplement to other extend, assign or merge methods as a polyfill for the Symbols part of the es6 Object.assign method.", + "devDependencies": { + "mocha": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/assign-symbols", + "keywords": [ + "assign", + "symbols" + ], + "license": "MIT", + "main": "index.js", + "name": "assign-symbols", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/assign-symbols.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "assign-deep", + "mixin-deep", + "merge-deep", + "extend-shallow", + "clone-deep" + ] + } + }, + "version": "1.0.0" +} diff --git a/js/node_modules/async-each/.npmignore b/js/node_modules/async-each/.npmignore new file mode 100644 index 0000000..3887b2b --- /dev/null +++ b/js/node_modules/async-each/.npmignore @@ -0,0 +1,3 @@ +bower.json +component.json +CHANGELOG.md diff --git a/js/node_modules/async-each/CHANGELOG.md b/js/node_modules/async-each/CHANGELOG.md new file mode 100644 index 0000000..bee2548 --- /dev/null +++ b/js/node_modules/async-each/CHANGELOG.md @@ -0,0 +1,23 @@ +# async-each 1.0.0 (26 November 2015) +* Bumped version to 1.0.0 (no functional changes) + +# async-each 0.1.6 (5 November 2014) +* Add license to package.json + +# async-each 0.1.5 (22 October 2014) +* Clean up package.json to fix npm warning about `repo` + +# async-each 0.1.4 (12 November 2013) +* Fixed AMD definition. + +# async-each 0.1.3 (25 July 2013) +* Fixed double wrapping of errors. + +# async-each 0.1.2 (7 July 2013) +* Fixed behaviour on empty arrays. + +# async-each 0.1.1 (14 June 2013) +* Wrapped function in closure, enabled strict mode. + +# async-each 0.1.0 (14 June 2013) +* Initial release. diff --git a/js/node_modules/async-each/README.md b/js/node_modules/async-each/README.md new file mode 100644 index 0000000..a79cbd7 --- /dev/null +++ b/js/node_modules/async-each/README.md @@ -0,0 +1,38 @@ +# async-each + +No-bullshit, ultra-simple, 35-lines-of-code async parallel forEach function for JavaScript. + +We don't need junky 30K async libs. Really. + +For browsers and node.js. + +## Installation +* Just include async-each before your scripts. +* `npm install async-each` if you’re using node.js. +* `bower install async-each` if you’re using [Bower](http://bower.io). + +## Usage + +* `each(array, iterator, callback);` — `Array`, `Function`, `(optional) Function` +* `iterator(item, next)` receives current item and a callback that will mark the item as done. `next` callback receives optional `error, transformedItem` arguments. +* `callback(error, transformedArray)` optionally receives first error and transformed result `Array`. + +Node.js: + +```javascript +var each = require('async-each'); +each(['a.js', 'b.js', 'c.js'], fs.readFile, function(error, contents) { + if (error) console.error(error); + console.log('Contents for a, b and c:', contents); +}); +``` + +Browser: + +```javascript +window.asyncEach(list, fn, callback); +``` + +## License + +[The MIT License](https://raw.githubusercontent.com/paulmillr/mit/master/README.md) diff --git a/js/node_modules/async-each/index.js b/js/node_modules/async-each/index.js new file mode 100644 index 0000000..1c51c95 --- /dev/null +++ b/js/node_modules/async-each/index.js @@ -0,0 +1,38 @@ +// async-each MIT license (by Paul Miller from http://paulmillr.com). +(function(globals) { + 'use strict'; + var each = function(items, next, callback) { + if (!Array.isArray(items)) throw new TypeError('each() expects array as first argument'); + if (typeof next !== 'function') throw new TypeError('each() expects function as second argument'); + if (typeof callback !== 'function') callback = Function.prototype; // no-op + + if (items.length === 0) return callback(undefined, items); + + var transformed = new Array(items.length); + var count = 0; + var returned = false; + + items.forEach(function(item, index) { + next(item, function(error, transformedItem) { + if (returned) return; + if (error) { + returned = true; + return callback(error); + } + transformed[index] = transformedItem; + count += 1; + if (count === items.length) return callback(undefined, transformed); + }); + }); + }; + + if (typeof define !== 'undefined' && define.amd) { + define([], function() { + return each; + }); // RequireJS + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = each; // CommonJS + } else { + globals.asyncEach = each; // + + +

Node-webkit-based module test

+ + diff --git a/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json b/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json new file mode 100644 index 0000000..71d03f8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json @@ -0,0 +1,9 @@ +{ +"main": "index.html", +"name": "nw-pre-gyp-module-test", +"description": "Node-webkit-based module test.", +"version": "0.0.1", +"window": { + "show": false +} +} diff --git a/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/s3_setup.js b/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/s3_setup.js new file mode 100644 index 0000000..5bc42e9 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/s3_setup.js @@ -0,0 +1,27 @@ +"use strict"; + +module.exports = exports; + +var url = require('url'); + +var URI_REGEX="^(.*)\.(s3(?:-.*)?)\.amazonaws\.com$"; + +module.exports.detect = function(to,config) { + var uri = url.parse(to); + var hostname_matches = uri.hostname.match(URI_REGEX); + config.prefix = (!uri.pathname || uri.pathname == '/') ? '' : uri.pathname.replace('/',''); + if(!hostname_matches) { + return; + } + if (!config.bucket) { + config.bucket = hostname_matches[1]; + } + if (!config.region) { + var s3_domain = hostname_matches[2]; + if (s3_domain.slice(0,3) == 's3-' && + s3_domain.length >= 3) { + // it appears the region is explicit in the url + config.region = s3_domain.replace('s3-',''); + } + } +}; diff --git a/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/versioning.js b/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/versioning.js new file mode 100644 index 0000000..70307b4 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/node-pre-gyp/lib/util/versioning.js @@ -0,0 +1,330 @@ +"use strict"; + +module.exports = exports; + +var path = require('path'); +var semver = require('semver'); +var url = require('url'); +var detect_libc = require('detect-libc'); +var napi = require('./napi.js'); + +var abi_crosswalk; + +// This is used for unit testing to provide a fake +// ABI crosswalk that emulates one that is not updated +// for the current version +if (process.env.NODE_PRE_GYP_ABI_CROSSWALK) { + abi_crosswalk = require(process.env.NODE_PRE_GYP_ABI_CROSSWALK); +} else { + abi_crosswalk = require('./abi_crosswalk.json'); +} + +var major_versions = {}; +Object.keys(abi_crosswalk).forEach(function(v) { + var major = v.split('.')[0]; + if (!major_versions[major]) { + major_versions[major] = v; + } +}); + +function get_electron_abi(runtime, target_version) { + if (!runtime) { + throw new Error("get_electron_abi requires valid runtime arg"); + } + if (typeof target_version === 'undefined') { + // erroneous CLI call + throw new Error("Empty target version is not supported if electron is the target."); + } + // Electron guarantees that patch version update won't break native modules. + var sem_ver = semver.parse(target_version); + return runtime + '-v' + sem_ver.major + '.' + sem_ver.minor; +} +module.exports.get_electron_abi = get_electron_abi; + +function get_node_webkit_abi(runtime, target_version) { + if (!runtime) { + throw new Error("get_node_webkit_abi requires valid runtime arg"); + } + if (typeof target_version === 'undefined') { + // erroneous CLI call + throw new Error("Empty target version is not supported if node-webkit is the target."); + } + return runtime + '-v' + target_version; +} +module.exports.get_node_webkit_abi = get_node_webkit_abi; + +function get_node_abi(runtime, versions) { + if (!runtime) { + throw new Error("get_node_abi requires valid runtime arg"); + } + if (!versions) { + throw new Error("get_node_abi requires valid process.versions object"); + } + var sem_ver = semver.parse(versions.node); + if (sem_ver.major === 0 && sem_ver.minor % 2) { // odd series + // https://github.com/mapbox/node-pre-gyp/issues/124 + return runtime+'-v'+versions.node; + } else { + // process.versions.modules added in >= v0.10.4 and v0.11.7 + // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e + return versions.modules ? runtime+'-v' + (+versions.modules) : + 'v8-' + versions.v8.split('.').slice(0,2).join('.'); + } +} +module.exports.get_node_abi = get_node_abi; + +function get_runtime_abi(runtime, target_version) { + if (!runtime) { + throw new Error("get_runtime_abi requires valid runtime arg"); + } + if (runtime === 'node-webkit') { + return get_node_webkit_abi(runtime, target_version || process.versions['node-webkit']); + } else if (runtime === 'electron') { + return get_electron_abi(runtime, target_version || process.versions.electron); + } else { + if (runtime != 'node') { + throw new Error("Unknown Runtime: '" + runtime + "'"); + } + if (!target_version) { + return get_node_abi(runtime,process.versions); + } else { + var cross_obj; + // abi_crosswalk generated with ./scripts/abi_crosswalk.js + if (abi_crosswalk[target_version]) { + cross_obj = abi_crosswalk[target_version]; + } else { + var target_parts = target_version.split('.').map(function(i) { return +i; }); + if (target_parts.length != 3) { // parse failed + throw new Error("Unknown target version: " + target_version); + } + /* + The below code tries to infer the last known ABI compatible version + that we have recorded in the abi_crosswalk.json when an exact match + is not possible. The reasons for this to exist are complicated: + + - We support passing --target to be able to allow developers to package binaries for versions of node + that are not the same one as they are running. This might also be used in combination with the + --target_arch or --target_platform flags to also package binaries for alternative platforms + - When --target is passed we can't therefore determine the ABI (process.versions.modules) from the node + version that is running in memory + - So, therefore node-pre-gyp keeps an "ABI crosswalk" (lib/util/abi_crosswalk.json) to be able to look + this info up for all versions + - But we cannot easily predict what the future ABI will be for released versions + - And node-pre-gyp needs to be a `bundledDependency` in apps that depend on it in order to work correctly + by being fully available at install time. + - So, the speed of node releases and the bundled nature of node-pre-gyp mean that a new node-pre-gyp release + need to happen for every node.js/io.js/node-webkit/nw.js/atom-shell/etc release that might come online if + you want the `--target` flag to keep working for the latest version + - Which is impractical ^^ + - Hence the below code guesses about future ABI to make the need to update node-pre-gyp less demanding. + + In practice then you can have a dependency of your app like `node-sqlite3` that bundles a `node-pre-gyp` that + only knows about node v0.10.33 in the `abi_crosswalk.json` but target node v0.10.34 (which is assumed to be + ABI compatible with v0.10.33). + + TODO: use semver module instead of custom version parsing + */ + var major = target_parts[0]; + var minor = target_parts[1]; + var patch = target_parts[2]; + // io.js: yeah if node.js ever releases 1.x this will break + // but that is unlikely to happen: https://github.com/iojs/io.js/pull/253#issuecomment-69432616 + if (major === 1) { + // look for last release that is the same major version + // e.g. we assume io.js 1.x is ABI compatible with >= 1.0.0 + while (true) { + if (minor > 0) --minor; + if (patch > 0) --patch; + var new_iojs_target = '' + major + '.' + minor + '.' + patch; + if (abi_crosswalk[new_iojs_target]) { + cross_obj = abi_crosswalk[new_iojs_target]; + console.log('Warning: node-pre-gyp could not find exact match for ' + target_version); + console.log('Warning: but node-pre-gyp successfully choose ' + new_iojs_target + ' as ABI compatible target'); + break; + } + if (minor === 0 && patch === 0) { + break; + } + } + } else if (major >= 2) { + // look for last release that is the same major version + if (major_versions[major]) { + cross_obj = abi_crosswalk[major_versions[major]]; + console.log('Warning: node-pre-gyp could not find exact match for ' + target_version); + console.log('Warning: but node-pre-gyp successfully choose ' + major_versions[major] + ' as ABI compatible target'); + } + } else if (major === 0) { // node.js + if (target_parts[1] % 2 === 0) { // for stable/even node.js series + // look for the last release that is the same minor release + // e.g. we assume node 0.10.x is ABI compatible with >= 0.10.0 + while (--patch > 0) { + var new_node_target = '' + major + '.' + minor + '.' + patch; + if (abi_crosswalk[new_node_target]) { + cross_obj = abi_crosswalk[new_node_target]; + console.log('Warning: node-pre-gyp could not find exact match for ' + target_version); + console.log('Warning: but node-pre-gyp successfully choose ' + new_node_target + ' as ABI compatible target'); + break; + } + } + } + } + } + if (!cross_obj) { + throw new Error("Unsupported target version: " + target_version); + } + // emulate process.versions + var versions_obj = { + node: target_version, + v8: cross_obj.v8+'.0', + // abi_crosswalk uses 1 for node versions lacking process.versions.modules + // process.versions.modules added in >= v0.10.4 and v0.11.7 + modules: cross_obj.node_abi > 1 ? cross_obj.node_abi : undefined + }; + return get_node_abi(runtime, versions_obj); + } + } +} +module.exports.get_runtime_abi = get_runtime_abi; + +var required_parameters = [ + 'module_name', + 'module_path', + 'host' +]; + +function validate_config(package_json) { + var msg = package_json.name + ' package.json is not node-pre-gyp ready:\n'; + var missing = []; + if (!package_json.main) { + missing.push('main'); + } + if (!package_json.version) { + missing.push('version'); + } + if (!package_json.name) { + missing.push('name'); + } + if (!package_json.binary) { + missing.push('binary'); + } + var o = package_json.binary; + required_parameters.forEach(function(p) { + if (missing.indexOf('binary') > -1) { + missing.pop('binary'); + } + if (!o || o[p] === undefined || o[p] === "") { + missing.push('binary.' + p); + } + }); + if (missing.length >= 1) { + throw new Error(msg+"package.json must declare these properties: \n" + missing.join('\n')); + } + if (o) { + // enforce https over http + var protocol = url.parse(o.host).protocol; + if (protocol === 'http:') { + throw new Error("'host' protocol ("+protocol+") is invalid - only 'https:' is accepted"); + } + } + napi.validate_package_json(package_json); +} + +module.exports.validate_config = validate_config; + +function eval_template(template,opts) { + Object.keys(opts).forEach(function(key) { + var pattern = '{'+key+'}'; + while (template.indexOf(pattern) > -1) { + template = template.replace(pattern,opts[key]); + } + }); + return template; +} + +// url.resolve needs single trailing slash +// to behave correctly, otherwise a double slash +// may end up in the url which breaks requests +// and a lacking slash may not lead to proper joining +function fix_slashes(pathname) { + if (pathname.slice(-1) != '/') { + return pathname + '/'; + } + return pathname; +} + +// remove double slashes +// note: path.normalize will not work because +// it will convert forward to back slashes +function drop_double_slashes(pathname) { + return pathname.replace(/\/\//g,'/'); +} + +function get_process_runtime(versions) { + var runtime = 'node'; + if (versions['node-webkit']) { + runtime = 'node-webkit'; + } else if (versions.electron) { + runtime = 'electron'; + } + return runtime; +} + +module.exports.get_process_runtime = get_process_runtime; + +var default_package_name = '{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz'; +var default_remote_path = ''; + +module.exports.evaluate = function(package_json,options,napi_build_version) { + options = options || {}; + validate_config(package_json); + var v = package_json.version; + var module_version = semver.parse(v); + var runtime = options.runtime || get_process_runtime(process.versions); + var opts = { + name: package_json.name, + configuration: Boolean(options.debug) ? 'Debug' : 'Release', + debug: options.debug, + module_name: package_json.binary.module_name, + version: module_version.version, + prerelease: module_version.prerelease.length ? module_version.prerelease.join('.') : '', + build: module_version.build.length ? module_version.build.join('.') : '', + major: module_version.major, + minor: module_version.minor, + patch: module_version.patch, + runtime: runtime, + node_abi: get_runtime_abi(runtime,options.target), + node_abi_napi: napi.get_napi_version() ? 'napi' : get_runtime_abi(runtime,options.target), + napi_version: napi.get_napi_version(), // non-zero numeric, undefined if unsupported + napi_build_version: napi_build_version, // undefined if not specified + target: options.target || '', + platform: options.target_platform || process.platform, + target_platform: options.target_platform || process.platform, + arch: options.target_arch || process.arch, + target_arch: options.target_arch || process.arch, + libc: options.target_libc || detect_libc.family || 'unknown', + module_main: package_json.main, + toolset : options.toolset || '' // address https://github.com/mapbox/node-pre-gyp/issues/119 + }; + // support host mirror with npm config `--{module_name}_binary_host_mirror` + // e.g.: https://github.com/node-inspector/v8-profiler/blob/master/package.json#L25 + // > npm install v8-profiler --profiler_binary_host_mirror=https://npm.taobao.org/mirrors/node-inspector/ + var host = process.env['npm_config_' + opts.module_name + '_binary_host_mirror'] || package_json.binary.host; + opts.host = fix_slashes(eval_template(host,opts)); + opts.module_path = eval_template(package_json.binary.module_path,opts); + // now we resolve the module_path to ensure it is absolute so that binding.gyp variables work predictably + if (options.module_root) { + // resolve relative to known module root: works for pre-binding require + opts.module_path = path.join(options.module_root,opts.module_path); + } else { + // resolve relative to current working directory: works for node-pre-gyp commands + opts.module_path = path.resolve(opts.module_path); + } + opts.module = path.join(opts.module_path,opts.module_name + '.node'); + opts.remote_path = package_json.binary.remote_path ? drop_double_slashes(fix_slashes(eval_template(package_json.binary.remote_path,opts))) : default_remote_path; + var package_name = package_json.binary.package_name ? package_json.binary.package_name : default_package_name; + opts.package_name = eval_template(package_name,opts); + opts.staged_tarball = path.join('build/stage',opts.remote_path,opts.package_name); + opts.hosted_path = url.resolve(opts.host,opts.remote_path); + opts.hosted_tarball = url.resolve(opts.hosted_path,opts.package_name); + return opts; +}; diff --git a/js/node_modules/fsevents/node_modules/node-pre-gyp/package.json b/js/node_modules/fsevents/node_modules/node-pre-gyp/package.json new file mode 100644 index 0000000..9222d2b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/node-pre-gyp/package.json @@ -0,0 +1,90 @@ +{ + "_args": [ + [ + "node-pre-gyp@0.9.1", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "node-pre-gyp@0.9.1", + "_id": "node-pre-gyp@0.9.1", + "_inBundle": true, + "_integrity": "sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=", + "_location": "/fsevents/node-pre-gyp", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "node-pre-gyp@0.9.1", + "name": "node-pre-gyp", + "escapedName": "node-pre-gyp", + "rawSpec": "0.9.1", + "saveSpec": null, + "fetchSpec": "0.9.1" + }, + "_requiredBy": [ + "/fsevents" + ], + "_resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz", + "_spec": "0.9.1", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Dane Springmeyer", + "email": "dane@mapbox.com" + }, + "bin": { + "node-pre-gyp": "./bin/node-pre-gyp" + }, + "bugs": { + "url": "https://github.com/mapbox/node-pre-gyp/issues" + }, + "dependencies": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "description": "Node.js native addon binary install tool", + "devDependencies": { + "aws-sdk": "^2.28.0", + "jshint": "^2.9.5", + "nock": "^9.2.3", + "retire": "^1.2.12", + "tape": "^4.6.3" + }, + "homepage": "https://github.com/mapbox/node-pre-gyp#readme", + "jshintConfig": { + "node": true, + "globalstrict": true, + "undef": true, + "unused": false, + "noarg": true + }, + "keywords": [ + "native", + "addon", + "module", + "c", + "c++", + "bindings", + "binary" + ], + "license": "BSD-3-Clause", + "main": "./lib/node-pre-gyp.js", + "name": "node-pre-gyp", + "repository": { + "type": "git", + "url": "git://github.com/mapbox/node-pre-gyp.git" + }, + "scripts": { + "pretest": "jshint test/build.test.js test/s3_setup.test.js test/versioning.test.js test/fetch.test.js lib lib/util scripts bin/node-pre-gyp", + "test": "jshint lib lib/util scripts bin/node-pre-gyp && tape test/*test.js", + "update-crosswalk": "node scripts/abi_crosswalk.js" + }, + "version": "0.9.1" +} diff --git a/js/node_modules/fsevents/node_modules/nopt/.npmignore b/js/node_modules/fsevents/node_modules/nopt/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/js/node_modules/fsevents/node_modules/nopt/.travis.yml b/js/node_modules/fsevents/node_modules/nopt/.travis.yml new file mode 100644 index 0000000..a1cef59 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - '0.12' + - '4' + - '6' + - '7' +before_install: + - npm install -g npm@latest diff --git a/js/node_modules/fsevents/node_modules/nopt/CHANGELOG.md b/js/node_modules/fsevents/node_modules/nopt/CHANGELOG.md new file mode 100644 index 0000000..82a09fb --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/CHANGELOG.md @@ -0,0 +1,58 @@ +### v4.0.1 (2016-12-14) + +#### WHOOPS + +* [`fb9b1ce`](https://github.com/npm/nopt/commit/fb9b1ce57b3c69b4f7819015be87719204f77ef6) + Merged so many patches at once that the code fencing + ([@adius](https://github.com/adius)) added got broken. Sorry, + ([@adius](https://github.com/adius))! + ([@othiym23](https://github.com/othiym23)) + +### v4.0.0 (2016-12-13) + +#### BREAKING CHANGES + +* [`651d447`](https://github.com/npm/nopt/commit/651d4473946096d341a480bbe56793de3fc706aa) + When parsing String-typed arguments, if the next value is `""`, don't simply + swallow it. ([@samjonester](https://github.com/samjonester)) + +#### PERFORMANCE TWEAKS + +* [`3370ce8`](https://github.com/npm/nopt/commit/3370ce87a7618ba228883861db84ddbcdff252a9) + Simplify initialization. ([@elidoran](https://github.com/elidoran)) +* [`356e58e`](https://github.com/npm/nopt/commit/356e58e3b3b431a4b1af7fd7bdee44c2c0526a09) + Store `Array.isArray(types[arg])` for reuse. + ([@elidoran](https://github.com/elidoran)) +* [`0d95e90`](https://github.com/npm/nopt/commit/0d95e90515844f266015b56d2c80b94e5d14a07e) + Interpret single-item type arrays as a single type. + ([@samjonester](https://github.com/samjonester)) +* [`07c69d3`](https://github.com/npm/nopt/commit/07c69d38b5186450941fbb505550becb78a0e925) + Simplify key-value extraction. ([@elidoran](https://github.com/elidoran)) +* [`39b6e5c`](https://github.com/npm/nopt/commit/39b6e5c65ac47f60cd43a1fbeece5cd4c834c254) + Only call `Date.parse(val)` once. ([@elidoran](https://github.com/elidoran)) +* [`934943d`](https://github.com/npm/nopt/commit/934943dffecb55123a2b15959fe2a359319a5dbd) + Use `osenv.home()` to find a user's home directory instead of assuming it's + always `$HOME`. ([@othiym23](https://github.com/othiym23)) + +#### TEST & CI IMPROVEMENTS + +* [`326ffff`](https://github.com/npm/nopt/commit/326ffff7f78a00bcd316adecf69075f8a8093619) + Fix `/tmp` test to work on Windows. + ([@elidoran](https://github.com/elidoran)) +* [`c89d31a`](https://github.com/npm/nopt/commit/c89d31a49d14f2238bc6672db08da697bbc57f1b) + Only run Windows tests on Windows, only run Unix tests on a Unix. + ([@elidoran](https://github.com/elidoran)) +* [`affd3d1`](https://github.com/npm/nopt/commit/affd3d1d0addffa93006397b2013b18447339366) + Refresh Travis to run the tests against the currently-supported batch of npm + versions. ([@helio](https://github.com/helio)-frota) +* [`55f9449`](https://github.com/npm/nopt/commit/55f94497d163ed4d16dd55fd6c4fb95cc440e66d) + `tap@8.0.1` ([@othiym23](https://github.com/othiym23)) + +#### DOC TWEAKS + +* [`5271229`](https://github.com/npm/nopt/commit/5271229ee7c810217dd51616c086f5d9ab224581) + Use JavaScript code block for syntax highlighting. + ([@adius](https://github.com/adius)) +* [`c0d156f`](https://github.com/npm/nopt/commit/c0d156f229f9994c5dfcec4a8886eceff7a07682) + The code sample in the README had `many2: [ oneThing ]`, and now it has + `many2: [ two, things ]`. ([@silkentrance](https://github.com/silkentrance)) diff --git a/js/node_modules/fsevents/node_modules/nopt/LICENSE b/js/node_modules/fsevents/node_modules/nopt/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/nopt/README.md b/js/node_modules/fsevents/node_modules/nopt/README.md new file mode 100644 index 0000000..a99531c --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/README.md @@ -0,0 +1,213 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you hit the limit of your frustration just trying to +manage them all, and defer it with duct-tape solutions until you see +exactly to the core of the problem, and finally snap and write an +awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + +```javascript +// my-program.js +var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many1" : [String, Array] + , "many2" : [path, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) +console.log(parsed) +``` + +This would give you support for any of the following: + +```console +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk -fp # unknown opts are ok. +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many1 5 --many1 null --many1 foo +{ many1: ["5", "null", "foo"] } + +$ node my-program.js --many2 foo --many2 bar +{ many2: ["/path/to/foo", "path/to/bar"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid values for +known options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/js/node_modules/fsevents/node_modules/nopt/examples/my-program.js b/js/node_modules/fsevents/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000..142447e --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/js/node_modules/fsevents/node_modules/nopt/lib/nopt.js b/js/node_modules/fsevents/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..1fb1135 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/lib/nopt.js @@ -0,0 +1,436 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + , osenv = require("osenv") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , argv = { + remain: [], + cooked: args, + original: args.slice(0) + } + + parse(args, data, argv.remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = argv + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Array] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + if (val === true) return false + if (val === null) return true + + val = String(val) + + var isWin = process.platform === 'win32' + , homePattern = isWin ? /^~(\/|\\)/ : /^~\// + , home = osenv.home() + + if (home && val.match(homePattern)) { + data[k] = path.resolve(home, val.substr(2)) + } else { + data[k] = path.resolve(val) + } + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + var s = Date.parse(val) + debug("validate Date %j %j %j", k, val, s) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && + ((type && type.name && t.type && t.type.name) ? (type.name === t.type.name) : (type === t.type))) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-" && arg.length > 1) { + var at = arg.indexOf('=') + if (at > -1) { + hadEq = true + var v = arg.substr(at + 1) + arg = arg.substr(0, at) + args.splice(i, 1, arg, v) + } + + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var argType = types[arg] + var isTypeArray = Array.isArray(argType) + if (isTypeArray && argType.length === 1) { + isTypeArray = false + argType = argType[0] + } + + var isArray = argType === Array || + isTypeArray && argType.indexOf(Array) !== -1 + + // allow unknown things to be arrays if specified multiple times. + if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) { + if (!Array.isArray(data[arg])) + data[arg] = [data[arg]] + isArray = true + } + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + argType === Boolean || + isTypeArray && argType.indexOf(Boolean) !== -1 || + (typeof argType === 'undefined' && !hadEq) || + (la === "false" && + (argType === null || + isTypeArray && ~argType.indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (isTypeArray && la) { + if (~argType.indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~argType.indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~argType.indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~argType.indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (argType === String) { + if (la === undefined) { + la = "" + } else if (la.match(/^-{1,2}[^-]+/)) { + la = "" + i -- + } + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + + // if it's an exact known option, then don't go any further + if (abbrevs[arg] === arg) + return null + + // if it's an exact known shortopt, same deal + if (shorthands[arg]) { + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] + } + + // first check to see if this arg is a set of single-char shorthands + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { + l[r] = true + return l + }, {}) + shorthands.___singles = singles + debug('shorthand singles', singles) + } + + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + + + // if it's an arg abbrev, and not a literal shorthand, then prefer the arg + if (abbrevs[arg] && !shorthands[arg]) + return null + + // if it's an abbr for a shorthand, then use that + if (shortAbbr[arg]) + arg = shortAbbr[arg] + + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] +} diff --git a/js/node_modules/fsevents/node_modules/nopt/package.json b/js/node_modules/fsevents/node_modules/nopt/package.json new file mode 100644 index 0000000..82636cd --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/package.json @@ -0,0 +1,61 @@ +{ + "_args": [ + [ + "nopt@4.0.1", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "nopt@4.0.1", + "_id": "nopt@4.0.1", + "_inBundle": true, + "_integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "_location": "/fsevents/nopt", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "nopt@4.0.1", + "name": "nopt", + "escapedName": "nopt", + "rawSpec": "4.0.1", + "saveSpec": null, + "fetchSpec": "4.0.1" + }, + "_requiredBy": [ + "/fsevents/node-pre-gyp" + ], + "_resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "_spec": "4.0.1", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "bugs": { + "url": "https://github.com/npm/nopt/issues" + }, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "devDependencies": { + "tap": "^8.0.1" + }, + "homepage": "https://github.com/npm/nopt#readme", + "license": "ISC", + "main": "lib/nopt.js", + "name": "nopt", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/nopt.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "4.0.1" +} diff --git a/js/node_modules/fsevents/node_modules/nopt/test/basic.js b/js/node_modules/fsevents/node_modules/nopt/test/basic.js new file mode 100644 index 0000000..5c18ac0 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/nopt/test/basic.js @@ -0,0 +1,303 @@ +var nopt = require("../") + , test = require('tap').test + , isWin = process.platform === 'win32' + +test("passing a string results in a string", function (t) { + var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0) + t.same(parsed.key, "myvalue") + t.end() +}) + +// https://github.com/npm/nopt/issues/31 +test("Empty String results in empty string, not true", function (t) { + var parsed = nopt({ empty: String }, {}, ["--empty"], 0) + t.same(parsed.empty, "") + t.end() +}) + +// https://github.com/npm/nopt/issues/65 +test("Empty String should not swallow next flag", function (t) { + var parsed = nopt({ empty: String, foo: String }, {}, ["--empty", "--foo"], 0) + t.same(parsed.empty, "") + t.same(parsed.foo, "") + t.end() +}) + +// https://github.com/npm/nopt/issues/66 +test("Empty String should not be true when type is single item Array", function (t) { + var parsed = nopt({ 'foo': [String] }, {}, ["--foo"], 0) + t.same(parsed.foo, "") + t.end() +}) + +test("~ path is resolved to " + (isWin ? '%USERPROFILE%' : '$HOME'), function (t) { + var path = require("path") + , the + + if (isWin) { + the = { + key: 'USERPROFILE', + dir: 'C:\\temp', + val: '~\\val' + } + } else { + the = { + key: 'HOME', + dir: '/tmp', + val: '~/val' + } + } + if (!process.env[the.key]) process.env[the.key] = v.dir + var parsed = nopt({key: path}, {}, ["--key=" + the.val], 0) + t.same(parsed.key, path.resolve(process.env[the.key], "val")) + t.end() +}) + +// https://github.com/npm/nopt/issues/24 +test("Unknown options are not parsed as numbers", function (t) { + var parsed = nopt({"parse-me": Number}, null, ['--leave-as-is=1.20', '--parse-me=1.20'], 0) + t.equal(parsed['leave-as-is'], '1.20') + t.equal(parsed['parse-me'], 1.2) + t.end() +}); + +// https://github.com/npm/nopt/issues/48 +test("Check types based on name of type", function (t) { + var parsed = nopt({"parse-me": {name: "Number"}}, null, ['--parse-me=1.20'], 0) + t.equal(parsed['parse-me'], 1.2) + t.end() +}) + + +test("Missing types are not parsed", function (t) { + var parsed = nopt({"parse-me": {}}, null, ['--parse-me=1.20'], 0) + //should only contain argv + t.equal(Object.keys(parsed).length, 1) + t.end() +}) + +test("Types passed without a name are not parsed", function (t) { + var parsed = nopt({"parse-me": {}}, {}, ['--parse-me=1.20'], 0) + //should only contain argv + t.equal(Object.keys(parsed).length, 1) + t.end() +}) + +test("other tests", function (t) { + + var util = require("util") + , Stream = require("stream") + , path = require("path") + , url = require("url") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + , path: path + } + + ; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar", {tmp: isWin ? "C:\\tmp" : "/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, '100']} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ,["-cl 1" + ,{config: true, length: 1} + ,[] + ,{config: Boolean, length: Number, clear: Boolean} + ,{c: "--config", l: "--length"}] + ,["--acount bla" + ,{"acount":true} + ,["bla"] + ,{account: Boolean, credentials: Boolean, options: String} + ,{a:"--account", c:"--credentials",o:"--options"}] + ,["--clear" + ,{clear:true} + ,[] + ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean} + ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}] + ,["--file -" + ,{"file":"-"} + ,[] + ,{file:String} + ,{}] + ,["--file -" + ,{"file":true} + ,["-"] + ,{file:Boolean} + ,{}] + ,["--path" + ,{"path":null} + ,[]] + ,["--path ." + ,{"path":process.cwd()} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + t.deepEqual(e, a) + } else { + t.equal(e, a) + } + } + t.deepEqual(rem, parsed.remain) + }) + t.end() +}) diff --git a/js/node_modules/fsevents/node_modules/npm-bundled/README.md b/js/node_modules/fsevents/node_modules/npm-bundled/README.md new file mode 100644 index 0000000..2974afa --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-bundled/README.md @@ -0,0 +1,46 @@ +# npm-bundled + +Run this in a node package, and it'll tell you which things in +node_modules are bundledDependencies, or transitive dependencies of +bundled dependencies. + +## USAGE + +To get the list of deps at the top level that are bundled (or +transitive deps of a bundled dep) run this: + +```js +const bundled = require('npm-bundled') + +// async version +bundled({ path: '/path/to/pkg/defaults/to/cwd'}, (er, list) => { + // er means it had an error, which is _hella_ weird + // list is a list of package names, like `fooblz` or `@corp/blerg` + // the might not all be deps of the top level, because transitives +}) + +// async promise version +bundled({ path: '/path/to/pkg/defaults/to/cwd'}).then(list => { + // so promisey! + // actually the callback version returns a promise, too, it just + // attaches the supplied callback to the promise +}) + +// sync version, throws if there's an error +const list = bundled({ path: '/path/to/pkg/defaults/to/cwd'}) +``` + +That's basically all you need to know. If you care to dig into it, +you can also use the `bundled.Walker` and `bundled.WalkerSync` +classes to get fancy. + +This library does not write anything to the filesystem, but it _may_ +have undefined behavior if the structure of `node_modules` changes +while it's reading deps. + +All symlinks are followed. This means that it can lead to surprising +results if a symlinked bundled dependency has a missing dependency +that is satisfied at the top level. Since package creation resolves +symlinks as well, this is an edge case where package creation and +development environment are not going to be aligned, and is best +avoided. diff --git a/js/node_modules/fsevents/node_modules/npm-bundled/index.js b/js/node_modules/fsevents/node_modules/npm-bundled/index.js new file mode 100644 index 0000000..dadd847 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-bundled/index.js @@ -0,0 +1,227 @@ +'use strict' + +// walk the tree of deps starting from the top level list of bundled deps +// Any deps at the top level that are depended on by a bundled dep that +// does not have that dep in its own node_modules folder are considered +// bundled deps as well. This list of names can be passed to npm-packlist +// as the "bundled" argument. Additionally, packageJsonCache is shared so +// packlist doesn't have to re-read files already consumed in this pass + +const fs = require('fs') +const path = require('path') +const EE = require('events').EventEmitter + +class BundleWalker extends EE { + constructor (opt) { + opt = opt || {} + super(opt) + this.path = path.resolve(opt.path || process.cwd()) + + this.parent = opt.parent || null + if (this.parent) { + this.result = this.parent.result + // only collect results in node_modules folders at the top level + // since the node_modules in a bundled dep is included always + if (!this.parent.parent) { + const base = path.basename(this.path) + const scope = path.basename(path.dirname(this.path)) + this.result.add(/^@/.test(scope) ? scope + '/' + base : base) + } + this.root = this.parent.root + this.packageJsonCache = this.parent.packageJsonCache + } else { + this.result = new Set() + this.root = this.path + this.packageJsonCache = opt.packageJsonCache || new Map() + } + + this.didDone = false + this.children = 0 + this.node_modules = [] + this.package = null + this.bundle = null + } + + done () { + if (!this.didDone) { + this.didDone = true + if (!this.parent) { + const res = Array.from(this.result) + this.result = res + this.emit('done', res) + } else { + this.emit('done') + } + } + } + + start () { + const pj = this.path + '/package.json' + if (this.packageJsonCache.has(pj)) + this.onPackage(this.packageJsonCache.get(pj)) + else + this.readPackageJson(pj) + return this + } + + readPackageJson (pj) { + fs.readFile(pj, (er, data) => + er ? this.done() : this.onPackageJson(pj, data)) + } + + onPackageJson (pj, data) { + try { + this.package = JSON.parse(data + '') + } catch (er) { + return this.done() + } + this.packageJsonCache.set(pj, this.package) + this.onPackage(this.package) + } + + onPackage (pkg) { + // all deps are bundled if we got here as a child. + // otherwise, only bundle bundledDeps + // Get a unique-ified array with a short-lived Set + const bdRaw = this.parent + ? Object.keys(pkg.dependencies || {}).concat( + Object.keys(pkg.optionalDependencies || {})) + : pkg.bundleDependencies || pkg.bundledDependencies || [] + + const bd = Array.from(new Set( + Array.isArray(bdRaw) ? bdRaw : Object.keys(bdRaw))) + + if (!bd.length) + return this.done() + + this.bundle = bd + const nm = this.path + '/node_modules' + this.readModules() + } + + readModules () { + readdirNodeModules(this.path + '/node_modules', (er, nm) => + er ? this.onReaddir([]) : this.onReaddir(nm)) + } + + onReaddir (nm) { + // keep track of what we have, in case children need it + this.node_modules = nm + + this.bundle.forEach(dep => this.childDep(dep)) + if (this.children === 0) + this.done() + } + + childDep (dep) { + if (this.node_modules.indexOf(dep) !== -1) { + this.child(dep) + } else if (this.parent) { + this.parent.childDep(dep) + } + } + + child (dep) { + const p = this.path + '/node_modules/' + dep + this.children += 1 + const child = new BundleWalker({ + path: p, + parent: this + }) + child.on('done', _ => { + if (--this.children === 0) + this.done() + }) + child.start() + } +} + +class BundleWalkerSync extends BundleWalker { + constructor (opt) { + super(opt) + } + + start () { + super.start() + this.done() + return this + } + + readPackageJson (pj) { + try { + this.onPackageJson(pj, fs.readFileSync(pj)) + } catch (er) {} + return this + } + + readModules () { + try { + this.onReaddir(readdirNodeModulesSync(this.path + '/node_modules')) + } catch (er) { + this.onReaddir([]) + } + } + + child (dep) { + new BundleWalkerSync({ + path: this.path + '/node_modules/' + dep, + parent: this + }).start() + } +} + +const readdirNodeModules = (nm, cb) => { + fs.readdir(nm, (er, set) => { + if (er) + cb(er) + else { + const scopes = set.filter(f => /^@/.test(f)) + if (!scopes.length) + cb(null, set) + else { + const unscoped = set.filter(f => !/^@/.test(f)) + let count = scopes.length + scopes.forEach(scope => { + fs.readdir(nm + '/' + scope, (er, pkgs) => { + if (er || !pkgs.length) + unscoped.push(scope) + else + unscoped.push.apply(unscoped, pkgs.map(p => scope + '/' + p)) + if (--count === 0) + cb(null, unscoped) + }) + }) + } + } + }) +} + +const readdirNodeModulesSync = nm => { + const set = fs.readdirSync(nm) + const unscoped = set.filter(f => !/^@/.test(f)) + const scopes = set.filter(f => /^@/.test(f)).map(scope => { + try { + const pkgs = fs.readdirSync(nm + '/' + scope) + return pkgs.length ? pkgs.map(p => scope + '/' + p) : [scope] + } catch (er) { + return [scope] + } + }).reduce((a, b) => a.concat(b), []) + return unscoped.concat(scopes) +} + +const walk = (options, callback) => { + const p = new Promise((resolve, reject) => { + new BundleWalker(options).on('done', resolve).on('error', reject).start() + }) + return callback ? p.then(res => callback(null, res), callback) : p +} + +const walkSync = options => { + return new BundleWalkerSync(options).start().result +} + +module.exports = walk +walk.sync = walkSync +walk.BundleWalker = BundleWalker +walk.BundleWalkerSync = BundleWalkerSync diff --git a/js/node_modules/fsevents/node_modules/npm-bundled/package.json b/js/node_modules/fsevents/node_modules/npm-bundled/package.json new file mode 100644 index 0000000..12663b7 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-bundled/package.json @@ -0,0 +1,63 @@ +{ + "_args": [ + [ + "npm-bundled@1.0.3", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "npm-bundled@1.0.3", + "_id": "npm-bundled@1.0.3", + "_inBundle": true, + "_integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "_location": "/fsevents/npm-bundled", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "npm-bundled@1.0.3", + "name": "npm-bundled", + "escapedName": "npm-bundled", + "rawSpec": "1.0.3", + "saveSpec": null, + "fetchSpec": "1.0.3" + }, + "_requiredBy": [ + "/fsevents/npm-packlist" + ], + "_resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "_spec": "1.0.3", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/npm/npm-bundled/issues" + }, + "description": "list things in node_modules that are bundledDependencies, or transitive dependencies thereof", + "devDependencies": { + "mkdirp": "^0.5.1", + "mutate-fs": "^1.1.0", + "rimraf": "^2.6.1", + "tap": "^10.3.2" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/npm/npm-bundled#readme", + "license": "ISC", + "main": "index.js", + "name": "npm-bundled", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/npm-bundled.git" + }, + "scripts": { + "postpublish": "git push origin --all; git push origin --tags", + "postversion": "npm publish", + "preversion": "npm test", + "test": "tap test/*.js -J --100" + }, + "version": "1.0.3" +} diff --git a/js/node_modules/fsevents/node_modules/npm-packlist/LICENSE b/js/node_modules/fsevents/node_modules/npm-packlist/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-packlist/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/npm-packlist/README.md b/js/node_modules/fsevents/node_modules/npm-packlist/README.md new file mode 100644 index 0000000..ead5821 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-packlist/README.md @@ -0,0 +1,68 @@ +# npm-packlist + +[![Build Status](https://travis-ci.com/npm/npm-packlist.svg?token=hHeDp9pQmz9kvsgRNVHy&branch=master)](https://travis-ci.com/npm/npm-packlist) + +Get a list of the files to add from a folder into an npm package + +These can be handed to [tar](http://npm.im/tar) like so to make an npm +package tarball: + +```js +const packlist = require('npm-packlist') +const tar = require('tar') +const packageDir = '/path/to/package' +const packageTarball = '/path/to/package.tgz' + +packlist({ path: packageDir }) + .then(files => tar.create({ + prefix: 'package/', + cwd: packageDir, + file: packageTarball, + gzip: true + }, files)) + .then(_ => { + // tarball has been created, continue with your day + }) +``` + +This uses the following rules: + +1. If a `package.json` file is found, and it has a `files` list, + then ignore everything that isn't in `files`. Always include the + readme, license, notice, changes, changelog, and history files, if + they exist, and the package.json file itself. +2. If there's no `package.json` file (or it has no `files` list), and + there is a `.npmignore` file, then ignore all the files in the + `.npmignore` file. +3. If there's no `package.json` with a `files` list, and there's no + `.npmignore` file, but there is a `.gitignore` file, then ignore + all the files in the `.gitignore` file. +4. Everything in the root `node_modules` is ignored, unless it's a + bundled dependency. If it IS a bundled dependency, and it's a + symbolic link, then the target of the link is included, not the + symlink itself. +4. Unless they're explicitly included (by being in a `files` list, or + a `!negated` rule in a relevant `.npmignore` or `.gitignore`), + always ignore certain common cruft files: + + 1. .npmignore and .gitignore files (their effect is in the package + already, there's no need to include them in the package) + 2. editor junk like `.*.swp`, `._*` and `.*.orig` files + 3. `.npmrc` files (these may contain private configs) + 4. The `node_modules/.bin` folder + 5. Waf and gyp cruft like `/build/config.gypi` and `.lock-wscript` + 6. Darwin's `.DS_Store` files because wtf are those even + 7. `npm-debug.log` files at the root of a project + + You can explicitly re-include any of these with a `files` list in + `package.json` or a negated ignore file rule. + +## API + +Same API as [ignore-walk](http://npm.im/ignore-walk), just hard-coded +file list and rule sets. + +The `Walker` and `WalkerSync` classes take a `bundled` argument, which +is a list of package names to include from node_modules. When calling +the top-level `packlist()` and `packlist.sync()` functions, this +module calls into `npm-bundled` directly. diff --git a/js/node_modules/fsevents/node_modules/npm-packlist/index.js b/js/node_modules/fsevents/node_modules/npm-packlist/index.js new file mode 100644 index 0000000..c1b8783 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-packlist/index.js @@ -0,0 +1,220 @@ +'use strict' + +// Do a two-pass walk, first to get the list of packages that need to be +// bundled, then again to get the actual files and folders. +// Keep a cache of node_modules content and package.json data, so that the +// second walk doesn't have to re-do all the same work. + +const bundleWalk = require('npm-bundled') +const BundleWalker = bundleWalk.BundleWalker +const BundleWalkerSync = bundleWalk.BundleWalkerSync + +const ignoreWalk = require('ignore-walk') +const IgnoreWalker = ignoreWalk.Walker +const IgnoreWalkerSync = ignoreWalk.WalkerSync + +const rootBuiltinRules = Symbol('root-builtin-rules') +const packageNecessaryRules = Symbol('package-necessary-rules') +const path = require('path') + +const defaultRules = [ + '.npmignore', + '.gitignore', + '**/.git/', + '**/.svn/', + '**/.hg/', + '**/CVS/', + '/.lock-wscript', + '/.wafpickle-*', + '/build/config.gypi', + 'npm-debug.log', + '**/.npmrc', + '.*.swp', + '.DS_Store', + '._*', + '*.orig', + 'package-lock.json' +] + +// a decorator that applies our custom rules to an ignore walker +const npmWalker = Class => class Walker extends Class { + constructor (opt) { + opt = opt || {} + + // the order in which rules are applied. + opt.ignoreFiles = [ + rootBuiltinRules, + 'package.json', + '.npmignore', + '.gitignore', + packageNecessaryRules + ] + + opt.includeEmpty = false + opt.path = opt.path || process.cwd() + opt.follow = path.basename(opt.path) === 'node_modules' + super(opt) + + // ignore a bunch of things by default at the root level. + // also ignore anything in node_modules, except bundled dependencies + if (!this.parent) { + this.bundled = opt.bundled || [] + this.bundledScopes = Array.from(new Set( + this.bundled.filter(f => /^@/.test(f)) + .map(f => f.split('/')[0]))) + const rules = defaultRules.join('\n') + '\n' + this.packageJsonCache = opt.packageJsonCache || new Map() + super.onReadIgnoreFile(rootBuiltinRules, rules, _=>_) + } else { + this.bundled = [] + this.bundledScopes = [] + this.packageJsonCache = this.parent.packageJsonCache + } + } + + filterEntry (entry, partial) { + // get the partial path from the root of the walk + const p = this.path.substr(this.root.length + 1) + const pkgre = /^node_modules\/(@[^\/]+\/?[^\/]+|[^\/]+)(\/.*)?$/ + const isRoot = !this.parent + const pkg = isRoot && pkgre.test(entry) ? + entry.replace(pkgre, '$1') : null + const rootNM = isRoot && entry === 'node_modules' + const rootPJ = isRoot && entry === 'package.json' + + return ( + // if we're in a bundled package, check with the parent. + /^node_modules($|\/)/i.test(p) ? this.parent.filterEntry( + this.basename + '/' + entry, partial) + + // if package is bundled, all files included + // also include @scope dirs for bundled scoped deps + // they'll be ignored if no files end up in them. + // However, this only matters if we're in the root. + // node_modules folders elsewhere, like lib/node_modules, + // should be included normally unless ignored. + : pkg ? -1 !== this.bundled.indexOf(pkg) || + -1 !== this.bundledScopes.indexOf(pkg) + + // only walk top node_modules if we want to bundle something + : rootNM ? !!this.bundled.length + + // always include package.json at the root. + : rootPJ ? true + + // otherwise, follow ignore-walk's logic + : super.filterEntry(entry, partial) + ) + } + + filterEntries () { + if (this.ignoreRules['package.json']) + this.ignoreRules['.gitignore'] = this.ignoreRules['.npmignore'] = null + else if (this.ignoreRules['.npmignore']) + this.ignoreRules['.gitignore'] = null + this.filterEntries = super.filterEntries + super.filterEntries() + } + + addIgnoreFile (file, then) { + const ig = path.resolve(this.path, file) + if (this.packageJsonCache.has(ig)) + this.onPackageJson(ig, this.packageJsonCache.get(ig), then) + else + super.addIgnoreFile(file, then) + } + + onPackageJson (ig, pkg, then) { + this.packageJsonCache.set(ig, pkg) + + // if there's a browser or main, make sure we don't ignore it + const rules = [ + pkg.browser ? '!' + pkg.browser : '', + pkg.main ? '!' + pkg.main : '', + '!@(readme|license|licence|notice|changes|changelog|history){,.*}' + ].filter(f => f).join('\n') + '\n' + super.onReadIgnoreFile(packageNecessaryRules, rules, _=>_) + + if (Array.isArray(pkg.files)) + super.onReadIgnoreFile('package.json', '*\n' + pkg.files.map( + f => '!' + f + '\n!' + f.replace(/\/+$/, '') + '/**' + ).join('\n') + '\n', then) + else + then() + } + + // override parent onstat function to nix all symlinks + onstat (st, entry, file, dir, then) { + if (st.isSymbolicLink()) + then() + else + super.onstat(st, entry, file, dir, then) + } + + onReadIgnoreFile (file, data, then) { + if (file === 'package.json') + try { + this.onPackageJson(file, JSON.parse(data), then) + } catch (er) { + // ignore package.json files that are not json + then() + } + else + super.onReadIgnoreFile(file, data, then) + } + + sort (a, b) { + return sort(a, b) + } +} + +class Walker extends npmWalker(IgnoreWalker) { + walker (entry, then) { + new Walker(this.walkerOpt(entry)).on('done', then).start() + } +} + +class WalkerSync extends npmWalker(IgnoreWalkerSync) { + walker (entry, then) { + new WalkerSync(this.walkerOpt(entry)).start() + then() + } +} + +const walk = (options, callback) => { + options = options || {} + const p = new Promise((resolve, reject) => { + const bw = new BundleWalker(options).start() + bw.on('done', bundled => { + options.bundled = bundled + options.packageJsonCache = bw.packageJsonCache + new Walker(options).on('done', resolve).on('error', reject).start() + }) + }) + return callback ? p.then(res => callback(null, res), callback) : p +} + +const walkSync = options => { + options = options || {} + const bw = new BundleWalkerSync(options).start() + options.bundled = bw.result + options.packageJsonCache = bw.packageJsonCache + const walker = new WalkerSync(options) + walker.start() + return walker.result +} + +// package.json first, node_modules last, files before folders, alphasort +const sort = (a, b) => + a === 'package.json' ? -1 + : b === 'package.json' ? 1 + : /^node_modules/.test(a) && !/^node_modules/.test(b) ? 1 + : /^node_modules/.test(b) && !/^node_modules/.test(a) ? -1 + : path.dirname(a) === '.' && path.dirname(b) !== '.' ? -1 + : path.dirname(b) === '.' && path.dirname(a) !== '.' ? 1 + : a.localeCompare(b) + +module.exports = walk +walk.sync = walkSync +walk.Walker = Walker +walk.WalkerSync = WalkerSync diff --git a/js/node_modules/fsevents/node_modules/npm-packlist/package.json b/js/node_modules/fsevents/node_modules/npm-packlist/package.json new file mode 100644 index 0000000..e4301b3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npm-packlist/package.json @@ -0,0 +1,69 @@ +{ + "_args": [ + [ + "npm-packlist@1.1.10", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "npm-packlist@1.1.10", + "_id": "npm-packlist@1.1.10", + "_inBundle": true, + "_integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "_location": "/fsevents/npm-packlist", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "npm-packlist@1.1.10", + "name": "npm-packlist", + "escapedName": "npm-packlist", + "rawSpec": "1.1.10", + "saveSpec": null, + "fetchSpec": "1.1.10" + }, + "_requiredBy": [ + "/fsevents/node-pre-gyp" + ], + "_resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "_spec": "1.1.10", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/npm/npm-packlist/issues" + }, + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + }, + "description": "Get a list of the files to add from a folder into an npm package", + "devDependencies": { + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "tap": "^10.7.2" + }, + "directories": { + "test": "test" + }, + "files": [ + "index.js" + ], + "homepage": "https://www.npmjs.com/package/npm-packlist", + "license": "ISC", + "main": "index.js", + "name": "npm-packlist", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/npm-packlist.git" + }, + "scripts": { + "postpublish": "git push origin --all; git push origin --tags", + "postversion": "npm publish", + "preversion": "npm test", + "test": "tap test/*.js --100 -J" + }, + "version": "1.1.10" +} diff --git a/js/node_modules/fsevents/node_modules/npmlog/CHANGELOG.md b/js/node_modules/fsevents/node_modules/npmlog/CHANGELOG.md new file mode 100644 index 0000000..51e4abc --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npmlog/CHANGELOG.md @@ -0,0 +1,49 @@ +### v4.0.2 + +* Added installation instructions. + +### v4.0.1 + +* Fix bugs where `log.progressEnabled` got out of sync with how `gauge` kept + track of these things resulting in a progressbar that couldn't be disabled. + +### v4.0.0 + +* Allow creating log levels that are an empty string or 0. + +### v3.1.2 + +* Update to `gauge@1.6.0` adding support for default values for template + items. + +### v3.1.1 + +* Update to `gauge@1.5.3` to fix to `1.x` compatibility when it comes to + when a progress bar is enabled. In `1.x` if you didn't have a TTY the + progress bar was never shown. In `2.x` it merely defaults to disabled, + but you can enable it explicitly if you still want progress updates. + +### v3.1.0 + +* Update to `gauge@2.5.2`: + * Updates the `signal-exit` dependency which fixes an incompatibility with + the node profiler. + * Uses externalizes its ansi code generation in `console-control-strings` +* Make the default progress bar include the last line printed, colored as it + would be when printing to a tty. + +### v3.0.0 + +* Switch to `gauge@2.0.0`, for better performance, better look. +* Set stderr/stdout blocking if they're tty's, so that we can hide a + progress bar going to stderr and then safely print to stdout. Without + this the two can end up overlapping producing confusing and sometimes + corrupted output. + +### v2.0.0 + +* Make the `error` event non-fatal so that folks can use it as a prefix. + +### v1.0.0 + +* Add progress bar with `gauge@1.1.0` diff --git a/js/node_modules/fsevents/node_modules/npmlog/LICENSE b/js/node_modules/fsevents/node_modules/npmlog/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npmlog/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/npmlog/README.md b/js/node_modules/fsevents/node_modules/npmlog/README.md new file mode 100644 index 0000000..268a4af --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npmlog/README.md @@ -0,0 +1,216 @@ +# npmlog + +The logger util that npm uses. + +This logger is very basic. It does the logging for npm. It supports +custom levels and colored output. + +By default, logs are written to stderr. If you want to send log messages +to outputs other than streams, then you can change the `log.stream` +member, or you can just listen to the events that it emits, and do +whatever you want with them. + +# Installation + +```console +npm install npmlog --save +``` + +# Basic Usage + +```javascript +var log = require('npmlog') + +// additional stuff ---------------------------+ +// message ----------+ | +// prefix ----+ | | +// level -+ | | | +// v v v v + log.info('fyi', 'I have a kitty cat: %j', myKittyCat) +``` + +## log.level + +* {String} + +The level to display logs at. Any logs at or above this level will be +displayed. The special level `silent` will prevent anything from being +displayed ever. + +## log.record + +* {Array} + +An array of all the log messages that have been entered. + +## log.maxRecordSize + +* {Number} + +The maximum number of records to keep. If log.record gets bigger than +10% over this value, then it is sliced down to 90% of this value. + +The reason for the 10% window is so that it doesn't have to resize a +large array on every log entry. + +## log.prefixStyle + +* {Object} + +A style object that specifies how prefixes are styled. (See below) + +## log.headingStyle + +* {Object} + +A style object that specifies how the heading is styled. (See below) + +## log.heading + +* {String} Default: "" + +If set, a heading that is printed at the start of every line. + +## log.stream + +* {Stream} Default: `process.stderr` + +The stream where output is written. + +## log.enableColor() + +Force colors to be used on all messages, regardless of the output +stream. + +## log.disableColor() + +Disable colors on all messages. + +## log.enableProgress() + +Enable the display of log activity spinner and progress bar + +## log.disableProgress() + +Disable the display of a progress bar + +## log.enableUnicode() + +Force the unicode theme to be used for the progress bar. + +## log.disableUnicode() + +Disable the use of unicode in the progress bar. + +## log.setGaugeTemplate(template) + +Set a template for outputting the progress bar. See the [gauge documentation] for details. + +[gauge documentation]: https://npmjs.com/package/gauge + +## log.setGaugeThemeset(themes) + +Select a themeset to pick themes from for the progress bar. See the [gauge documentation] for details. + +## log.pause() + +Stop emitting messages to the stream, but do not drop them. + +## log.resume() + +Emit all buffered messages that were written while paused. + +## log.log(level, prefix, message, ...) + +* `level` {String} The level to emit the message at +* `prefix` {String} A string prefix. Set to "" to skip. +* `message...` Arguments to `util.format` + +Emit a log message at the specified level. + +## log\[level](prefix, message, ...) + +For example, + +* log.silly(prefix, message, ...) +* log.verbose(prefix, message, ...) +* log.info(prefix, message, ...) +* log.http(prefix, message, ...) +* log.warn(prefix, message, ...) +* log.error(prefix, message, ...) + +Like `log.log(level, prefix, message, ...)`. In this way, each level is +given a shorthand, so you can do `log.info(prefix, message)`. + +## log.addLevel(level, n, style, disp) + +* `level` {String} Level indicator +* `n` {Number} The numeric level +* `style` {Object} Object with fg, bg, inverse, etc. +* `disp` {String} Optional replacement for `level` in the output. + +Sets up a new level with a shorthand function and so forth. + +Note that if the number is `Infinity`, then setting the level to that +will cause all log messages to be suppressed. If the number is +`-Infinity`, then the only way to show it is to enable all log messages. + +## log.newItem(name, todo, weight) + +* `name` {String} Optional; progress item name. +* `todo` {Number} Optional; total amount of work to be done. Default 0. +* `weight` {Number} Optional; the weight of this item relative to others. Default 1. + +This adds a new `are-we-there-yet` item tracker to the progress tracker. The +object returned has the `log[level]` methods but is otherwise an +`are-we-there-yet` `Tracker` object. + +## log.newStream(name, todo, weight) + +This adds a new `are-we-there-yet` stream tracker to the progress tracker. The +object returned has the `log[level]` methods but is otherwise an +`are-we-there-yet` `TrackerStream` object. + +## log.newGroup(name, weight) + +This adds a new `are-we-there-yet` tracker group to the progress tracker. The +object returned has the `log[level]` methods but is otherwise an +`are-we-there-yet` `TrackerGroup` object. + +# Events + +Events are all emitted with the message object. + +* `log` Emitted for all messages +* `log.` Emitted for all messages with the `` level. +* `` Messages with prefixes also emit their prefix as an event. + +# Style Objects + +Style objects can have the following fields: + +* `fg` {String} Color for the foreground text +* `bg` {String} Color for the background +* `bold`, `inverse`, `underline` {Boolean} Set the associated property +* `bell` {Boolean} Make a noise (This is pretty annoying, probably.) + +# Message Objects + +Every log event is emitted with a message object, and the `log.record` +list contains all of them that have been created. They have the +following fields: + +* `id` {Number} +* `level` {String} +* `prefix` {String} +* `message` {String} Result of `util.format()` +* `messageRaw` {Array} Arguments to `util.format()` + +# Blocking TTYs + +We use [`set-blocking`](https://npmjs.com/package/set-blocking) to set +stderr and stdout blocking if they are tty's and have the setBlocking call. +This is a work around for an issue in early versions of Node.js 6.x, which +made stderr and stdout non-blocking on OSX. (They are always blocking +Windows and were never blocking on Linux.) `npmlog` needs them to be blocking +so that it can allow output to stdout and stderr to be interlaced. diff --git a/js/node_modules/fsevents/node_modules/npmlog/log.js b/js/node_modules/fsevents/node_modules/npmlog/log.js new file mode 100644 index 0000000..341f331 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npmlog/log.js @@ -0,0 +1,309 @@ +'use strict' +var Progress = require('are-we-there-yet') +var Gauge = require('gauge') +var EE = require('events').EventEmitter +var log = exports = module.exports = new EE() +var util = require('util') + +var setBlocking = require('set-blocking') +var consoleControl = require('console-control-strings') + +setBlocking(true) +var stream = process.stderr +Object.defineProperty(log, 'stream', { + set: function (newStream) { + stream = newStream + if (this.gauge) this.gauge.setWriteTo(stream, stream) + }, + get: function () { + return stream + } +}) + +// by default, decide based on tty-ness. +var colorEnabled +log.useColor = function () { + return colorEnabled != null ? colorEnabled : stream.isTTY +} + +log.enableColor = function () { + colorEnabled = true + this.gauge.setTheme({hasColor: colorEnabled, hasUnicode: unicodeEnabled}) +} +log.disableColor = function () { + colorEnabled = false + this.gauge.setTheme({hasColor: colorEnabled, hasUnicode: unicodeEnabled}) +} + +// default level +log.level = 'info' + +log.gauge = new Gauge(stream, { + enabled: false, // no progress bars unless asked + theme: {hasColor: log.useColor()}, + template: [ + {type: 'progressbar', length: 20}, + {type: 'activityIndicator', kerning: 1, length: 1}, + {type: 'section', default: ''}, + ':', + {type: 'logline', kerning: 1, default: ''} + ] +}) + +log.tracker = new Progress.TrackerGroup() + +// we track this separately as we may need to temporarily disable the +// display of the status bar for our own loggy purposes. +log.progressEnabled = log.gauge.isEnabled() + +var unicodeEnabled + +log.enableUnicode = function () { + unicodeEnabled = true + this.gauge.setTheme({hasColor: this.useColor(), hasUnicode: unicodeEnabled}) +} + +log.disableUnicode = function () { + unicodeEnabled = false + this.gauge.setTheme({hasColor: this.useColor(), hasUnicode: unicodeEnabled}) +} + +log.setGaugeThemeset = function (themes) { + this.gauge.setThemeset(themes) +} + +log.setGaugeTemplate = function (template) { + this.gauge.setTemplate(template) +} + +log.enableProgress = function () { + if (this.progressEnabled) return + this.progressEnabled = true + this.tracker.on('change', this.showProgress) + if (this._pause) return + this.gauge.enable() +} + +log.disableProgress = function () { + if (!this.progressEnabled) return + this.progressEnabled = false + this.tracker.removeListener('change', this.showProgress) + this.gauge.disable() +} + +var trackerConstructors = ['newGroup', 'newItem', 'newStream'] + +var mixinLog = function (tracker) { + // mixin the public methods from log into the tracker + // (except: conflicts and one's we handle specially) + Object.keys(log).forEach(function (P) { + if (P[0] === '_') return + if (trackerConstructors.filter(function (C) { return C === P }).length) return + if (tracker[P]) return + if (typeof log[P] !== 'function') return + var func = log[P] + tracker[P] = function () { + return func.apply(log, arguments) + } + }) + // if the new tracker is a group, make sure any subtrackers get + // mixed in too + if (tracker instanceof Progress.TrackerGroup) { + trackerConstructors.forEach(function (C) { + var func = tracker[C] + tracker[C] = function () { return mixinLog(func.apply(tracker, arguments)) } + }) + } + return tracker +} + +// Add tracker constructors to the top level log object +trackerConstructors.forEach(function (C) { + log[C] = function () { return mixinLog(this.tracker[C].apply(this.tracker, arguments)) } +}) + +log.clearProgress = function (cb) { + if (!this.progressEnabled) return cb && process.nextTick(cb) + this.gauge.hide(cb) +} + +log.showProgress = function (name, completed) { + if (!this.progressEnabled) return + var values = {} + if (name) values.section = name + var last = log.record[log.record.length - 1] + if (last) { + values.subsection = last.prefix + var disp = log.disp[last.level] || last.level + var logline = this._format(disp, log.style[last.level]) + if (last.prefix) logline += ' ' + this._format(last.prefix, this.prefixStyle) + logline += ' ' + last.message.split(/\r?\n/)[0] + values.logline = logline + } + values.completed = completed || this.tracker.completed() + this.gauge.show(values) +}.bind(log) // bind for use in tracker's on-change listener + +// temporarily stop emitting, but don't drop +log.pause = function () { + this._paused = true + if (this.progressEnabled) this.gauge.disable() +} + +log.resume = function () { + if (!this._paused) return + this._paused = false + + var b = this._buffer + this._buffer = [] + b.forEach(function (m) { + this.emitLog(m) + }, this) + if (this.progressEnabled) this.gauge.enable() +} + +log._buffer = [] + +var id = 0 +log.record = [] +log.maxRecordSize = 10000 +log.log = function (lvl, prefix, message) { + var l = this.levels[lvl] + if (l === undefined) { + return this.emit('error', new Error(util.format( + 'Undefined log level: %j', lvl))) + } + + var a = new Array(arguments.length - 2) + var stack = null + for (var i = 2; i < arguments.length; i++) { + var arg = a[i - 2] = arguments[i] + + // resolve stack traces to a plain string. + if (typeof arg === 'object' && arg && + (arg instanceof Error) && arg.stack) { + + Object.defineProperty(arg, 'stack', { + value: stack = arg.stack + '', + enumerable: true, + writable: true + }) + } + } + if (stack) a.unshift(stack + '\n') + message = util.format.apply(util, a) + + var m = { id: id++, + level: lvl, + prefix: String(prefix || ''), + message: message, + messageRaw: a } + + this.emit('log', m) + this.emit('log.' + lvl, m) + if (m.prefix) this.emit(m.prefix, m) + + this.record.push(m) + var mrs = this.maxRecordSize + var n = this.record.length - mrs + if (n > mrs / 10) { + var newSize = Math.floor(mrs * 0.9) + this.record = this.record.slice(-1 * newSize) + } + + this.emitLog(m) +}.bind(log) + +log.emitLog = function (m) { + if (this._paused) { + this._buffer.push(m) + return + } + if (this.progressEnabled) this.gauge.pulse(m.prefix) + var l = this.levels[m.level] + if (l === undefined) return + if (l < this.levels[this.level]) return + if (l > 0 && !isFinite(l)) return + + // If 'disp' is null or undefined, use the lvl as a default + // Allows: '', 0 as valid disp + var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level + this.clearProgress() + m.message.split(/\r?\n/).forEach(function (line) { + if (this.heading) { + this.write(this.heading, this.headingStyle) + this.write(' ') + } + this.write(disp, log.style[m.level]) + var p = m.prefix || '' + if (p) this.write(' ') + this.write(p, this.prefixStyle) + this.write(' ' + line + '\n') + }, this) + this.showProgress() +} + +log._format = function (msg, style) { + if (!stream) return + + var output = '' + if (this.useColor()) { + style = style || {} + var settings = [] + if (style.fg) settings.push(style.fg) + if (style.bg) settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1)) + if (style.bold) settings.push('bold') + if (style.underline) settings.push('underline') + if (style.inverse) settings.push('inverse') + if (settings.length) output += consoleControl.color(settings) + if (style.beep) output += consoleControl.beep() + } + output += msg + if (this.useColor()) { + output += consoleControl.color('reset') + } + return output +} + +log.write = function (msg, style) { + if (!stream) return + + stream.write(this._format(msg, style)) +} + +log.addLevel = function (lvl, n, style, disp) { + // If 'disp' is null or undefined, use the lvl as a default + if (disp == null) disp = lvl + this.levels[lvl] = n + this.style[lvl] = style + if (!this[lvl]) { + this[lvl] = function () { + var a = new Array(arguments.length + 1) + a[0] = lvl + for (var i = 0; i < arguments.length; i++) { + a[i + 1] = arguments[i] + } + return this.log.apply(this, a) + }.bind(this) + } + this.disp[lvl] = disp +} + +log.prefixStyle = { fg: 'magenta' } +log.headingStyle = { fg: 'white', bg: 'black' } + +log.style = {} +log.levels = {} +log.disp = {} +log.addLevel('silly', -Infinity, { inverse: true }, 'sill') +log.addLevel('verbose', 1000, { fg: 'blue', bg: 'black' }, 'verb') +log.addLevel('info', 2000, { fg: 'green' }) +log.addLevel('timing', 2500, { fg: 'green', bg: 'black' }) +log.addLevel('http', 3000, { fg: 'green', bg: 'black' }) +log.addLevel('notice', 3500, { fg: 'blue', bg: 'black' }) +log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN') +log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!') +log.addLevel('silent', Infinity) + +// allow 'error' prefix +log.on('error', function () {}) diff --git a/js/node_modules/fsevents/node_modules/npmlog/package.json b/js/node_modules/fsevents/node_modules/npmlog/package.json new file mode 100644 index 0000000..0a63144 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/npmlog/package.json @@ -0,0 +1,64 @@ +{ + "_args": [ + [ + "npmlog@4.1.2", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "npmlog@4.1.2", + "_id": "npmlog@4.1.2", + "_inBundle": true, + "_integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "_location": "/fsevents/npmlog", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "npmlog@4.1.2", + "name": "npmlog", + "escapedName": "npmlog", + "rawSpec": "4.1.2", + "saveSpec": null, + "fetchSpec": "4.1.2" + }, + "_requiredBy": [ + "/fsevents/node-pre-gyp" + ], + "_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "_spec": "4.1.2", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/npm/npmlog/issues" + }, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + }, + "description": "logger for npm", + "devDependencies": { + "standard": "~7.1.2", + "tap": "~5.7.3" + }, + "files": [ + "log.js" + ], + "homepage": "https://github.com/npm/npmlog#readme", + "license": "ISC", + "main": "log.js", + "name": "npmlog", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/npmlog.git" + }, + "scripts": { + "test": "standard && tap test/*.js" + }, + "version": "4.1.2" +} diff --git a/js/node_modules/fsevents/node_modules/number-is-nan/index.js b/js/node_modules/fsevents/node_modules/number-is-nan/index.js new file mode 100644 index 0000000..79be4b9 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/number-is-nan/index.js @@ -0,0 +1,4 @@ +'use strict'; +module.exports = Number.isNaN || function (x) { + return x !== x; +}; diff --git a/js/node_modules/fsevents/node_modules/number-is-nan/license b/js/node_modules/fsevents/node_modules/number-is-nan/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/number-is-nan/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/number-is-nan/package.json b/js/node_modules/fsevents/node_modules/number-is-nan/package.json new file mode 100644 index 0000000..4cbc0c9 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/number-is-nan/package.json @@ -0,0 +1,70 @@ +{ + "_args": [ + [ + "number-is-nan@1.0.1", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "number-is-nan@1.0.1", + "_id": "number-is-nan@1.0.1", + "_inBundle": true, + "_integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "_location": "/fsevents/number-is-nan", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "number-is-nan@1.0.1", + "name": "number-is-nan", + "escapedName": "number-is-nan", + "rawSpec": "1.0.1", + "saveSpec": null, + "fetchSpec": "1.0.1" + }, + "_requiredBy": [ + "/fsevents/is-fullwidth-code-point" + ], + "_resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "_spec": "1.0.1", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/number-is-nan/issues" + }, + "description": "ES2015 Number.isNaN() ponyfill", + "devDependencies": { + "ava": "*" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/sindresorhus/number-is-nan#readme", + "keywords": [ + "es2015", + "ecmascript", + "ponyfill", + "polyfill", + "shim", + "number", + "is", + "nan", + "not" + ], + "license": "MIT", + "name": "number-is-nan", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/number-is-nan.git" + }, + "scripts": { + "test": "ava" + }, + "version": "1.0.1" +} diff --git a/js/node_modules/fsevents/node_modules/number-is-nan/readme.md b/js/node_modules/fsevents/node_modules/number-is-nan/readme.md new file mode 100644 index 0000000..2463508 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/number-is-nan/readme.md @@ -0,0 +1,28 @@ +# number-is-nan [![Build Status](https://travis-ci.org/sindresorhus/number-is-nan.svg?branch=master)](https://travis-ci.org/sindresorhus/number-is-nan) + +> ES2015 [`Number.isNaN()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) [ponyfill](https://ponyfill.com) + + +## Install + +``` +$ npm install --save number-is-nan +``` + + +## Usage + +```js +var numberIsNan = require('number-is-nan'); + +numberIsNan(NaN); +//=> true + +numberIsNan('unicorn'); +//=> false +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/js/node_modules/fsevents/node_modules/object-assign/index.js b/js/node_modules/fsevents/node_modules/object-assign/index.js new file mode 100644 index 0000000..0930cf8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/object-assign/index.js @@ -0,0 +1,90 @@ +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ + +'use strict'; +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; diff --git a/js/node_modules/fsevents/node_modules/object-assign/license b/js/node_modules/fsevents/node_modules/object-assign/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/object-assign/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/object-assign/package.json b/js/node_modules/fsevents/node_modules/object-assign/package.json new file mode 100644 index 0000000..0c08818 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/object-assign/package.json @@ -0,0 +1,77 @@ +{ + "_args": [ + [ + "object-assign@4.1.1", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "object-assign@4.1.1", + "_id": "object-assign@4.1.1", + "_inBundle": true, + "_integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "_location": "/fsevents/object-assign", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "object-assign@4.1.1", + "name": "object-assign", + "escapedName": "object-assign", + "rawSpec": "4.1.1", + "saveSpec": null, + "fetchSpec": "4.1.1" + }, + "_requiredBy": [ + "/fsevents/gauge" + ], + "_resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "_spec": "4.1.1", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/object-assign/issues" + }, + "description": "ES2015 `Object.assign()` ponyfill", + "devDependencies": { + "ava": "^0.16.0", + "lodash": "^4.16.4", + "matcha": "^0.7.0", + "xo": "^0.16.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/sindresorhus/object-assign#readme", + "keywords": [ + "object", + "assign", + "extend", + "properties", + "es2015", + "ecmascript", + "harmony", + "ponyfill", + "prollyfill", + "polyfill", + "shim", + "browser" + ], + "license": "MIT", + "name": "object-assign", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/object-assign.git" + }, + "scripts": { + "bench": "matcha bench.js", + "test": "xo && ava" + }, + "version": "4.1.1" +} diff --git a/js/node_modules/fsevents/node_modules/object-assign/readme.md b/js/node_modules/fsevents/node_modules/object-assign/readme.md new file mode 100644 index 0000000..1be09d3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/object-assign/readme.md @@ -0,0 +1,61 @@ +# object-assign [![Build Status](https://travis-ci.org/sindresorhus/object-assign.svg?branch=master)](https://travis-ci.org/sindresorhus/object-assign) + +> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com) + + +## Use the built-in + +Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari), +support `Object.assign()` :tada:. If you target only those environments, then by all +means, use `Object.assign()` instead of this package. + + +## Install + +``` +$ npm install --save object-assign +``` + + +## Usage + +```js +const objectAssign = require('object-assign'); + +objectAssign({foo: 0}, {bar: 1}); +//=> {foo: 0, bar: 1} + +// multiple sources +objectAssign({foo: 0}, {bar: 1}, {baz: 2}); +//=> {foo: 0, bar: 1, baz: 2} + +// overwrites equal keys +objectAssign({foo: 0}, {foo: 1}, {foo: 2}); +//=> {foo: 2} + +// ignores null and undefined sources +objectAssign({foo: 0}, null, {bar: 1}, undefined); +//=> {foo: 0, bar: 1} +``` + + +## API + +### objectAssign(target, [source, ...]) + +Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones. + + +## Resources + +- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign) + + +## Related + +- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()` + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/js/node_modules/fsevents/node_modules/once/LICENSE b/js/node_modules/fsevents/node_modules/once/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/once/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/once/README.md b/js/node_modules/fsevents/node_modules/once/README.md new file mode 100644 index 0000000..1f1ffca --- /dev/null +++ b/js/node_modules/fsevents/node_modules/once/README.md @@ -0,0 +1,79 @@ +# once + +Only call a function once. + +## usage + +```javascript +var once = require('once') + +function load (file, cb) { + cb = once(cb) + loader.load('file') + loader.once('load', cb) + loader.once('error', cb) +} +``` + +Or add to the Function.prototype in a responsible way: + +```javascript +// only has to be done once +require('once').proto() + +function load (file, cb) { + cb = cb.once() + loader.load('file') + loader.once('load', cb) + loader.once('error', cb) +} +``` + +Ironically, the prototype feature makes this module twice as +complicated as necessary. + +To check whether you function has been called, use `fn.called`. Once the +function is called for the first time the return value of the original +function is saved in `fn.value` and subsequent calls will continue to +return this value. + +```javascript +var once = require('once') + +function load (cb) { + cb = once(cb) + var stream = createStream() + stream.once('data', cb) + stream.once('end', function () { + if (!cb.called) cb(new Error('not found')) + }) +} +``` + +## `once.strict(func)` + +Throw an error if the function is called twice. + +Some functions are expected to be called only once. Using `once` for them would +potentially hide logical errors. + +In the example below, the `greet` function has to call the callback only once: + +```javascript +function greet (name, cb) { + // return is missing from the if statement + // when no name is passed, the callback is called twice + if (!name) cb('Hello anonymous') + cb('Hello ' + name) +} + +function log (msg) { + console.log(msg) +} + +// this will print 'Hello anonymous' but the logical error will be missed +greet(null, once(msg)) + +// once.strict will print 'Hello anonymous' and throw an error when the callback will be called the second time +greet(null, once.strict(msg)) +``` diff --git a/js/node_modules/fsevents/node_modules/once/once.js b/js/node_modules/fsevents/node_modules/once/once.js new file mode 100644 index 0000000..2354067 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/once/once.js @@ -0,0 +1,42 @@ +var wrappy = require('wrappy') +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} diff --git a/js/node_modules/fsevents/node_modules/once/package.json b/js/node_modules/fsevents/node_modules/once/package.json new file mode 100644 index 0000000..5050a14 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/once/package.json @@ -0,0 +1,70 @@ +{ + "_args": [ + [ + "once@1.4.0", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "once@1.4.0", + "_id": "once@1.4.0", + "_inBundle": true, + "_integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "_location": "/fsevents/once", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "once@1.4.0", + "name": "once", + "escapedName": "once", + "rawSpec": "1.4.0", + "saveSpec": null, + "fetchSpec": "1.4.0" + }, + "_requiredBy": [ + "/fsevents/glob", + "/fsevents/inflight" + ], + "_resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "_spec": "1.4.0", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/isaacs/once/issues" + }, + "dependencies": { + "wrappy": "1" + }, + "description": "Run a function exactly one time", + "devDependencies": { + "tap": "^7.0.1" + }, + "directories": { + "test": "test" + }, + "files": [ + "once.js" + ], + "homepage": "https://github.com/isaacs/once#readme", + "keywords": [ + "once", + "function", + "one", + "single" + ], + "license": "ISC", + "main": "once.js", + "name": "once", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/once.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "1.4.0" +} diff --git a/js/node_modules/fsevents/node_modules/os-homedir/index.js b/js/node_modules/fsevents/node_modules/os-homedir/index.js new file mode 100644 index 0000000..3306616 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-homedir/index.js @@ -0,0 +1,24 @@ +'use strict'; +var os = require('os'); + +function homedir() { + var env = process.env; + var home = env.HOME; + var user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME; + + if (process.platform === 'win32') { + return env.USERPROFILE || env.HOMEDRIVE + env.HOMEPATH || home || null; + } + + if (process.platform === 'darwin') { + return home || (user ? '/Users/' + user : null); + } + + if (process.platform === 'linux') { + return home || (process.getuid() === 0 ? '/root' : (user ? '/home/' + user : null)); + } + + return home || null; +} + +module.exports = typeof os.homedir === 'function' ? os.homedir : homedir; diff --git a/js/node_modules/fsevents/node_modules/os-homedir/license b/js/node_modules/fsevents/node_modules/os-homedir/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-homedir/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/os-homedir/package.json b/js/node_modules/fsevents/node_modules/os-homedir/package.json new file mode 100644 index 0000000..26493ea --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-homedir/package.json @@ -0,0 +1,76 @@ +{ + "_args": [ + [ + "os-homedir@1.0.2", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "os-homedir@1.0.2", + "_id": "os-homedir@1.0.2", + "_inBundle": true, + "_integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "_location": "/fsevents/os-homedir", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "os-homedir@1.0.2", + "name": "os-homedir", + "escapedName": "os-homedir", + "rawSpec": "1.0.2", + "saveSpec": null, + "fetchSpec": "1.0.2" + }, + "_requiredBy": [ + "/fsevents/osenv" + ], + "_resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "_spec": "1.0.2", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/os-homedir/issues" + }, + "description": "Node.js 4 `os.homedir()` ponyfill", + "devDependencies": { + "ava": "*", + "path-exists": "^2.0.0", + "xo": "^0.16.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/sindresorhus/os-homedir#readme", + "keywords": [ + "builtin", + "core", + "ponyfill", + "polyfill", + "shim", + "os", + "homedir", + "home", + "dir", + "directory", + "folder", + "user", + "path" + ], + "license": "MIT", + "name": "os-homedir", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/os-homedir.git" + }, + "scripts": { + "test": "xo && ava" + }, + "version": "1.0.2" +} diff --git a/js/node_modules/fsevents/node_modules/os-homedir/readme.md b/js/node_modules/fsevents/node_modules/os-homedir/readme.md new file mode 100644 index 0000000..856ae61 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-homedir/readme.md @@ -0,0 +1,31 @@ +# os-homedir [![Build Status](https://travis-ci.org/sindresorhus/os-homedir.svg?branch=master)](https://travis-ci.org/sindresorhus/os-homedir) + +> Node.js 4 [`os.homedir()`](https://nodejs.org/api/os.html#os_os_homedir) [ponyfill](https://ponyfill.com) + + +## Install + +``` +$ npm install --save os-homedir +``` + + +## Usage + +```js +const osHomedir = require('os-homedir'); + +console.log(osHomedir()); +//=> '/Users/sindresorhus' +``` + + +## Related + +- [user-home](https://github.com/sindresorhus/user-home) - Same as this module but caches the result +- [home-or-tmp](https://github.com/sindresorhus/home-or-tmp) - Get the user home directory with fallback to the system temp directory + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/js/node_modules/fsevents/node_modules/os-tmpdir/index.js b/js/node_modules/fsevents/node_modules/os-tmpdir/index.js new file mode 100644 index 0000000..2077b1c --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-tmpdir/index.js @@ -0,0 +1,25 @@ +'use strict'; +var isWindows = process.platform === 'win32'; +var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/; + +// https://github.com/nodejs/node/blob/3e7a14381497a3b73dda68d05b5130563cdab420/lib/os.js#L25-L43 +module.exports = function () { + var path; + + if (isWindows) { + path = process.env.TEMP || + process.env.TMP || + (process.env.SystemRoot || process.env.windir) + '\\temp'; + } else { + path = process.env.TMPDIR || + process.env.TMP || + process.env.TEMP || + '/tmp'; + } + + if (trailingSlashRe.test(path)) { + path = path.slice(0, -1); + } + + return path; +}; diff --git a/js/node_modules/fsevents/node_modules/os-tmpdir/license b/js/node_modules/fsevents/node_modules/os-tmpdir/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-tmpdir/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/os-tmpdir/package.json b/js/node_modules/fsevents/node_modules/os-tmpdir/package.json new file mode 100644 index 0000000..3f075a0 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-tmpdir/package.json @@ -0,0 +1,76 @@ +{ + "_args": [ + [ + "os-tmpdir@1.0.2", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "os-tmpdir@1.0.2", + "_id": "os-tmpdir@1.0.2", + "_inBundle": true, + "_integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "_location": "/fsevents/os-tmpdir", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "os-tmpdir@1.0.2", + "name": "os-tmpdir", + "escapedName": "os-tmpdir", + "rawSpec": "1.0.2", + "saveSpec": null, + "fetchSpec": "1.0.2" + }, + "_requiredBy": [ + "/fsevents/osenv" + ], + "_resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "_spec": "1.0.2", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/os-tmpdir/issues" + }, + "description": "Node.js os.tmpdir() ponyfill", + "devDependencies": { + "ava": "*", + "xo": "^0.16.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/sindresorhus/os-tmpdir#readme", + "keywords": [ + "built-in", + "core", + "ponyfill", + "polyfill", + "shim", + "os", + "tmpdir", + "tempdir", + "tmp", + "temp", + "dir", + "directory", + "env", + "environment" + ], + "license": "MIT", + "name": "os-tmpdir", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/os-tmpdir.git" + }, + "scripts": { + "test": "xo && ava" + }, + "version": "1.0.2" +} diff --git a/js/node_modules/fsevents/node_modules/os-tmpdir/readme.md b/js/node_modules/fsevents/node_modules/os-tmpdir/readme.md new file mode 100644 index 0000000..c09f7ed --- /dev/null +++ b/js/node_modules/fsevents/node_modules/os-tmpdir/readme.md @@ -0,0 +1,32 @@ +# os-tmpdir [![Build Status](https://travis-ci.org/sindresorhus/os-tmpdir.svg?branch=master)](https://travis-ci.org/sindresorhus/os-tmpdir) + +> Node.js [`os.tmpdir()`](https://nodejs.org/api/os.html#os_os_tmpdir) [ponyfill](https://ponyfill.com) + +Use this instead of `require('os').tmpdir()` to get a consistent behavior on different Node.js versions (even 0.8). + + +## Install + +``` +$ npm install --save os-tmpdir +``` + + +## Usage + +```js +const osTmpdir = require('os-tmpdir'); + +osTmpdir(); +//=> '/var/folders/m3/5574nnhn0yj488ccryqr7tc80000gn/T' +``` + + +## API + +See the [`os.tmpdir()` docs](https://nodejs.org/api/os.html#os_os_tmpdir). + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/js/node_modules/fsevents/node_modules/osenv/LICENSE b/js/node_modules/fsevents/node_modules/osenv/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/osenv/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/osenv/README.md b/js/node_modules/fsevents/node_modules/osenv/README.md new file mode 100644 index 0000000..08fd900 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/osenv/README.md @@ -0,0 +1,63 @@ +# osenv + +Look up environment settings specific to different operating systems. + +## Usage + +```javascript +var osenv = require('osenv') +var path = osenv.path() +var user = osenv.user() +// etc. + +// Some things are not reliably in the env, and have a fallback command: +var h = osenv.hostname(function (er, hostname) { + h = hostname +}) +// This will still cause it to be memoized, so calling osenv.hostname() +// is now an immediate operation. + +// You can always send a cb, which will get called in the nextTick +// if it's been memoized, or wait for the fallback data if it wasn't +// found in the environment. +osenv.hostname(function (er, hostname) { + if (er) console.error('error looking up hostname') + else console.log('this machine calls itself %s', hostname) +}) +``` + +## osenv.hostname() + +The machine name. Calls `hostname` if not found. + +## osenv.user() + +The currently logged-in user. Calls `whoami` if not found. + +## osenv.prompt() + +Either PS1 on unix, or PROMPT on Windows. + +## osenv.tmpdir() + +The place where temporary files should be created. + +## osenv.home() + +No place like it. + +## osenv.path() + +An array of the places that the operating system will search for +executables. + +## osenv.editor() + +Return the executable name of the editor program. This uses the EDITOR +and VISUAL environment variables, and falls back to `vi` on Unix, or +`notepad.exe` on Windows. + +## osenv.shell() + +The SHELL on Unix, which Windows calls the ComSpec. Defaults to 'bash' +or 'cmd'. diff --git a/js/node_modules/fsevents/node_modules/osenv/osenv.js b/js/node_modules/fsevents/node_modules/osenv/osenv.js new file mode 100644 index 0000000..702a95b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/osenv/osenv.js @@ -0,0 +1,72 @@ +var isWindows = process.platform === 'win32' +var path = require('path') +var exec = require('child_process').exec +var osTmpdir = require('os-tmpdir') +var osHomedir = require('os-homedir') + +// looking up envs is a bit costly. +// Also, sometimes we want to have a fallback +// Pass in a callback to wait for the fallback on failures +// After the first lookup, always returns the same thing. +function memo (key, lookup, fallback) { + var fell = false + var falling = false + exports[key] = function (cb) { + var val = lookup() + if (!val && !fell && !falling && fallback) { + fell = true + falling = true + exec(fallback, function (er, output, stderr) { + falling = false + if (er) return // oh well, we tried + val = output.trim() + }) + } + exports[key] = function (cb) { + if (cb) process.nextTick(cb.bind(null, null, val)) + return val + } + if (cb && !falling) process.nextTick(cb.bind(null, null, val)) + return val + } +} + +memo('user', function () { + return ( isWindows + ? process.env.USERDOMAIN + '\\' + process.env.USERNAME + : process.env.USER + ) +}, 'whoami') + +memo('prompt', function () { + return isWindows ? process.env.PROMPT : process.env.PS1 +}) + +memo('hostname', function () { + return isWindows ? process.env.COMPUTERNAME : process.env.HOSTNAME +}, 'hostname') + +memo('tmpdir', function () { + return osTmpdir() +}) + +memo('home', function () { + return osHomedir() +}) + +memo('path', function () { + return (process.env.PATH || + process.env.Path || + process.env.path).split(isWindows ? ';' : ':') +}) + +memo('editor', function () { + return process.env.EDITOR || + process.env.VISUAL || + (isWindows ? 'notepad.exe' : 'vi') +}) + +memo('shell', function () { + return isWindows ? process.env.ComSpec || 'cmd' + : process.env.SHELL || 'bash' +}) diff --git a/js/node_modules/fsevents/node_modules/osenv/package.json b/js/node_modules/fsevents/node_modules/osenv/package.json new file mode 100644 index 0000000..0ab79e0 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/osenv/package.json @@ -0,0 +1,76 @@ +{ + "_args": [ + [ + "osenv@0.1.5", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "osenv@0.1.5", + "_id": "osenv@0.1.5", + "_inBundle": true, + "_integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "_location": "/fsevents/osenv", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "osenv@0.1.5", + "name": "osenv", + "escapedName": "osenv", + "rawSpec": "0.1.5", + "saveSpec": null, + "fetchSpec": "0.1.5" + }, + "_requiredBy": [ + "/fsevents/nopt" + ], + "_resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "_spec": "0.1.5", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/npm/osenv/issues" + }, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + }, + "description": "Look up environment settings specific to different operating systems", + "devDependencies": { + "tap": "^11.1.0" + }, + "directories": { + "test": "test" + }, + "files": [ + "osenv.js" + ], + "homepage": "https://github.com/npm/osenv#readme", + "keywords": [ + "environment", + "variable", + "home", + "tmpdir", + "path", + "prompt", + "ps1" + ], + "license": "ISC", + "main": "osenv.js", + "name": "osenv", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/osenv.git" + }, + "scripts": { + "postpublish": "git push origin --all; git push origin --tags", + "postversion": "npm publish", + "preversion": "npm test", + "test": "tap test/*.js" + }, + "version": "0.1.5" +} diff --git a/js/node_modules/fsevents/node_modules/path-is-absolute/index.js b/js/node_modules/fsevents/node_modules/path-is-absolute/index.js new file mode 100644 index 0000000..22aa6c3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/path-is-absolute/index.js @@ -0,0 +1,20 @@ +'use strict'; + +function posix(path) { + return path.charAt(0) === '/'; +} + +function win32(path) { + // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 + var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + var result = splitDeviceRe.exec(path); + var device = result[1] || ''; + var isUnc = Boolean(device && device.charAt(1) !== ':'); + + // UNC paths are always absolute + return Boolean(result[2] || isUnc); +} + +module.exports = process.platform === 'win32' ? win32 : posix; +module.exports.posix = posix; +module.exports.win32 = win32; diff --git a/js/node_modules/fsevents/node_modules/path-is-absolute/license b/js/node_modules/fsevents/node_modules/path-is-absolute/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/path-is-absolute/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/path-is-absolute/package.json b/js/node_modules/fsevents/node_modules/path-is-absolute/package.json new file mode 100644 index 0000000..2e73f46 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/path-is-absolute/package.json @@ -0,0 +1,78 @@ +{ + "_args": [ + [ + "path-is-absolute@1.0.1", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "path-is-absolute@1.0.1", + "_id": "path-is-absolute@1.0.1", + "_inBundle": true, + "_integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "_location": "/fsevents/path-is-absolute", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "path-is-absolute@1.0.1", + "name": "path-is-absolute", + "escapedName": "path-is-absolute", + "rawSpec": "1.0.1", + "saveSpec": null, + "fetchSpec": "1.0.1" + }, + "_requiredBy": [ + "/fsevents/glob" + ], + "_resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "_spec": "1.0.1", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/path-is-absolute/issues" + }, + "description": "Node.js 0.12 path.isAbsolute() ponyfill", + "devDependencies": { + "xo": "^0.16.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/sindresorhus/path-is-absolute#readme", + "keywords": [ + "path", + "paths", + "file", + "dir", + "absolute", + "isabsolute", + "is-absolute", + "built-in", + "util", + "utils", + "core", + "ponyfill", + "polyfill", + "shim", + "is", + "detect", + "check" + ], + "license": "MIT", + "name": "path-is-absolute", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/path-is-absolute.git" + }, + "scripts": { + "test": "xo && node test.js" + }, + "version": "1.0.1" +} diff --git a/js/node_modules/fsevents/node_modules/path-is-absolute/readme.md b/js/node_modules/fsevents/node_modules/path-is-absolute/readme.md new file mode 100644 index 0000000..8dbdf5f --- /dev/null +++ b/js/node_modules/fsevents/node_modules/path-is-absolute/readme.md @@ -0,0 +1,59 @@ +# path-is-absolute [![Build Status](https://travis-ci.org/sindresorhus/path-is-absolute.svg?branch=master)](https://travis-ci.org/sindresorhus/path-is-absolute) + +> Node.js 0.12 [`path.isAbsolute()`](http://nodejs.org/api/path.html#path_path_isabsolute_path) [ponyfill](https://ponyfill.com) + + +## Install + +``` +$ npm install --save path-is-absolute +``` + + +## Usage + +```js +const pathIsAbsolute = require('path-is-absolute'); + +// Running on Linux +pathIsAbsolute('/home/foo'); +//=> true +pathIsAbsolute('C:/Users/foo'); +//=> false + +// Running on Windows +pathIsAbsolute('C:/Users/foo'); +//=> true +pathIsAbsolute('/home/foo'); +//=> false + +// Running on any OS +pathIsAbsolute.posix('/home/foo'); +//=> true +pathIsAbsolute.posix('C:/Users/foo'); +//=> false +pathIsAbsolute.win32('C:/Users/foo'); +//=> true +pathIsAbsolute.win32('/home/foo'); +//=> false +``` + + +## API + +See the [`path.isAbsolute()` docs](http://nodejs.org/api/path.html#path_path_isabsolute_path). + +### pathIsAbsolute(path) + +### pathIsAbsolute.posix(path) + +POSIX specific version. + +### pathIsAbsolute.win32(path) + +Windows specific version. + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/js/node_modules/fsevents/node_modules/process-nextick-args/index.js b/js/node_modules/fsevents/node_modules/process-nextick-args/index.js new file mode 100644 index 0000000..5f585e8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/process-nextick-args/index.js @@ -0,0 +1,44 @@ +'use strict'; + +if (!process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + diff --git a/js/node_modules/fsevents/node_modules/process-nextick-args/license.md b/js/node_modules/fsevents/node_modules/process-nextick-args/license.md new file mode 100644 index 0000000..c67e353 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/process-nextick-args/license.md @@ -0,0 +1,19 @@ +# Copyright (c) 2015 Calvin Metcalf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.** diff --git a/js/node_modules/fsevents/node_modules/process-nextick-args/package.json b/js/node_modules/fsevents/node_modules/process-nextick-args/package.json new file mode 100644 index 0000000..01bbb76 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/process-nextick-args/package.json @@ -0,0 +1,53 @@ +{ + "_args": [ + [ + "process-nextick-args@2.0.0", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "process-nextick-args@2.0.0", + "_id": "process-nextick-args@2.0.0", + "_inBundle": true, + "_integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "_location": "/fsevents/process-nextick-args", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "process-nextick-args@2.0.0", + "name": "process-nextick-args", + "escapedName": "process-nextick-args", + "rawSpec": "2.0.0", + "saveSpec": null, + "fetchSpec": "2.0.0" + }, + "_requiredBy": [ + "/fsevents/readable-stream" + ], + "_resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "_spec": "2.0.0", + "_where": "/Users/eshanker/Code/fsevents", + "author": "", + "bugs": { + "url": "https://github.com/calvinmetcalf/process-nextick-args/issues" + }, + "description": "process.nextTick but always with args", + "devDependencies": { + "tap": "~0.2.6" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/calvinmetcalf/process-nextick-args", + "license": "MIT", + "main": "index.js", + "name": "process-nextick-args", + "repository": { + "type": "git", + "url": "git+https://github.com/calvinmetcalf/process-nextick-args.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "2.0.0" +} diff --git a/js/node_modules/fsevents/node_modules/process-nextick-args/readme.md b/js/node_modules/fsevents/node_modules/process-nextick-args/readme.md new file mode 100644 index 0000000..ecb432c --- /dev/null +++ b/js/node_modules/fsevents/node_modules/process-nextick-args/readme.md @@ -0,0 +1,18 @@ +process-nextick-args +===== + +[![Build Status](https://travis-ci.org/calvinmetcalf/process-nextick-args.svg?branch=master)](https://travis-ci.org/calvinmetcalf/process-nextick-args) + +```bash +npm install --save process-nextick-args +``` + +Always be able to pass arguments to process.nextTick, no matter the platform + +```js +var pna = require('process-nextick-args'); + +pna.nextTick(function (a, b, c) { + console.log(a, b, c); +}, 'step', 3, 'profit'); +``` diff --git a/js/node_modules/fsevents/node_modules/rc/.npmignore b/js/node_modules/fsevents/node_modules/rc/.npmignore new file mode 100644 index 0000000..13abef4 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/.npmignore @@ -0,0 +1,3 @@ +node_modules +node_modules/* +npm_debug.log diff --git a/js/node_modules/fsevents/node_modules/rc/LICENSE.APACHE2 b/js/node_modules/fsevents/node_modules/rc/LICENSE.APACHE2 new file mode 100644 index 0000000..6366c04 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/LICENSE.APACHE2 @@ -0,0 +1,15 @@ +Apache License, Version 2.0 + +Copyright (c) 2011 Dominic Tarr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/js/node_modules/fsevents/node_modules/rc/LICENSE.BSD b/js/node_modules/fsevents/node_modules/rc/LICENSE.BSD new file mode 100644 index 0000000..96bb796 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/LICENSE.BSD @@ -0,0 +1,26 @@ +Copyright (c) 2013, Dominic Tarr +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. diff --git a/js/node_modules/fsevents/node_modules/rc/LICENSE.MIT b/js/node_modules/fsevents/node_modules/rc/LICENSE.MIT new file mode 100644 index 0000000..6eafbd7 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/LICENSE.MIT @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2011 Dominic Tarr + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/rc/README.md b/js/node_modules/fsevents/node_modules/rc/README.md new file mode 100644 index 0000000..e6522e2 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/README.md @@ -0,0 +1,227 @@ +# rc + +The non-configurable configuration loader for lazy people. + +## Usage + +The only option is to pass rc the name of your app, and your default configuration. + +```javascript +var conf = require('rc')(appname, { + //defaults go here. + port: 2468, + + //defaults which are objects will be merged, not replaced + views: { + engine: 'jade' + } +}); +``` + +`rc` will return your configuration options merged with the defaults you specify. +If you pass in a predefined defaults object, it will be mutated: + +```javascript +var conf = {}; +require('rc')(appname, conf); +``` + +If `rc` finds any config files for your app, the returned config object will have +a `configs` array containing their paths: + +```javascript +var appCfg = require('rc')(appname, conf); +appCfg.configs[0] // /etc/appnamerc +appCfg.configs[1] // /home/dominictarr/.config/appname +appCfg.config // same as appCfg.configs[appCfg.configs.length - 1] +``` + +## Standards + +Given your application name (`appname`), rc will look in all the obvious places for configuration. + + * command line arguments, parsed by minimist _(e.g. `--foo baz`, also nested: `--foo.bar=baz`)_ + * environment variables prefixed with `${appname}_` + * or use "\_\_" to indicate nested properties
_(e.g. `appname_foo__bar__baz` => `foo.bar.baz`)_ + * if you passed an option `--config file` then from that file + * a local `.${appname}rc` or the first found looking in `./ ../ ../../ ../../../` etc. + * `$HOME/.${appname}rc` + * `$HOME/.${appname}/config` + * `$HOME/.config/${appname}` + * `$HOME/.config/${appname}/config` + * `/etc/${appname}rc` + * `/etc/${appname}/config` + * the defaults object you passed in. + +All configuration sources that were found will be flattened into one object, +so that sources **earlier** in this list override later ones. + + +## Configuration File Formats + +Configuration files (e.g. `.appnamerc`) may be in either [json](http://json.org/example) or [ini](http://en.wikipedia.org/wiki/INI_file) format. **No** file extension (`.json` or `.ini`) should be used. The example configurations below are equivalent: + + +#### Formatted as `ini` + +``` +; You can include comments in `ini` format if you want. + +dependsOn=0.10.0 + + +; `rc` has built-in support for ini sections, see? + +[commands] + www = ./commands/www + console = ./commands/repl + + +; You can even do nested sections + +[generators.options] + engine = ejs + +[generators.modules] + new = generate-new + engine = generate-backend + +``` + +#### Formatted as `json` + +```javascript +{ + // You can even comment your JSON, if you want + "dependsOn": "0.10.0", + "commands": { + "www": "./commands/www", + "console": "./commands/repl" + }, + "generators": { + "options": { + "engine": "ejs" + }, + "modules": { + "new": "generate-new", + "backend": "generate-backend" + } + } +} +``` + +Comments are stripped from JSON config via [strip-json-comments](https://github.com/sindresorhus/strip-json-comments). + +> Since ini, and env variables do not have a standard for types, your application needs be prepared for strings. + +To ensure that string representations of booleans and numbers are always converted into their proper types (especially useful if you intend to do strict `===` comparisons), consider using a module such as [parse-strings-in-object](https://github.com/anselanza/parse-strings-in-object) to wrap the config object returned from rc. + + +## Simple example demonstrating precedence +Assume you have an application like this (notice the hard-coded defaults passed to rc): +``` +const conf = require('rc')('myapp', { + port: 12345, + mode: 'test' +}); + +console.log(JSON.stringify(conf, null, 2)); +``` +You also have a file `config.json`, with these contents: +``` +{ + "port": 9000, + "foo": "from config json", + "something": "else" +} +``` +And a file `.myapprc` in the same folder, with these contents: +``` +{ + "port": "3001", + "foo": "bar" +} +``` +Here is the expected output from various commands: + +`node .` +``` +{ + "port": "3001", + "mode": "test", + "foo": "bar", + "_": [], + "configs": [ + "/Users/stephen/repos/conftest/.myapprc" + ], + "config": "/Users/stephen/repos/conftest/.myapprc" +} +``` +*Default `mode` from hard-coded object is retained, but port is overridden by `.myapprc` file (automatically found based on appname match), and `foo` is added.* + + +`node . --foo baz` +``` +{ + "port": "3001", + "mode": "test", + "foo": "baz", + "_": [], + "configs": [ + "/Users/stephen/repos/conftest/.myapprc" + ], + "config": "/Users/stephen/repos/conftest/.myapprc" +} +``` +*Same result as above but `foo` is overridden because command-line arguments take precedence over `.myapprc` file.* + +`node . --foo barbar --config config.json` +``` +{ + "port": 9000, + "mode": "test", + "foo": "barbar", + "something": "else", + "_": [], + "config": "config.json", + "configs": [ + "/Users/stephen/repos/conftest/.myapprc", + "config.json" + ] +} +``` +*Now the `port` comes from the `config.json` file specified (overriding the value from `.myapprc`), and `foo` value is overriden by command-line despite also being specified in the `config.json` file.* + + + +## Advanced Usage + +#### Pass in your own `argv` + +You may pass in your own `argv` as the third argument to `rc`. This is in case you want to [use your own command-line opts parser](https://github.com/dominictarr/rc/pull/12). + +```javascript +require('rc')(appname, defaults, customArgvParser); +``` + +## Pass in your own parser + +If you have a special need to use a non-standard parser, +you can do so by passing in the parser as the 4th argument. +(leave the 3rd as null to get the default args parser) + +```javascript +require('rc')(appname, defaults, null, parser); +``` + +This may also be used to force a more strict format, +such as strict, valid JSON only. + +## Note on Performance + +`rc` is running `fs.statSync`-- so make sure you don't use it in a hot code path (e.g. a request handler) + + +## License + +Multi-licensed under the two-clause BSD License, MIT License, or Apache License, version 2.0 diff --git a/js/node_modules/fsevents/node_modules/rc/browser.js b/js/node_modules/fsevents/node_modules/rc/browser.js new file mode 100644 index 0000000..8c230c5 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/browser.js @@ -0,0 +1,7 @@ + +// when this is loaded into the browser, +// just use the defaults... + +module.exports = function (name, defaults) { + return defaults +} diff --git a/js/node_modules/fsevents/node_modules/rc/cli.js b/js/node_modules/fsevents/node_modules/rc/cli.js new file mode 100755 index 0000000..ab05b60 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/cli.js @@ -0,0 +1,4 @@ +#! /usr/bin/env node +var rc = require('./index') + +console.log(JSON.stringify(rc(process.argv[2]), false, 2)) diff --git a/js/node_modules/fsevents/node_modules/rc/index.js b/js/node_modules/fsevents/node_modules/rc/index.js new file mode 100755 index 0000000..65eb47a --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/index.js @@ -0,0 +1,53 @@ +var cc = require('./lib/utils') +var join = require('path').join +var deepExtend = require('deep-extend') +var etc = '/etc' +var win = process.platform === "win32" +var home = win + ? process.env.USERPROFILE + : process.env.HOME + +module.exports = function (name, defaults, argv, parse) { + if('string' !== typeof name) + throw new Error('rc(name): name *must* be string') + if(!argv) + argv = require('minimist')(process.argv.slice(2)) + defaults = ( + 'string' === typeof defaults + ? cc.json(defaults) : defaults + ) || {} + + parse = parse || cc.parse + + var env = cc.env(name + '_') + + var configs = [defaults] + var configFiles = [] + function addConfigFile (file) { + if (configFiles.indexOf(file) >= 0) return + var fileConfig = cc.file(file) + if (fileConfig) { + configs.push(parse(fileConfig)) + configFiles.push(file) + } + } + + // which files do we look at? + if (!win) + [join(etc, name, 'config'), + join(etc, name + 'rc')].forEach(addConfigFile) + if (home) + [join(home, '.config', name, 'config'), + join(home, '.config', name), + join(home, '.' + name, 'config'), + join(home, '.' + name + 'rc')].forEach(addConfigFile) + addConfigFile(cc.find('.'+name+'rc')) + if (env.config) addConfigFile(env.config) + if (argv.config) addConfigFile(argv.config) + + return deepExtend.apply(null, configs.concat([ + env, + argv, + configFiles.length ? {configs: configFiles, config: configFiles[configFiles.length - 1]} : undefined, + ])) +} diff --git a/js/node_modules/fsevents/node_modules/rc/lib/utils.js b/js/node_modules/fsevents/node_modules/rc/lib/utils.js new file mode 100644 index 0000000..8b3beff --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/lib/utils.js @@ -0,0 +1,104 @@ +'use strict'; +var fs = require('fs') +var ini = require('ini') +var path = require('path') +var stripJsonComments = require('strip-json-comments') + +var parse = exports.parse = function (content) { + + //if it ends in .json or starts with { then it must be json. + //must be done this way, because ini accepts everything. + //can't just try and parse it and let it throw if it's not ini. + //everything is ini. even json with a syntax error. + + if(/^\s*{/.test(content)) + return JSON.parse(stripJsonComments(content)) + return ini.parse(content) + +} + +var file = exports.file = function () { + var args = [].slice.call(arguments).filter(function (arg) { return arg != null }) + + //path.join breaks if it's a not a string, so just skip this. + for(var i in args) + if('string' !== typeof args[i]) + return + + var file = path.join.apply(null, args) + var content + try { + return fs.readFileSync(file,'utf-8') + } catch (err) { + return + } +} + +var json = exports.json = function () { + var content = file.apply(null, arguments) + return content ? parse(content) : null +} + +var env = exports.env = function (prefix, env) { + env = env || process.env + var obj = {} + var l = prefix.length + for(var k in env) { + if(k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) { + + var keypath = k.substring(l).split('__') + + // Trim empty strings from keypath array + var _emptyStringIndex + while ((_emptyStringIndex=keypath.indexOf('')) > -1) { + keypath.splice(_emptyStringIndex, 1) + } + + var cursor = obj + keypath.forEach(function _buildSubObj(_subkey,i){ + + // (check for _subkey first so we ignore empty strings) + // (check for cursor to avoid assignment to primitive objects) + if (!_subkey || typeof cursor !== 'object') + return + + // If this is the last key, just stuff the value in there + // Assigns actual value from env variable to final key + // (unless it's just an empty string- in that case use the last valid key) + if (i === keypath.length-1) + cursor[_subkey] = env[k] + + + // Build sub-object if nothing already exists at the keypath + if (cursor[_subkey] === undefined) + cursor[_subkey] = {} + + // Increment cursor used to track the object at the current depth + cursor = cursor[_subkey] + + }) + + } + + } + + return obj +} + +var find = exports.find = function () { + var rel = path.join.apply(null, [].slice.call(arguments)) + + function find(start, rel) { + var file = path.join(start, rel) + try { + fs.statSync(file) + return file + } catch (err) { + if(path.dirname(start) !== start) // root + return find(path.dirname(start), rel) + } + } + return find(process.cwd(), rel) +} + + diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/.travis.yml b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/.travis.yml new file mode 100644 index 0000000..74c57bf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - "0.8" + - "0.10" + - "0.12" + - "iojs" +before_install: + - npm install -g npm@~1.4.6 diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/LICENSE b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/example/parse.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/example/parse.js new file mode 100644 index 0000000..abff3e8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/example/parse.js @@ -0,0 +1,2 @@ +var argv = require('../')(process.argv.slice(2)); +console.dir(argv); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/index.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/index.js new file mode 100644 index 0000000..6a0559d --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/index.js @@ -0,0 +1,236 @@ +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; + + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } + + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); + + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } + + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } + + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } + + var value = !flags.strings[key] && isNumber(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next, arg) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + notFlags.forEach(function(key) { + argv._.push(key); + }); + } + + return argv; +}; + +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function isNumber (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} + diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/package.json b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/package.json new file mode 100644 index 0000000..bb05425 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/package.json @@ -0,0 +1,76 @@ +{ + "_args": [ + [ + "minimist@1.2.0", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "minimist@1.2.0", + "_id": "minimist@1.2.0", + "_inBundle": true, + "_integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "_location": "/fsevents/rc/minimist", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "minimist@1.2.0", + "name": "minimist", + "escapedName": "minimist", + "rawSpec": "1.2.0", + "saveSpec": null, + "fetchSpec": "1.2.0" + }, + "_requiredBy": [ + "/fsevents/rc" + ], + "_resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "_spec": "1.2.0", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "bugs": { + "url": "https://github.com/substack/minimist/issues" + }, + "description": "parse argument options", + "devDependencies": { + "covert": "^1.0.0", + "tap": "~0.4.0", + "tape": "^3.5.0" + }, + "homepage": "https://github.com/substack/minimist", + "keywords": [ + "argv", + "getopt", + "parser", + "optimist" + ], + "license": "MIT", + "main": "index.js", + "name": "minimist", + "repository": { + "type": "git", + "url": "git://github.com/substack/minimist.git" + }, + "scripts": { + "coverage": "covert test/*.js", + "test": "tap test/*.js" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/6..latest", + "ff/5", + "firefox/latest", + "chrome/10", + "chrome/latest", + "safari/5.1", + "safari/latest", + "opera/12" + ] + }, + "version": "1.2.0" +} diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/readme.markdown b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/readme.markdown new file mode 100644 index 0000000..30a74cf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/readme.markdown @@ -0,0 +1,91 @@ +# minimist + +parse argument options + +This module is the guts of optimist's argument parser without all the +fanciful decoration. + +[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist) + +[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist) + +# example + +``` js +var argv = require('minimist')(process.argv.slice(2)); +console.dir(argv); +``` + +``` +$ node example/parse.js -a beep -b boop +{ _: [], a: 'beep', b: 'boop' } +``` + +``` +$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz +{ _: [ 'foo', 'bar', 'baz' ], + x: 3, + y: 4, + n: 5, + a: true, + b: true, + c: true, + beep: 'boop' } +``` + +# methods + +``` js +var parseArgs = require('minimist') +``` + +## var argv = parseArgs(args, opts={}) + +Return an argument object `argv` populated with the array arguments from `args`. + +`argv._` contains all the arguments that didn't have an option associated with +them. + +Numeric-looking arguments will be returned as numbers unless `opts.string` or +`opts.boolean` is set for that argument name. + +Any arguments after `'--'` will not be parsed and will end up in `argv._`. + +options can be: + +* `opts.string` - a string or array of strings argument names to always treat as +strings +* `opts.boolean` - a boolean, string or array of strings to always treat as +booleans. if `true` will treat all double hyphenated arguments without equal signs +as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`) +* `opts.alias` - an object mapping string names to strings or arrays of string +argument names to use as aliases +* `opts.default` - an object mapping string argument names to default values +* `opts.stopEarly` - when true, populate `argv._` with everything after the +first non-option +* `opts['--']` - when true, populate `argv._` with everything before the `--` +and `argv['--']` with everything after the `--`. Here's an example: +* `opts.unknown` - a function which is invoked with a command line parameter not +defined in the `opts` configuration object. If the function returns `false`, the +unknown option is not added to `argv`. + +``` +> require('./')('one two three -- four five --six'.split(' '), { '--': true }) +{ _: [ 'one', 'two', 'three' ], + '--': [ 'four', 'five', '--six' ] } +``` + +Note that with `opts['--']` set, parsing for arguments still stops after the +`--`. + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install minimist +``` + +# license + +MIT diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/all_bool.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/all_bool.js new file mode 100644 index 0000000..ac83548 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/all_bool.js @@ -0,0 +1,32 @@ +var parse = require('../'); +var test = require('tape'); + +test('flag boolean true (default all --args to boolean)', function (t) { + var argv = parse(['moo', '--honk', 'cow'], { + boolean: true + }); + + t.deepEqual(argv, { + honk: true, + _: ['moo', 'cow'] + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); + +test('flag boolean true only affects double hyphen arguments without equals signs', function (t) { + var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], { + boolean: true + }); + + t.deepEqual(argv, { + honk: true, + tacos: 'good', + p: 55, + _: ['moo', 'cow'] + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/bool.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/bool.js new file mode 100644 index 0000000..14b0717 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/bool.js @@ -0,0 +1,166 @@ +var parse = require('../'); +var test = require('tape'); + +test('flag boolean default false', function (t) { + var argv = parse(['moo'], { + boolean: ['t', 'verbose'], + default: { verbose: false, t: false } + }); + + t.deepEqual(argv, { + verbose: false, + t: false, + _: ['moo'] + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], { + boolean: ['x','y','z'] + }); + + t.deepEqual(argv, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ] + }); + + t.deepEqual(typeof argv.x, 'boolean'); + t.deepEqual(typeof argv.y, 'boolean'); + t.deepEqual(typeof argv.z, 'boolean'); + t.end(); +}); +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = parse(aliased, { + boolean: 'herp', + alias: { h: 'herp' } + }); + var propertyArgv = parse(regular, { + boolean: 'herp', + alias: { h: 'herp' } + }); + var expected = { + herp: true, + h: true, + '_': [ 'derp' ] + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + alias: { 'h': 'herp' }, + boolean: 'herp' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + '_': [ 'derp' ] + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias array with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var alt = [ '--harp', 'derp' ]; + var opts = { + alias: { 'h': ['herp', 'harp'] }, + boolean: 'h' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var altPropertyArgv = parse(alt, opts); + var expected = { + harp: true, + herp: true, + h: true, + '_': [ 'derp' ] + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.same(altPropertyArgv, expected); + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + alias: { h: 'herp' }, + boolean: 'h' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + '_': [ ] + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = parse(['--boool', '--other=true'], { + boolean: 'boool' + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = parse(['--boool', '--other=false'], { + boolean: 'boool' + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); + +test('boolean --boool=true', function (t) { + var parsed = parse(['--boool=true'], { + default: { + boool: false + }, + boolean: ['boool'] + }); + + t.same(parsed.boool, true); + t.end(); +}); + +test('boolean --boool=false', function (t) { + var parsed = parse(['--boool=false'], { + default: { + boool: true + }, + boolean: ['boool'] + }); + + t.same(parsed.boool, false); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dash.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dash.js new file mode 100644 index 0000000..5a4fa5b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dash.js @@ -0,0 +1,31 @@ +var parse = require('../'); +var test = require('tape'); + +test('-', function (t) { + t.plan(5); + t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] }); + t.deepEqual(parse([ '-' ]), { _: [ '-' ] }); + t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] }); + t.deepEqual( + parse([ '-b', '-' ], { boolean: 'b' }), + { b: true, _: [ '-' ] } + ); + t.deepEqual( + parse([ '-s', '-' ], { string: 's' }), + { s: '-', _: [] } + ); +}); + +test('-a -- b', function (t) { + t.plan(3); + t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] }); + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] }); + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] }); +}); + +test('move arguments after the -- into their own `--` array', function(t) { + t.plan(1); + t.deepEqual( + parse([ '--name', 'John', 'before', '--', 'after' ], { '--': true }), + { name: 'John', _: [ 'before' ], '--': [ 'after' ] }); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/default_bool.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/default_bool.js new file mode 100644 index 0000000..780a311 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/default_bool.js @@ -0,0 +1,35 @@ +var test = require('tape'); +var parse = require('../'); + +test('boolean default true', function (t) { + var argv = parse([], { + boolean: 'sometrue', + default: { sometrue: true } + }); + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = parse([], { + boolean: 'somefalse', + default: { somefalse: false } + }); + t.equal(argv.somefalse, false); + t.end(); +}); + +test('boolean default to null', function (t) { + var argv = parse([], { + boolean: 'maybe', + default: { maybe: null } + }); + t.equal(argv.maybe, null); + var argv = parse(['--maybe'], { + boolean: 'maybe', + default: { maybe: null } + }); + t.equal(argv.maybe, true); + t.end(); + +}) diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dotted.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dotted.js new file mode 100644 index 0000000..d8b3e85 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/dotted.js @@ -0,0 +1,22 @@ +var parse = require('../'); +var test = require('tape'); + +test('dotted alias', function (t) { + var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}}); + t.equal(argv.a.b, 22); + t.equal(argv.aa.bb, 22); + t.end(); +}); + +test('dotted default', function (t) { + var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}}); + t.equal(argv.a.b, 11); + t.equal(argv.aa.bb, 11); + t.end(); +}); + +test('dotted default with no alias', function (t) { + var argv = parse('', {default: {'a.b': 11}}); + t.equal(argv.a.b, 11); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/kv_short.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/kv_short.js new file mode 100644 index 0000000..f813b30 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/kv_short.js @@ -0,0 +1,16 @@ +var parse = require('../'); +var test = require('tape'); + +test('short -k=v' , function (t) { + t.plan(1); + + var argv = parse([ '-b=123' ]); + t.deepEqual(argv, { b: 123, _: [] }); +}); + +test('multi short -k=v' , function (t) { + t.plan(1); + + var argv = parse([ '-a=whatever', '-b=robots' ]); + t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] }); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/long.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/long.js new file mode 100644 index 0000000..5d3a1e0 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/long.js @@ -0,0 +1,31 @@ +var test = require('tape'); +var parse = require('../'); + +test('long opts', function (t) { + t.deepEqual( + parse([ '--bool' ]), + { bool : true, _ : [] }, + 'long boolean' + ); + t.deepEqual( + parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [] }, + 'long capture sp' + ); + t.deepEqual( + parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [] }, + 'long capture eq' + ); + t.deepEqual( + parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [] }, + 'long captures sp' + ); + t.deepEqual( + parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [] }, + 'long captures eq' + ); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/num.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/num.js new file mode 100644 index 0000000..2cc77f4 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/num.js @@ -0,0 +1,36 @@ +var parse = require('../'); +var test = require('tape'); + +test('nums', function (t) { + var argv = parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789' + ]); + t.deepEqual(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ] + }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv.y, 'number'); + t.deepEqual(typeof argv.z, 'number'); + t.deepEqual(typeof argv.w, 'string'); + t.deepEqual(typeof argv.hex, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); + +test('already a number', function (t) { + var argv = parse([ '-x', 1234, 789 ]); + t.deepEqual(argv, { x : 1234, _ : [ 789 ] }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse.js new file mode 100644 index 0000000..7b4a2a1 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse.js @@ -0,0 +1,197 @@ +var parse = require('../'); +var test = require('tape'); + +test('parse args', function (t) { + t.deepEqual( + parse([ '--no-moo' ]), + { moo : false, _ : [] }, + 'no' + ); + t.deepEqual( + parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [] }, + 'multi' + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.deepEqual( + parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ] + } + ); + t.end(); +}); + +test('flag boolean', function (t) { + var argv = parse([ '-t', 'moo' ], { boolean: 't' }); + t.deepEqual(argv, { t : true, _ : [ 'moo' ] }); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], { + boolean: [ 't', 'verbose' ], + default: { verbose: true } + }); + + t.deepEqual(argv, { + verbose: false, + t: true, + _: ['moo'] + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = parse([ '-s', "X\nX" ]) + t.deepEqual(args, { _ : [], s : "X\nX" }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = parse([ "--s=X\nX" ]) + t.deepEqual(args, { _ : [], s : "X\nX" }); + t.end(); +}); + +test('strings' , function (t) { + var s = parse([ '-s', '0001234' ], { string: 's' }).s; + t.equal(s, '0001234'); + t.equal(typeof s, 'string'); + + var x = parse([ '-x', '56' ], { string: 'x' }).x; + t.equal(x, '56'); + t.equal(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = parse([ ' ', ' ' ], { string: '_' })._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('empty strings', function(t) { + var s = parse([ '-s' ], { string: 's' }).s; + t.equal(s, ''); + t.equal(typeof s, 'string'); + + var str = parse([ '--str' ], { string: 'str' }).str; + t.equal(str, ''); + t.equal(typeof str, 'string'); + + var letters = parse([ '-art' ], { + string: [ 'a', 't' ] + }); + + t.equal(letters.a, ''); + t.equal(letters.r, true); + t.equal(letters.t, ''); + + t.end(); +}); + + +test('string and alias', function(t) { + var x = parse([ '--str', '000123' ], { + string: 's', + alias: { s: 'str' } + }); + + t.equal(x.str, '000123'); + t.equal(typeof x.str, 'string'); + t.equal(x.s, '000123'); + t.equal(typeof x.s, 'string'); + + var y = parse([ '-s', '000123' ], { + string: 'str', + alias: { str: 's' } + }); + + t.equal(y.str, '000123'); + t.equal(typeof y.str, 'string'); + t.equal(y.s, '000123'); + t.equal(typeof y.s, 'string'); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [] } + ); + t.same( + parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [] } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = parse([ '-f', '11', '--zoom', '55' ], { + alias: { z: 'zoom' } + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = parse([ '-f', '11', '--zoom', '55' ], { + alias: { z: [ 'zm', 'zoom' ] } + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = parse([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]); + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + } + }); + t.same(argv.beep, { boop : true }); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse_modified.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse_modified.js new file mode 100644 index 0000000..ab620dc --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/parse_modified.js @@ -0,0 +1,9 @@ +var parse = require('../'); +var test = require('tape'); + +test('parse with modifier functions' , function (t) { + t.plan(1); + + var argv = parse([ '-b', '123' ], { boolean: 'b' }); + t.deepEqual(argv, { b: true, _: [123] }); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/short.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/short.js new file mode 100644 index 0000000..d513a1c --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/short.js @@ -0,0 +1,67 @@ +var parse = require('../'); +var test = require('tape'); + +test('numeric short args', function (t) { + t.plan(2); + t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] }); + t.deepEqual( + parse([ '-123', '456' ]), + { 1: true, 2: true, 3: 456, _: [] } + ); +}); + +test('short', function (t) { + t.deepEqual( + parse([ '-b' ]), + { b : true, _ : [] }, + 'short boolean' + ); + t.deepEqual( + parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ] }, + 'bare' + ); + t.deepEqual( + parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [] }, + 'group' + ); + t.deepEqual( + parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [] }, + 'short group next' + ); + t.deepEqual( + parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [] }, + 'short capture' + ); + t.deepEqual( + parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [] }, + 'short captures' + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ] + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.deepEqual( + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ] + } + ); + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/stop_early.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/stop_early.js new file mode 100644 index 0000000..bdf9fbc --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/stop_early.js @@ -0,0 +1,15 @@ +var parse = require('../'); +var test = require('tape'); + +test('stops parsing on the first non-option when stopEarly is set', function (t) { + var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], { + stopEarly: true + }); + + t.deepEqual(argv, { + aaa: 'bbb', + _: ['ccc', '--ddd'] + }); + + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/unknown.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/unknown.js new file mode 100644 index 0000000..462a36b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/unknown.js @@ -0,0 +1,102 @@ +var parse = require('../'); +var test = require('tape'); + +test('boolean and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'true', '--derp', 'true' ]; + var regular = [ '--herp', 'true', '-d', 'true' ]; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('flag boolean true any double hyphen argument is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], { + boolean: true, + unknown: unknownFn + }); + t.same(unknown, ['--tacos=good', 'cow', '-p']); + t.same(argv, { + honk: true, + _: [] + }); + t.end(); +}); + +test('string and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'hello', '--derp', 'goodbye' ]; + var regular = [ '--herp', 'hello', '-d', 'moon' ]; + var opts = { + alias: { h: 'herp' }, + string: 'h', + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('default and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'hello' ]; + var regular = [ '--herp', 'hello' ]; + var opts = { + default: { 'h': 'bar' }, + alias: { 'h': 'herp' }, + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, []); + t.end(); + unknownFn(); // exercise fn for 100% coverage +}); + +test('value following -- is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '--bad', '--', 'good', 'arg' ]; + var opts = { + '--': true, + unknown: unknownFn + }; + var argv = parse(aliased, opts); + + t.same(unknown, ['--bad']); + t.same(argv, { + '--': ['good', 'arg'], + '_': [] + }) + t.end(); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/whitespace.js b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/whitespace.js new file mode 100644 index 0000000..8a52a58 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/node_modules/minimist/test/whitespace.js @@ -0,0 +1,8 @@ +var parse = require('../'); +var test = require('tape'); + +test('whitespace should be whitespace' , function (t) { + t.plan(1); + var x = parse([ '-x', '\t' ]).x; + t.equal(x, '\t'); +}); diff --git a/js/node_modules/fsevents/node_modules/rc/package.json b/js/node_modules/fsevents/node_modules/rc/package.json new file mode 100644 index 0000000..8ae82b2 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/package.json @@ -0,0 +1,67 @@ +{ + "_args": [ + [ + "rc@1.2.6", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "rc@1.2.6", + "_id": "rc@1.2.6", + "_inBundle": true, + "_integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", + "_location": "/fsevents/rc", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "rc@1.2.6", + "name": "rc", + "escapedName": "rc", + "rawSpec": "1.2.6", + "saveSpec": null, + "fetchSpec": "1.2.6" + }, + "_requiredBy": [ + "/fsevents/node-pre-gyp" + ], + "_resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", + "_spec": "1.2.6", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "dominictarr.com" + }, + "bin": { + "rc": "./cli.js" + }, + "browser": "browser.js", + "bugs": { + "url": "https://github.com/dominictarr/rc/issues" + }, + "dependencies": { + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "description": "hardwired configuration loader", + "homepage": "https://github.com/dominictarr/rc#readme", + "keywords": [ + "config", + "rc", + "unix", + "defaults" + ], + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "main": "index.js", + "name": "rc", + "repository": { + "type": "git", + "url": "git+https://github.com/dominictarr/rc.git" + }, + "scripts": { + "test": "set -e; node test/test.js; node test/ini.js; node test/nested-env-vars.js" + }, + "version": "1.2.6" +} diff --git a/js/node_modules/fsevents/node_modules/rc/test/ini.js b/js/node_modules/fsevents/node_modules/rc/test/ini.js new file mode 100644 index 0000000..e6857f8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/test/ini.js @@ -0,0 +1,16 @@ +var cc =require('../lib/utils') +var INI = require('ini') +var assert = require('assert') + +function test(obj) { + + var _json, _ini + var json = cc.parse (_json = JSON.stringify(obj)) + var ini = cc.parse (_ini = INI.stringify(obj)) + console.log(_ini, _json) + assert.deepEqual(json, ini) +} + + +test({hello: true}) + diff --git a/js/node_modules/fsevents/node_modules/rc/test/nested-env-vars.js b/js/node_modules/fsevents/node_modules/rc/test/nested-env-vars.js new file mode 100644 index 0000000..0ecd176 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/test/nested-env-vars.js @@ -0,0 +1,50 @@ + +var seed = Math.random(); +var n = 'rc'+ seed; +var N = 'RC'+ seed; +var assert = require('assert') + + +// Basic usage +process.env[n+'_someOpt__a'] = 42 +process.env[n+'_someOpt__x__'] = 99 +process.env[n+'_someOpt__a__b'] = 186 +process.env[n+'_someOpt__a__b__c'] = 243 +process.env[n+'_someOpt__x__y'] = 1862 +process.env[n+'_someOpt__z'] = 186577 + +// Should ignore empty strings from orphaned '__' +process.env[n+'_someOpt__z__x__'] = 18629 +process.env[n+'_someOpt__w__w__'] = 18629 + +// Leading '__' should ignore everything up to 'z' +process.env[n+'___z__i__'] = 9999 + +// should ignore case for config name section. +process.env[N+'_test_upperCase'] = 187 + +function testPrefix(prefix) { + var config = require('../')(prefix, { + option: true + }) + + console.log('\n\n------ nested-env-vars ------\n',{prefix: prefix}, '\n', config); + + assert.equal(config.option, true) + assert.equal(config.someOpt.a, 42) + assert.equal(config.someOpt.x, 99) + // Should not override `a` once it's been set + assert.equal(config.someOpt.a/*.b*/, 42) + // Should not override `x` once it's been set + assert.equal(config.someOpt.x/*.y*/, 99) + assert.equal(config.someOpt.z, 186577) + // Should not override `z` once it's been set + assert.equal(config.someOpt.z/*.x*/, 186577) + assert.equal(config.someOpt.w.w, 18629) + assert.equal(config.z.i, 9999) + + assert.equal(config.test_upperCase, 187) +} + +testPrefix(n); +testPrefix(N); diff --git a/js/node_modules/fsevents/node_modules/rc/test/test.js b/js/node_modules/fsevents/node_modules/rc/test/test.js new file mode 100644 index 0000000..4f63351 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rc/test/test.js @@ -0,0 +1,59 @@ + +var n = 'rc'+Math.random() +var assert = require('assert') + +process.env[n+'_envOption'] = 42 + +var config = require('../')(n, { + option: true +}) + +console.log(config) + +assert.equal(config.option, true) +assert.equal(config.envOption, 42) + +var customArgv = require('../')(n, { + option: true +}, { // nopt-like argv + option: false, + envOption: 24, + argv: { + remain: [], + cooked: ['--no-option', '--envOption', '24'], + original: ['--no-option', '--envOption=24'] + } +}) + +console.log(customArgv) + +assert.equal(customArgv.option, false) +assert.equal(customArgv.envOption, 24) + +var fs = require('fs') +var path = require('path') +var jsonrc = path.resolve('.' + n + 'rc'); + +fs.writeFileSync(jsonrc, [ + '{', + '// json overrides default', + '"option": false,', + '/* env overrides json */', + '"envOption": 24', + '}' +].join('\n')); + +var commentedJSON = require('../')(n, { + option: true +}) + +fs.unlinkSync(jsonrc); + +console.log(commentedJSON) + +assert.equal(commentedJSON.option, false) +assert.equal(commentedJSON.envOption, 42) + +assert.equal(commentedJSON.config, jsonrc) +assert.equal(commentedJSON.configs.length, 1) +assert.equal(commentedJSON.configs[0], jsonrc) diff --git a/js/node_modules/fsevents/node_modules/readable-stream/.travis.yml b/js/node_modules/fsevents/node_modules/readable-stream/.travis.yml new file mode 100644 index 0000000..4099255 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/.travis.yml @@ -0,0 +1,55 @@ +sudo: false +language: node_js +before_install: + - npm install -g npm@2 + - test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g +notifications: + email: false +matrix: + fast_finish: true + include: + - node_js: '0.8' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: '0.10' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: '0.11' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: '0.12' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 1 + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 2 + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 3 + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 4 + env: TASK=test + - node_js: 5 + env: TASK=test + - node_js: 6 + env: TASK=test + - node_js: 7 + env: TASK=test + - node_js: 8 + env: TASK=test + - node_js: 9 + env: TASK=test +script: "npm run $TASK" +env: + global: + - secure: rE2Vvo7vnjabYNULNyLFxOyt98BoJexDqsiOnfiD6kLYYsiQGfr/sbZkPMOFm9qfQG7pjqx+zZWZjGSswhTt+626C0t/njXqug7Yps4c3dFblzGfreQHp7wNX5TFsvrxd6dAowVasMp61sJcRnB2w8cUzoe3RAYUDHyiHktwqMc= + - secure: g9YINaKAdMatsJ28G9jCGbSaguXCyxSTy+pBO6Ch0Cf57ZLOTka3HqDj8p3nV28LUIHZ3ut5WO43CeYKwt4AUtLpBS3a0dndHdY6D83uY6b2qh5hXlrcbeQTq2cvw2y95F7hm4D1kwrgZ7ViqaKggRcEupAL69YbJnxeUDKWEdI= diff --git a/js/node_modules/fsevents/node_modules/readable-stream/CONTRIBUTING.md b/js/node_modules/fsevents/node_modules/readable-stream/CONTRIBUTING.md new file mode 100644 index 0000000..f478d58 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/CONTRIBUTING.md @@ -0,0 +1,38 @@ +# Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +## Moderation Policy + +The [Node.js Moderation Policy] applies to this WG. + +## Code of Conduct + +The [Node.js Code of Conduct][] applies to this WG. + +[Node.js Code of Conduct]: +https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md +[Node.js Moderation Policy]: +https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md diff --git a/js/node_modules/fsevents/node_modules/readable-stream/GOVERNANCE.md b/js/node_modules/fsevents/node_modules/readable-stream/GOVERNANCE.md new file mode 100644 index 0000000..16ffb93 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/GOVERNANCE.md @@ -0,0 +1,136 @@ +### Streams Working Group + +The Node.js Streams is jointly governed by a Working Group +(WG) +that is responsible for high-level guidance of the project. + +The WG has final authority over this project including: + +* Technical direction +* Project governance and process (including this policy) +* Contribution policy +* GitHub repository hosting +* Conduct guidelines +* Maintaining the list of additional Collaborators + +For the current list of WG members, see the project +[README.md](./README.md#current-project-team-members). + +### Collaborators + +The readable-stream GitHub repository is +maintained by the WG and additional Collaborators who are added by the +WG on an ongoing basis. + +Individuals making significant and valuable contributions are made +Collaborators and given commit-access to the project. These +individuals are identified by the WG and their addition as +Collaborators is discussed during the WG meeting. + +_Note:_ If you make a significant contribution and are not considered +for commit-access log an issue or contact a WG member directly and it +will be brought up in the next WG meeting. + +Modifications of the contents of the readable-stream repository are +made on +a collaborative basis. Anybody with a GitHub account may propose a +modification via pull request and it will be considered by the project +Collaborators. All pull requests must be reviewed and accepted by a +Collaborator with sufficient expertise who is able to take full +responsibility for the change. In the case of pull requests proposed +by an existing Collaborator, an additional Collaborator is required +for sign-off. Consensus should be sought if additional Collaborators +participate and there is disagreement around a particular +modification. See _Consensus Seeking Process_ below for further detail +on the consensus model used for governance. + +Collaborators may opt to elevate significant or controversial +modifications, or modifications that have not found consensus to the +WG for discussion by assigning the ***WG-agenda*** tag to a pull +request or issue. The WG should serve as the final arbiter where +required. + +For the current list of Collaborators, see the project +[README.md](./README.md#members). + +### WG Membership + +WG seats are not time-limited. There is no fixed size of the WG. +However, the expected target is between 6 and 12, to ensure adequate +coverage of important areas of expertise, balanced with the ability to +make decisions efficiently. + +There is no specific set of requirements or qualifications for WG +membership beyond these rules. + +The WG may add additional members to the WG by unanimous consensus. + +A WG member may be removed from the WG by voluntary resignation, or by +unanimous consensus of all other WG members. + +Changes to WG membership should be posted in the agenda, and may be +suggested as any other agenda item (see "WG Meetings" below). + +If an addition or removal is proposed during a meeting, and the full +WG is not in attendance to participate, then the addition or removal +is added to the agenda for the subsequent meeting. This is to ensure +that all members are given the opportunity to participate in all +membership decisions. If a WG member is unable to attend a meeting +where a planned membership decision is being made, then their consent +is assumed. + +No more than 1/3 of the WG members may be affiliated with the same +employer. If removal or resignation of a WG member, or a change of +employment by a WG member, creates a situation where more than 1/3 of +the WG membership shares an employer, then the situation must be +immediately remedied by the resignation or removal of one or more WG +members affiliated with the over-represented employer(s). + +### WG Meetings + +The WG meets occasionally on a Google Hangout On Air. A designated moderator +approved by the WG runs the meeting. Each meeting should be +published to YouTube. + +Items are added to the WG agenda that are considered contentious or +are modifications of governance, contribution policy, WG membership, +or release process. + +The intention of the agenda is not to approve or review all patches; +that should happen continuously on GitHub and be handled by the larger +group of Collaborators. + +Any community member or contributor can ask that something be added to +the next meeting's agenda by logging a GitHub Issue. Any Collaborator, +WG member or the moderator can add the item to the agenda by adding +the ***WG-agenda*** tag to the issue. + +Prior to each WG meeting the moderator will share the Agenda with +members of the WG. WG members can add any items they like to the +agenda at the beginning of each meeting. The moderator and the WG +cannot veto or remove items. + +The WG may invite persons or representatives from certain projects to +participate in a non-voting capacity. + +The moderator is responsible for summarizing the discussion of each +agenda item and sends it as a pull request after the meeting. + +### Consensus Seeking Process + +The WG follows a +[Consensus +Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making) +decision-making model. + +When an agenda item has appeared to reach a consensus the moderator +will ask "Does anyone object?" as a final call for dissent from the +consensus. + +If an agenda item cannot reach a consensus a WG member can call for +either a closing vote or a vote to table the issue to the next +meeting. The call for a vote must be seconded by a majority of the WG +or else the discussion will continue. Simple majority wins. + +Note that changes to WG membership require a majority consensus. See +"WG Membership" above. diff --git a/js/node_modules/fsevents/node_modules/readable-stream/LICENSE b/js/node_modules/fsevents/node_modules/readable-stream/LICENSE new file mode 100644 index 0000000..2873b3b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/LICENSE @@ -0,0 +1,47 @@ +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" diff --git a/js/node_modules/fsevents/node_modules/readable-stream/README.md b/js/node_modules/fsevents/node_modules/readable-stream/README.md new file mode 100644 index 0000000..23fe3f3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/README.md @@ -0,0 +1,58 @@ +# readable-stream + +***Node-core v8.11.1 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) + + +[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) +[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/) + + +[![Sauce Test Status](https://saucelabs.com/browser-matrix/readable-stream.svg)](https://saucelabs.com/u/readable-stream) + +```bash +npm install --save readable-stream +``` + +***Node-core streams for userland*** + +This package is a mirror of the Streams2 and Streams3 implementations in +Node-core. + +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.11.1/docs/api/stream.html). + +If you want to guarantee a stable streams base, regardless of what version of +Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html). + +As of version 2.0.0 **readable-stream** uses semantic versioning. + +# Streams Working Group + +`readable-stream` is maintained by the Streams Working Group, which +oversees the development and maintenance of the Streams API within +Node.js. The responsibilities of the Streams Working Group include: + +* Addressing stream issues on the Node.js issue tracker. +* Authoring and editing stream documentation within the Node.js project. +* Reviewing changes to stream subclasses within the Node.js project. +* Redirecting changes to streams from the Node.js project to this + project. +* Assisting in the implementation of stream providers within Node.js. +* Recommending versions of `readable-stream` to be included in Node.js. +* Messaging about the future of streams to give the community advance + notice of changes. + + +## Team Members + +* **Chris Dickinson** ([@chrisdickinson](https://github.com/chrisdickinson)) <christopher.s.dickinson@gmail.com> + - Release GPG key: 9554F04D7259F04124DE6B476D5A82AC7E37093B +* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) <calvin.metcalf@gmail.com> + - Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242 +* **Rod Vagg** ([@rvagg](https://github.com/rvagg)) <rod@vagg.org> + - Release GPG key: DD8F2338BAE7501E3DD5AC78C273792F7D83545D +* **Sam Newman** ([@sonewman](https://github.com/sonewman)) <newmansam@outlook.com> +* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) <mathiasbuus@gmail.com> +* **Domenic Denicola** ([@domenic](https://github.com/domenic)) <d@domenic.me> +* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) <matteo.collina@gmail.com> + - Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E +* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) <shestak.irina@gmail.com> diff --git a/js/node_modules/fsevents/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md b/js/node_modules/fsevents/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md new file mode 100644 index 0000000..83275f1 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md @@ -0,0 +1,60 @@ +# streams WG Meeting 2015-01-30 + +## Links + +* **Google Hangouts Video**: http://www.youtube.com/watch?v=I9nDOSGfwZg +* **GitHub Issue**: https://github.com/iojs/readable-stream/issues/106 +* **Original Minutes Google Doc**: https://docs.google.com/document/d/17aTgLnjMXIrfjgNaTUnHQO7m3xgzHR2VXBTmi03Qii4/ + +## Agenda + +Extracted from https://github.com/iojs/readable-stream/labels/wg-agenda prior to meeting. + +* adopt a charter [#105](https://github.com/iojs/readable-stream/issues/105) +* release and versioning strategy [#101](https://github.com/iojs/readable-stream/issues/101) +* simpler stream creation [#102](https://github.com/iojs/readable-stream/issues/102) +* proposal: deprecate implicit flowing of streams [#99](https://github.com/iojs/readable-stream/issues/99) + +## Minutes + +### adopt a charter + +* group: +1's all around + +### What versioning scheme should be adopted? +* group: +1’s 3.0.0 +* domenic+group: pulling in patches from other sources where appropriate +* mikeal: version independently, suggesting versions for io.js +* mikeal+domenic: work with TC to notify in advance of changes +simpler stream creation + +### streamline creation of streams +* sam: streamline creation of streams +* domenic: nice simple solution posted + but, we lose the opportunity to change the model + may not be backwards incompatible (double check keys) + + **action item:** domenic will check + +### remove implicit flowing of streams on(‘data’) +* add isFlowing / isPaused +* mikeal: worrying that we’re documenting polyfill methods – confuses users +* domenic: more reflective API is probably good, with warning labels for users +* new section for mad scientists (reflective stream access) +* calvin: name the “third state” +* mikeal: maybe borrow the name from whatwg? +* domenic: we’re missing the “third state” +* consensus: kind of difficult to name the third state +* mikeal: figure out differences in states / compat +* mathias: always flow on data – eliminates third state + * explore what it breaks + +**action items:** +* ask isaac for ability to list packages by what public io.js APIs they use (esp. Stream) +* ask rod/build for infrastructure +* **chris**: explore the “flow on data” approach +* add isPaused/isFlowing +* add new docs section +* move isPaused to that section + + diff --git a/js/node_modules/fsevents/node_modules/readable-stream/duplex-browser.js b/js/node_modules/fsevents/node_modules/readable-stream/duplex-browser.js new file mode 100644 index 0000000..f8b2db8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/duplex-browser.js @@ -0,0 +1 @@ +module.exports = require('./lib/_stream_duplex.js'); diff --git a/js/node_modules/fsevents/node_modules/readable-stream/duplex.js b/js/node_modules/fsevents/node_modules/readable-stream/duplex.js new file mode 100644 index 0000000..46924cb --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/duplex.js @@ -0,0 +1 @@ +module.exports = require('./readable').Duplex diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_duplex.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_duplex.js new file mode 100644 index 0000000..a1ca813 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_duplex.js @@ -0,0 +1,131 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_passthrough.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_passthrough.js new file mode 100644 index 0000000..a9c8358 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_passthrough.js @@ -0,0 +1,47 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_readable.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_readable.js new file mode 100644 index 0000000..bf34ac6 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_readable.js @@ -0,0 +1,1019 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_transform.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_transform.js new file mode 100644 index 0000000..5d1f8b8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_transform.js @@ -0,0 +1,214 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_writable.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_writable.js new file mode 100644 index 0000000..b3f4e85 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/_stream_writable.js @@ -0,0 +1,687 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/BufferList.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/BufferList.js new file mode 100644 index 0000000..aefc68b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/BufferList.js @@ -0,0 +1,79 @@ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/destroy.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/destroy.js new file mode 100644 index 0000000..5a0a0d8 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/destroy.js @@ -0,0 +1,74 @@ +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; \ No newline at end of file diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream-browser.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream-browser.js new file mode 100644 index 0000000..9332a3f --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream-browser.js @@ -0,0 +1 @@ +module.exports = require('events').EventEmitter; diff --git a/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream.js b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream.js new file mode 100644 index 0000000..ce2ad5b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/lib/internal/streams/stream.js @@ -0,0 +1 @@ +module.exports = require('stream'); diff --git a/js/node_modules/fsevents/node_modules/readable-stream/package.json b/js/node_modules/fsevents/node_modules/readable-stream/package.json new file mode 100644 index 0000000..df96972 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/package.json @@ -0,0 +1,84 @@ +{ + "_args": [ + [ + "readable-stream@2.3.6", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "readable-stream@2.3.6", + "_id": "readable-stream@2.3.6", + "_inBundle": true, + "_integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "_location": "/fsevents/readable-stream", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "readable-stream@2.3.6", + "name": "readable-stream", + "escapedName": "readable-stream", + "rawSpec": "2.3.6", + "saveSpec": null, + "fetchSpec": "2.3.6" + }, + "_requiredBy": [ + "/fsevents/are-we-there-yet" + ], + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "_spec": "2.3.6", + "_where": "/Users/eshanker/Code/fsevents", + "browser": { + "util": false, + "./readable.js": "./readable-browser.js", + "./writable.js": "./writable-browser.js", + "./duplex.js": "./duplex-browser.js", + "./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js" + }, + "bugs": { + "url": "https://github.com/nodejs/readable-stream/issues" + }, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "description": "Streams3, a user-land copy of the stream library from Node.js", + "devDependencies": { + "assert": "^1.4.0", + "babel-polyfill": "^6.9.1", + "buffer": "^4.9.0", + "lolex": "^2.3.2", + "nyc": "^6.4.0", + "tap": "^0.7.0", + "tape": "^4.8.0" + }, + "homepage": "https://github.com/nodejs/readable-stream#readme", + "keywords": [ + "readable", + "stream", + "pipe" + ], + "license": "MIT", + "main": "readable.js", + "name": "readable-stream", + "nyc": { + "include": [ + "lib/**.js" + ] + }, + "repository": { + "type": "git", + "url": "git://github.com/nodejs/readable-stream.git" + }, + "scripts": { + "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js", + "cover": "nyc npm test", + "report": "nyc report --reporter=lcov", + "test": "tap test/parallel/*.js test/ours/*.js && node test/verify-dependencies.js" + }, + "version": "2.3.6" +} diff --git a/js/node_modules/fsevents/node_modules/readable-stream/passthrough.js b/js/node_modules/fsevents/node_modules/readable-stream/passthrough.js new file mode 100644 index 0000000..ffd791d --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/passthrough.js @@ -0,0 +1 @@ +module.exports = require('./readable').PassThrough diff --git a/js/node_modules/fsevents/node_modules/readable-stream/readable-browser.js b/js/node_modules/fsevents/node_modules/readable-stream/readable-browser.js new file mode 100644 index 0000000..e503725 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/readable-browser.js @@ -0,0 +1,7 @@ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); diff --git a/js/node_modules/fsevents/node_modules/readable-stream/readable.js b/js/node_modules/fsevents/node_modules/readable-stream/readable.js new file mode 100644 index 0000000..ec89ec5 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/readable.js @@ -0,0 +1,19 @@ +var Stream = require('stream'); +if (process.env.READABLE_STREAM === 'disable' && Stream) { + module.exports = Stream; + exports = module.exports = Stream.Readable; + exports.Readable = Stream.Readable; + exports.Writable = Stream.Writable; + exports.Duplex = Stream.Duplex; + exports.Transform = Stream.Transform; + exports.PassThrough = Stream.PassThrough; + exports.Stream = Stream; +} else { + exports = module.exports = require('./lib/_stream_readable.js'); + exports.Stream = Stream || exports; + exports.Readable = exports; + exports.Writable = require('./lib/_stream_writable.js'); + exports.Duplex = require('./lib/_stream_duplex.js'); + exports.Transform = require('./lib/_stream_transform.js'); + exports.PassThrough = require('./lib/_stream_passthrough.js'); +} diff --git a/js/node_modules/fsevents/node_modules/readable-stream/transform.js b/js/node_modules/fsevents/node_modules/readable-stream/transform.js new file mode 100644 index 0000000..b1baba2 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/transform.js @@ -0,0 +1 @@ +module.exports = require('./readable').Transform diff --git a/js/node_modules/fsevents/node_modules/readable-stream/writable-browser.js b/js/node_modules/fsevents/node_modules/readable-stream/writable-browser.js new file mode 100644 index 0000000..ebdde6a --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/writable-browser.js @@ -0,0 +1 @@ +module.exports = require('./lib/_stream_writable.js'); diff --git a/js/node_modules/fsevents/node_modules/readable-stream/writable.js b/js/node_modules/fsevents/node_modules/readable-stream/writable.js new file mode 100644 index 0000000..3211a6f --- /dev/null +++ b/js/node_modules/fsevents/node_modules/readable-stream/writable.js @@ -0,0 +1,8 @@ +var Stream = require("stream") +var Writable = require("./lib/_stream_writable.js") + +if (process.env.READABLE_STREAM === 'disable') { + module.exports = Stream && Stream.Writable || Writable +} else { + module.exports = Writable +} diff --git a/js/node_modules/fsevents/node_modules/rimraf/LICENSE b/js/node_modules/fsevents/node_modules/rimraf/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rimraf/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/rimraf/README.md b/js/node_modules/fsevents/node_modules/rimraf/README.md new file mode 100644 index 0000000..423b8cf --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rimraf/README.md @@ -0,0 +1,101 @@ +[![Build Status](https://travis-ci.org/isaacs/rimraf.svg?branch=master)](https://travis-ci.org/isaacs/rimraf) [![Dependency Status](https://david-dm.org/isaacs/rimraf.svg)](https://david-dm.org/isaacs/rimraf) [![devDependency Status](https://david-dm.org/isaacs/rimraf/dev-status.svg)](https://david-dm.org/isaacs/rimraf#info=devDependencies) + +The [UNIX command](http://en.wikipedia.org/wiki/Rm_(Unix)) `rm -rf` for node. + +Install with `npm install rimraf`, or just drop rimraf.js somewhere. + +## API + +`rimraf(f, [opts], callback)` + +The first parameter will be interpreted as a globbing pattern for files. If you +want to disable globbing you can do so with `opts.disableGlob` (defaults to +`false`). This might be handy, for instance, if you have filenames that contain +globbing wildcard characters. + +The callback will be called with an error if there is one. Certain +errors are handled for you: + +* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of + `opts.maxBusyTries` times before giving up, adding 100ms of wait + between each attempt. The default `maxBusyTries` is 3. +* `ENOENT` - If the file doesn't exist, rimraf will return + successfully, since your desired outcome is already the case. +* `EMFILE` - Since `readdir` requires opening a file descriptor, it's + possible to hit `EMFILE` if too many file descriptors are in use. + In the sync case, there's nothing to be done for this. But in the + async case, rimraf will gradually back off with timeouts up to + `opts.emfileWait` ms, which defaults to 1000. + +## options + +* unlink, chmod, stat, lstat, rmdir, readdir, + unlinkSync, chmodSync, statSync, lstatSync, rmdirSync, readdirSync + + In order to use a custom file system library, you can override + specific fs functions on the options object. + + If any of these functions are present on the options object, then + the supplied function will be used instead of the default fs + method. + + Sync methods are only relevant for `rimraf.sync()`, of course. + + For example: + + ```javascript + var myCustomFS = require('some-custom-fs') + + rimraf('some-thing', myCustomFS, callback) + ``` + +* maxBusyTries + + If an `EBUSY`, `ENOTEMPTY`, or `EPERM` error code is encountered + on Windows systems, then rimraf will retry with a linear backoff + wait of 100ms longer on each try. The default maxBusyTries is 3. + + Only relevant for async usage. + +* emfileWait + + If an `EMFILE` error is encountered, then rimraf will retry + repeatedly with a linear backoff of 1ms longer on each try, until + the timeout counter hits this max. The default limit is 1000. + + If you repeatedly encounter `EMFILE` errors, then consider using + [graceful-fs](http://npm.im/graceful-fs) in your program. + + Only relevant for async usage. + +* glob + + Set to `false` to disable [glob](http://npm.im/glob) pattern + matching. + + Set to an object to pass options to the glob module. The default + glob options are `{ nosort: true, silent: true }`. + + Glob version 6 is used in this module. + + Relevant for both sync and async usage. + +* disableGlob + + Set to any non-falsey value to disable globbing entirely. + (Equivalent to setting `glob: false`.) + +## rimraf.sync + +It can remove stuff synchronously, too. But that's not so good. Use +the async API. It's better. + +## CLI + +If installed with `npm install rimraf -g` it can be used as a global +command `rimraf [ ...]` which is useful for cross platform support. + +## mkdirp + +If you need to create a directory recursively, check out +[mkdirp](https://github.com/substack/node-mkdirp). diff --git a/js/node_modules/fsevents/node_modules/rimraf/bin.js b/js/node_modules/fsevents/node_modules/rimraf/bin.js new file mode 100755 index 0000000..0d1e17b --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rimraf/bin.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node + +var rimraf = require('./') + +var help = false +var dashdash = false +var noglob = false +var args = process.argv.slice(2).filter(function(arg) { + if (dashdash) + return !!arg + else if (arg === '--') + dashdash = true + else if (arg === '--no-glob' || arg === '-G') + noglob = true + else if (arg === '--glob' || arg === '-g') + noglob = false + else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/)) + help = true + else + return !!arg +}) + +if (help || args.length === 0) { + // If they didn't ask for help, then this is not a "success" + var log = help ? console.log : console.error + log('Usage: rimraf [ ...]') + log('') + log(' Deletes all files and folders at "path" recursively.') + log('') + log('Options:') + log('') + log(' -h, --help Display this usage info') + log(' -G, --no-glob Do not expand glob patterns in arguments') + log(' -g, --glob Expand glob patterns in arguments (default)') + process.exit(help ? 0 : 1) +} else + go(0) + +function go (n) { + if (n >= args.length) + return + var options = {} + if (noglob) + options = { glob: false } + rimraf(args[n], options, function (er) { + if (er) + throw er + go(n+1) + }) +} diff --git a/js/node_modules/fsevents/node_modules/rimraf/package.json b/js/node_modules/fsevents/node_modules/rimraf/package.json new file mode 100644 index 0000000..5689a6c --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rimraf/package.json @@ -0,0 +1,67 @@ +{ + "_args": [ + [ + "rimraf@2.6.2", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "rimraf@2.6.2", + "_id": "rimraf@2.6.2", + "_inBundle": true, + "_integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "_location": "/fsevents/rimraf", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "rimraf@2.6.2", + "name": "rimraf", + "escapedName": "rimraf", + "rawSpec": "2.6.2", + "saveSpec": null, + "fetchSpec": "2.6.2" + }, + "_requiredBy": [ + "/fsevents/node-pre-gyp" + ], + "_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "_spec": "2.6.2", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bin": { + "rimraf": "./bin.js" + }, + "bugs": { + "url": "https://github.com/isaacs/rimraf/issues" + }, + "dependencies": { + "glob": "^7.0.5" + }, + "description": "A deep deletion module for node (like `rm -rf`)", + "devDependencies": { + "mkdirp": "^0.5.1", + "tap": "^10.1.2" + }, + "files": [ + "LICENSE", + "README.md", + "bin.js", + "rimraf.js" + ], + "homepage": "https://github.com/isaacs/rimraf#readme", + "license": "ISC", + "main": "rimraf.js", + "name": "rimraf", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/rimraf.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "2.6.2" +} diff --git a/js/node_modules/fsevents/node_modules/rimraf/rimraf.js b/js/node_modules/fsevents/node_modules/rimraf/rimraf.js new file mode 100644 index 0000000..e80dd10 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/rimraf/rimraf.js @@ -0,0 +1,364 @@ +module.exports = rimraf +rimraf.sync = rimrafSync + +var assert = require("assert") +var path = require("path") +var fs = require("fs") +var glob = require("glob") +var _0666 = parseInt('666', 8) + +var defaultGlobOpts = { + nosort: true, + silent: true +} + +// for EMFILE handling +var timeout = 0 + +var isWindows = (process.platform === "win32") + +function defaults (options) { + var methods = [ + 'unlink', + 'chmod', + 'stat', + 'lstat', + 'rmdir', + 'readdir' + ] + methods.forEach(function(m) { + options[m] = options[m] || fs[m] + m = m + 'Sync' + options[m] = options[m] || fs[m] + }) + + options.maxBusyTries = options.maxBusyTries || 3 + options.emfileWait = options.emfileWait || 1000 + if (options.glob === false) { + options.disableGlob = true + } + options.disableGlob = options.disableGlob || false + options.glob = options.glob || defaultGlobOpts +} + +function rimraf (p, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } + + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert.equal(typeof cb, 'function', 'rimraf: callback function required') + assert(options, 'rimraf: invalid options argument provided') + assert.equal(typeof options, 'object', 'rimraf: options should be object') + + defaults(options) + + var busyTries = 0 + var errState = null + var n = 0 + + if (options.disableGlob || !glob.hasMagic(p)) + return afterGlob(null, [p]) + + options.lstat(p, function (er, stat) { + if (!er) + return afterGlob(null, [p]) + + glob(p, options.glob, afterGlob) + }) + + function next (er) { + errState = errState || er + if (--n === 0) + cb(errState) + } + + function afterGlob (er, results) { + if (er) + return cb(er) + + n = results.length + if (n === 0) + return cb() + + results.forEach(function (p) { + rimraf_(p, options, function CB (er) { + if (er) { + if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && + busyTries < options.maxBusyTries) { + busyTries ++ + var time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(function () { + rimraf_(p, options, CB) + }, time) + } + + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < options.emfileWait) { + return setTimeout(function () { + rimraf_(p, options, CB) + }, timeout ++) + } + + // already gone + if (er.code === "ENOENT") er = null + } + + timeout = 0 + next(er) + }) + }) + } +} + +// Two possible strategies. +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR +// +// Both result in an extra syscall when you guess wrong. However, there +// are likely far more normal files in the world than directories. This +// is based on the assumption that a the average number of files per +// directory is >= 1. +// +// If anyone ever complains about this, then I guess the strategy could +// be made configurable somehow. But until then, YAGNI. +function rimraf_ (p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + + // sunos lets the root user unlink directories, which is... weird. + // so we have to lstat here and make sure it's not a dir. + options.lstat(p, function (er, st) { + if (er && er.code === "ENOENT") + return cb(null) + + // Windows can EPERM on stat. Life is suffering. + if (er && er.code === "EPERM" && isWindows) + fixWinEPERM(p, options, er, cb) + + if (st && st.isDirectory()) + return rmdir(p, options, er, cb) + + options.unlink(p, function (er) { + if (er) { + if (er.code === "ENOENT") + return cb(null) + if (er.code === "EPERM") + return (isWindows) + ? fixWinEPERM(p, options, er, cb) + : rmdir(p, options, er, cb) + if (er.code === "EISDIR") + return rmdir(p, options, er, cb) + } + return cb(er) + }) + }) +} + +function fixWinEPERM (p, options, er, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + if (er) + assert(er instanceof Error) + + options.chmod(p, _0666, function (er2) { + if (er2) + cb(er2.code === "ENOENT" ? null : er) + else + options.stat(p, function(er3, stats) { + if (er3) + cb(er3.code === "ENOENT" ? null : er) + else if (stats.isDirectory()) + rmdir(p, options, er, cb) + else + options.unlink(p, cb) + }) + }) +} + +function fixWinEPERMSync (p, options, er) { + assert(p) + assert(options) + if (er) + assert(er instanceof Error) + + try { + options.chmodSync(p, _0666) + } catch (er2) { + if (er2.code === "ENOENT") + return + else + throw er + } + + try { + var stats = options.statSync(p) + } catch (er3) { + if (er3.code === "ENOENT") + return + else + throw er + } + + if (stats.isDirectory()) + rmdirSync(p, options, er) + else + options.unlinkSync(p) +} + +function rmdir (p, options, originalEr, cb) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) + assert(typeof cb === 'function') + + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) + // if we guessed wrong, and it's not a directory, then + // raise the original error. + options.rmdir(p, function (er) { + if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) + rmkids(p, options, cb) + else if (er && er.code === "ENOTDIR") + cb(originalEr) + else + cb(er) + }) +} + +function rmkids(p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + + options.readdir(p, function (er, files) { + if (er) + return cb(er) + var n = files.length + if (n === 0) + return options.rmdir(p, cb) + var errState + files.forEach(function (f) { + rimraf(path.join(p, f), options, function (er) { + if (errState) + return + if (er) + return cb(errState = er) + if (--n === 0) + options.rmdir(p, cb) + }) + }) + }) +} + +// this looks simpler, and is strictly *faster*, but will +// tie up the JavaScript thread and fail on excessively +// deep directory trees. +function rimrafSync (p, options) { + options = options || {} + defaults(options) + + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert(options, 'rimraf: missing options') + assert.equal(typeof options, 'object', 'rimraf: options should be object') + + var results + + if (options.disableGlob || !glob.hasMagic(p)) { + results = [p] + } else { + try { + options.lstatSync(p) + results = [p] + } catch (er) { + results = glob.sync(p, options.glob) + } + } + + if (!results.length) + return + + for (var i = 0; i < results.length; i++) { + var p = results[i] + + try { + var st = options.lstatSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + + // Windows can EPERM on stat. Life is suffering. + if (er.code === "EPERM" && isWindows) + fixWinEPERMSync(p, options, er) + } + + try { + // sunos lets the root user unlink directories, which is... weird. + if (st && st.isDirectory()) + rmdirSync(p, options, null) + else + options.unlinkSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "EPERM") + return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) + if (er.code !== "EISDIR") + throw er + + rmdirSync(p, options, er) + } + } +} + +function rmdirSync (p, options, originalEr) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) + + try { + options.rmdirSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "ENOTDIR") + throw originalEr + if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") + rmkidsSync(p, options) + } +} + +function rmkidsSync (p, options) { + assert(p) + assert(options) + options.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f), options) + }) + + // We only end up here once we got ENOTEMPTY at least once, and + // at this point, we are guaranteed to have removed all the kids. + // So, we know that it won't be ENOENT or ENOTDIR or anything else. + // try really hard to delete stuff on windows, because it has a + // PROFOUNDLY annoying habit of not closing handles promptly when + // files are deleted, resulting in spurious ENOTEMPTY errors. + var retries = isWindows ? 100 : 1 + var i = 0 + do { + var threw = true + try { + var ret = options.rmdirSync(p, options) + threw = false + return ret + } finally { + if (++i < retries && threw) + continue + } + } while (true) +} diff --git a/js/node_modules/fsevents/node_modules/safe-buffer/.travis.yml b/js/node_modules/fsevents/node_modules/safe-buffer/.travis.yml new file mode 100644 index 0000000..7b20f28 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safe-buffer/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - 'node' + - '5' + - '4' + - '0.12' + - '0.10' diff --git a/js/node_modules/fsevents/node_modules/safe-buffer/LICENSE b/js/node_modules/fsevents/node_modules/safe-buffer/LICENSE new file mode 100644 index 0000000..0c068ce --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safe-buffer/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/safe-buffer/README.md b/js/node_modules/fsevents/node_modules/safe-buffer/README.md new file mode 100644 index 0000000..e9a81af --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safe-buffer/README.md @@ -0,0 +1,584 @@ +# safe-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] + +[travis-image]: https://img.shields.io/travis/feross/safe-buffer/master.svg +[travis-url]: https://travis-ci.org/feross/safe-buffer +[npm-image]: https://img.shields.io/npm/v/safe-buffer.svg +[npm-url]: https://npmjs.org/package/safe-buffer +[downloads-image]: https://img.shields.io/npm/dm/safe-buffer.svg +[downloads-url]: https://npmjs.org/package/safe-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com + +#### Safer Node.js Buffer API + +**Use the new Node.js Buffer APIs (`Buffer.from`, `Buffer.alloc`, +`Buffer.allocUnsafe`, `Buffer.allocUnsafeSlow`) in all versions of Node.js.** + +**Uses the built-in implementation when available.** + +## install + +``` +npm install safe-buffer +``` + +## usage + +The goal of this package is to provide a safe replacement for the node.js `Buffer`. + +It's a drop-in replacement for `Buffer`. You can use it by adding one `require` line to +the top of your node.js modules: + +```js +var Buffer = require('safe-buffer').Buffer + +// Existing buffer code will continue to work without issues: + +new Buffer('hey', 'utf8') +new Buffer([1, 2, 3], 'utf8') +new Buffer(obj) +new Buffer(16) // create an uninitialized buffer (potentially unsafe) + +// But you can use these new explicit APIs to make clear what you want: + +Buffer.from('hey', 'utf8') // convert from many types to a Buffer +Buffer.alloc(16) // create a zero-filled buffer (safe) +Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe) +``` + +## api + +### Class Method: Buffer.from(array) + + +* `array` {Array} + +Allocates a new `Buffer` using an `array` of octets. + +```js +const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]); + // creates a new Buffer containing ASCII bytes + // ['b','u','f','f','e','r'] +``` + +A `TypeError` will be thrown if `array` is not an `Array`. + +### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]]) + + +* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or + a `new ArrayBuffer()` +* `byteOffset` {Number} Default: `0` +* `length` {Number} Default: `arrayBuffer.length - byteOffset` + +When passed a reference to the `.buffer` property of a `TypedArray` instance, +the newly created `Buffer` will share the same allocated memory as the +TypedArray. + +```js +const arr = new Uint16Array(2); +arr[0] = 5000; +arr[1] = 4000; + +const buf = Buffer.from(arr.buffer); // shares the memory with arr; + +console.log(buf); + // Prints: + +// changing the TypedArray changes the Buffer also +arr[1] = 6000; + +console.log(buf); + // Prints: +``` + +The optional `byteOffset` and `length` arguments specify a memory range within +the `arrayBuffer` that will be shared by the `Buffer`. + +```js +const ab = new ArrayBuffer(10); +const buf = Buffer.from(ab, 0, 2); +console.log(buf.length); + // Prints: 2 +``` + +A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`. + +### Class Method: Buffer.from(buffer) + + +* `buffer` {Buffer} + +Copies the passed `buffer` data onto a new `Buffer` instance. + +```js +const buf1 = Buffer.from('buffer'); +const buf2 = Buffer.from(buf1); + +buf1[0] = 0x61; +console.log(buf1.toString()); + // 'auffer' +console.log(buf2.toString()); + // 'buffer' (copy is not changed) +``` + +A `TypeError` will be thrown if `buffer` is not a `Buffer`. + +### Class Method: Buffer.from(str[, encoding]) + + +* `str` {String} String to encode. +* `encoding` {String} Encoding to use, Default: `'utf8'` + +Creates a new `Buffer` containing the given JavaScript string `str`. If +provided, the `encoding` parameter identifies the character encoding. +If not provided, `encoding` defaults to `'utf8'`. + +```js +const buf1 = Buffer.from('this is a tést'); +console.log(buf1.toString()); + // prints: this is a tést +console.log(buf1.toString('ascii')); + // prints: this is a tC)st + +const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); +console.log(buf2.toString()); + // prints: this is a tést +``` + +A `TypeError` will be thrown if `str` is not a string. + +### Class Method: Buffer.alloc(size[, fill[, encoding]]) + + +* `size` {Number} +* `fill` {Value} Default: `undefined` +* `encoding` {String} Default: `utf8` + +Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the +`Buffer` will be *zero-filled*. + +```js +const buf = Buffer.alloc(5); +console.log(buf); + // +``` + +The `size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +If `fill` is specified, the allocated `Buffer` will be initialized by calling +`buf.fill(fill)`. See [`buf.fill()`][] for more information. + +```js +const buf = Buffer.alloc(5, 'a'); +console.log(buf); + // +``` + +If both `fill` and `encoding` are specified, the allocated `Buffer` will be +initialized by calling `buf.fill(fill, encoding)`. For example: + +```js +const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); +console.log(buf); + // +``` + +Calling `Buffer.alloc(size)` can be significantly slower than the alternative +`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance +contents will *never contain sensitive data*. + +A `TypeError` will be thrown if `size` is not a number. + +### Class Method: Buffer.allocUnsafe(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must +be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit +architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is +thrown. A zero-length Buffer will be created if a `size` less than or equal to +0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +```js +const buf = Buffer.allocUnsafe(5); +console.log(buf); + // + // (octets will be different, every time) +buf.fill(0); +console.log(buf); + // +``` + +A `TypeError` will be thrown if `size` is not a number. + +Note that the `Buffer` module pre-allocates an internal `Buffer` instance of +size `Buffer.poolSize` that is used as a pool for the fast allocation of new +`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated +`new Buffer(size)` constructor) only when `size` is less than or equal to +`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default +value of `Buffer.poolSize` is `8192` but can be modified. + +Use of this pre-allocated internal memory pool is a key difference between +calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. +Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer +pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal +Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The +difference is subtle but can be important when an application requires the +additional performance that `Buffer.allocUnsafe(size)` provides. + +### Class Method: Buffer.allocUnsafeSlow(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The +`size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, +allocations under 4KB are, by default, sliced from a single pre-allocated +`Buffer`. This allows applications to avoid the garbage collection overhead of +creating many individually allocated Buffers. This approach improves both +performance and memory usage by eliminating the need to track and cleanup as +many `Persistent` objects. + +However, in the case where a developer may need to retain a small chunk of +memory from a pool for an indeterminate amount of time, it may be appropriate +to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then +copy out the relevant bits. + +```js +// need to keep around a few small chunks of memory +const store = []; + +socket.on('readable', () => { + const data = socket.read(); + // allocate for retained data + const sb = Buffer.allocUnsafeSlow(10); + // copy the data into the new allocation + data.copy(sb, 0, 0, 10); + store.push(sb); +}); +``` + +Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after* +a developer has observed undue memory retention in their applications. + +A `TypeError` will be thrown if `size` is not a number. + +### All the Rest + +The rest of the `Buffer` API is exactly the same as in node.js. +[See the docs](https://nodejs.org/api/buffer.html). + + +## Related links + +- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660) +- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4) + +## Why is `Buffer` unsafe? + +Today, the node.js `Buffer` constructor is overloaded to handle many different argument +types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.), +`ArrayBuffer`, and also `Number`. + +The API is optimized for convenience: you can throw any type at it, and it will try to do +what you want. + +Because the Buffer constructor is so powerful, you often see code like this: + +```js +// Convert UTF-8 strings to hex +function toHex (str) { + return new Buffer(str).toString('hex') +} +``` + +***But what happens if `toHex` is called with a `Number` argument?*** + +### Remote Memory Disclosure + +If an attacker can make your program call the `Buffer` constructor with a `Number` +argument, then they can make it allocate uninitialized memory from the node.js process. +This could potentially disclose TLS private keys, user data, or database passwords. + +When the `Buffer` constructor is passed a `Number` argument, it returns an +**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like +this, you **MUST** overwrite the contents before returning it to the user. + +From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size): + +> `new Buffer(size)` +> +> - `size` Number +> +> The underlying memory for `Buffer` instances created in this way is not initialized. +> **The contents of a newly created `Buffer` are unknown and could contain sensitive +> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes. + +(Emphasis our own.) + +Whenever the programmer intended to create an uninitialized `Buffer` you often see code +like this: + +```js +var buf = new Buffer(16) + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### Would this ever be a problem in real code? + +Yes. It's surprisingly common to forget to check the type of your variables in a +dynamically-typed language like JavaScript. + +Usually the consequences of assuming the wrong type is that your program crashes with an +uncaught exception. But the failure mode for forgetting to check the type of arguments to +the `Buffer` constructor is more catastrophic. + +Here's an example of a vulnerable service that takes a JSON payload and converts it to +hex: + +```js +// Take a JSON payload {str: "some string"} and convert it to hex +var server = http.createServer(function (req, res) { + var data = '' + req.setEncoding('utf8') + req.on('data', function (chunk) { + data += chunk + }) + req.on('end', function () { + var body = JSON.parse(data) + res.end(new Buffer(body.str).toString('hex')) + }) +}) + +server.listen(8080) +``` + +In this example, an http client just has to send: + +```json +{ + "str": 1000 +} +``` + +and it will get back 1,000 bytes of uninitialized memory from the server. + +This is a very serious bug. It's similar in severity to the +[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process +memory by remote attackers. + + +### Which real-world packages were vulnerable? + +#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht) + +[Mathias Buus](https://github.com/mafintosh) and I +([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages, +[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow +anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get +them to reveal 20 bytes at a time of uninitialized memory from the node.js process. + +Here's +[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8) +that fixed it. We released a new fixed version, created a +[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all +vulnerable versions on npm so users will get a warning to upgrade to a newer version. + +#### [`ws`](https://www.npmjs.com/package/ws) + +That got us wondering if there were other vulnerable packages. Sure enough, within a short +period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the +most popular WebSocket implementation in node.js. + +If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as +expected, then uninitialized server memory would be disclosed to the remote peer. + +These were the vulnerable methods: + +```js +socket.send(number) +socket.ping(number) +socket.pong(number) +``` + +Here's a vulnerable socket server with some echo functionality: + +```js +server.on('connection', function (socket) { + socket.on('message', function (message) { + message = JSON.parse(message) + if (message.type === 'echo') { + socket.send(message.data) // send back the user's message + } + }) +}) +``` + +`socket.send(number)` called on the server, will disclose server memory. + +Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue +was fixed, with a more detailed explanation. Props to +[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the +[Node Security Project disclosure](https://nodesecurity.io/advisories/67). + + +### What's the solution? + +It's important that node.js offers a fast way to get memory otherwise performance-critical +applications would needlessly get a lot slower. + +But we need a better way to *signal our intent* as programmers. **When we want +uninitialized memory, we should request it explicitly.** + +Sensitive functionality should not be packed into a developer-friendly API that loosely +accepts many different types. This type of API encourages the lazy practice of passing +variables in without checking the type very carefully. + +#### A new API: `Buffer.allocUnsafe(number)` + +The functionality of creating buffers with uninitialized memory should be part of another +API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that +frequently gets user input of all sorts of different types passed into it. + +```js +var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory! + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### How do we fix node.js core? + +We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as +`semver-major`) which defends against one case: + +```js +var str = 16 +new Buffer(str, 'utf8') +``` + +In this situation, it's implied that the programmer intended the first argument to be a +string, since they passed an encoding as a second argument. Today, node.js will allocate +uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not +what the programmer intended. + +But this is only a partial solution, since if the programmer does `new Buffer(variable)` +(without an `encoding` parameter) there's no way to know what they intended. If `variable` +is sometimes a number, then uninitialized memory will sometimes be returned. + +### What's the real long-term fix? + +We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when +we need uninitialized memory. But that would break 1000s of packages. + +~~We believe the best solution is to:~~ + +~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~ + +~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~ + +#### Update + +We now support adding three new APIs: + +- `Buffer.from(value)` - convert from any type to a buffer +- `Buffer.alloc(size)` - create a zero-filled buffer +- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size + +This solves the core problem that affected `ws` and `bittorrent-dht` which is +`Buffer(variable)` getting tricked into taking a number argument. + +This way, existing code continues working and the impact on the npm ecosystem will be +minimal. Over time, npm maintainers can migrate performance-critical code to use +`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`. + + +### Conclusion + +We think there's a serious design issue with the `Buffer` API as it exists today. It +promotes insecure software by putting high-risk functionality into a convenient API +with friendly "developer ergonomics". + +This wasn't merely a theoretical exercise because we found the issue in some of the +most popular npm packages. + +Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of +`buffer`. + +```js +var Buffer = require('safe-buffer').Buffer +``` + +Eventually, we hope that node.js core can switch to this new, safer behavior. We believe +the impact on the ecosystem would be minimal since it's not a breaking change. +Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while +older, insecure packages would magically become safe from this attack vector. + + +## links + +- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514) +- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67) +- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68) + + +## credit + +The original issues in `bittorrent-dht` +([disclosure](https://nodesecurity.io/advisories/68)) and +`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by +[Mathias Buus](https://github.com/mafintosh) and +[Feross Aboukhadijeh](http://feross.org/). + +Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues +and for his work running the [Node Security Project](https://nodesecurity.io/). + +Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and +auditing the code. + + +## license + +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org) diff --git a/js/node_modules/fsevents/node_modules/safe-buffer/index.js b/js/node_modules/fsevents/node_modules/safe-buffer/index.js new file mode 100644 index 0000000..22438da --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safe-buffer/index.js @@ -0,0 +1,62 @@ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} diff --git a/js/node_modules/fsevents/node_modules/safe-buffer/package.json b/js/node_modules/fsevents/node_modules/safe-buffer/package.json new file mode 100644 index 0000000..cd1d646 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safe-buffer/package.json @@ -0,0 +1,68 @@ +{ + "_args": [ + [ + "safe-buffer@5.1.1", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "safe-buffer@5.1.1", + "_id": "safe-buffer@5.1.1", + "_inBundle": true, + "_integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "_location": "/fsevents/safe-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "safe-buffer@5.1.1", + "name": "safe-buffer", + "escapedName": "safe-buffer", + "rawSpec": "5.1.1", + "saveSpec": null, + "fetchSpec": "5.1.1" + }, + "_requiredBy": [ + "/fsevents/minipass", + "/fsevents/readable-stream", + "/fsevents/string_decoder", + "/fsevents/tar" + ], + "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "_spec": "5.1.1", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "http://feross.org" + }, + "bugs": { + "url": "https://github.com/feross/safe-buffer/issues" + }, + "description": "Safer Node.js Buffer API", + "devDependencies": { + "standard": "*", + "tape": "^4.0.0", + "zuul": "^3.0.0" + }, + "homepage": "https://github.com/feross/safe-buffer", + "keywords": [ + "buffer", + "buffer allocate", + "node security", + "safe", + "safe-buffer", + "security", + "uninitialized" + ], + "license": "MIT", + "main": "index.js", + "name": "safe-buffer", + "repository": { + "type": "git", + "url": "git://github.com/feross/safe-buffer.git" + }, + "scripts": { + "test": "standard && tape test.js" + }, + "version": "5.1.1" +} diff --git a/js/node_modules/fsevents/node_modules/safe-buffer/test.js b/js/node_modules/fsevents/node_modules/safe-buffer/test.js new file mode 100644 index 0000000..4925059 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safe-buffer/test.js @@ -0,0 +1,101 @@ +/* eslint-disable node/no-deprecated-api */ + +var test = require('tape') +var SafeBuffer = require('./').Buffer + +test('new SafeBuffer(value) works just like Buffer', function (t) { + t.deepEqual(new SafeBuffer('hey'), new Buffer('hey')) + t.deepEqual(new SafeBuffer('hey', 'utf8'), new Buffer('hey', 'utf8')) + t.deepEqual(new SafeBuffer('686579', 'hex'), new Buffer('686579', 'hex')) + t.deepEqual(new SafeBuffer([1, 2, 3]), new Buffer([1, 2, 3])) + t.deepEqual(new SafeBuffer(new Uint8Array([1, 2, 3])), new Buffer(new Uint8Array([1, 2, 3]))) + + t.equal(typeof SafeBuffer.isBuffer, 'function') + t.equal(SafeBuffer.isBuffer(new SafeBuffer('hey')), true) + t.equal(Buffer.isBuffer(new SafeBuffer('hey')), true) + t.notOk(SafeBuffer.isBuffer({})) + + t.end() +}) + +test('SafeBuffer.from(value) converts to a Buffer', function (t) { + t.deepEqual(SafeBuffer.from('hey'), new Buffer('hey')) + t.deepEqual(SafeBuffer.from('hey', 'utf8'), new Buffer('hey', 'utf8')) + t.deepEqual(SafeBuffer.from('686579', 'hex'), new Buffer('686579', 'hex')) + t.deepEqual(SafeBuffer.from([1, 2, 3]), new Buffer([1, 2, 3])) + t.deepEqual(SafeBuffer.from(new Uint8Array([1, 2, 3])), new Buffer(new Uint8Array([1, 2, 3]))) + + t.end() +}) + +test('SafeBuffer.alloc(number) returns zeroed-out memory', function (t) { + for (var i = 0; i < 10; i++) { + var expected1 = new Buffer(1000) + expected1.fill(0) + t.deepEqual(SafeBuffer.alloc(1000), expected1) + + var expected2 = new Buffer(1000 * 1000) + expected2.fill(0) + t.deepEqual(SafeBuffer.alloc(1000 * 1000), expected2) + } + t.end() +}) + +test('SafeBuffer.allocUnsafe(number)', function (t) { + var buf = SafeBuffer.allocUnsafe(100) // unitialized memory + t.equal(buf.length, 100) + t.equal(SafeBuffer.isBuffer(buf), true) + t.equal(Buffer.isBuffer(buf), true) + t.end() +}) + +test('SafeBuffer.from() throws with number types', function (t) { + t.plan(5) + t.throws(function () { + SafeBuffer.from(0) + }) + t.throws(function () { + SafeBuffer.from(-1) + }) + t.throws(function () { + SafeBuffer.from(NaN) + }) + t.throws(function () { + SafeBuffer.from(Infinity) + }) + t.throws(function () { + SafeBuffer.from(99) + }) +}) + +test('SafeBuffer.allocUnsafe() throws with non-number types', function (t) { + t.plan(4) + t.throws(function () { + SafeBuffer.allocUnsafe('hey') + }) + t.throws(function () { + SafeBuffer.allocUnsafe('hey', 'utf8') + }) + t.throws(function () { + SafeBuffer.allocUnsafe([1, 2, 3]) + }) + t.throws(function () { + SafeBuffer.allocUnsafe({}) + }) +}) + +test('SafeBuffer.alloc() throws with non-number types', function (t) { + t.plan(4) + t.throws(function () { + SafeBuffer.alloc('hey') + }) + t.throws(function () { + SafeBuffer.alloc('hey', 'utf8') + }) + t.throws(function () { + SafeBuffer.alloc([1, 2, 3]) + }) + t.throws(function () { + SafeBuffer.alloc({}) + }) +}) diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/LICENSE b/js/node_modules/fsevents/node_modules/safer-buffer/LICENSE new file mode 100644 index 0000000..4fe9e6f --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Nikita Skovoroda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/Porting-Buffer.md b/js/node_modules/fsevents/node_modules/safer-buffer/Porting-Buffer.md new file mode 100644 index 0000000..68d86ba --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/Porting-Buffer.md @@ -0,0 +1,268 @@ +# Porting to the Buffer.from/Buffer.alloc API + + +## Overview + +- [Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x.](#variant-1) (*recommended*) +- [Variant 2: Use a polyfill](#variant-2) +- [Variant 3: manual detection, with safeguards](#variant-3) + +### Finding problematic bits of code using grep + +Just run `grep -nrE '[^a-zA-Z](Slow)?Buffer\s*\(' --exclude-dir node_modules`. + +It will find all the potentially unsafe places in your own code (with some considerably unlikely +exceptions). + +### Finding problematic bits of code using Node.js 8 + +If you’re using Node.js ≥ 8.0.0 (which is recommended), Node.js exposes multiple options that help with finding the relevant pieces of code: + +- `--trace-warnings` will make Node.js show a stack trace for this warning and other warnings that are printed by Node.js. +- `--trace-deprecation` does the same thing, but only for deprecation warnings. +- `--pending-deprecation` will show more types of deprecation warnings. In particular, it will show the `Buffer()` deprecation warning, even on Node.js 8. + +You can set these flags using an environment variable: + +```console +$ export NODE_OPTIONS='--trace-warnings --pending-deprecation' +$ cat example.js +'use strict'; +const foo = new Buffer('foo'); +$ node example.js +(node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead. + at showFlaggedDeprecation (buffer.js:127:13) + at new Buffer (buffer.js:148:3) + at Object. (/path/to/example.js:2:13) + [... more stack trace lines ...] +``` + +### Finding problematic bits of code using linters + +Eslint rules [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +also find calls to deprecated `Buffer()` API. Those rules are included in some pre-sets. + +There is a drawback, though, that it doesn't always +[work correctly](https://github.com/chalker/safer-buffer#why-not-safe-buffer) when `Buffer` is +overriden e.g. with a polyfill, so recommended is a combination of this and some other method +described above. + + +## Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x. + +This is the recommended solution nowadays that would imply only minimal overhead. + +The Node.js 5.x release line has been unsupported since July 2016, and the Node.js 4.x release line reaches its End of Life in April 2018 (→ [Schedule](https://github.com/nodejs/Release#release-schedule)). This means that these versions of Node.js will *not* receive any updates, even in case of security issues, so using these release lines should be avoided, if at all possible. + +What you would do in this case is to convert all `new Buffer()` or `Buffer()` calls to use `Buffer.alloc()` or `Buffer.from()`, in the following way: + +- For `new Buffer(number)`, replace it with `Buffer.alloc(number)`. +- For `new Buffer(string)` (or `new Buffer(string, encoding)`), replace it with `Buffer.from(string)` (or `Buffer.from(string, encoding)`). +- For all other combinations of arguments (these are much rarer), also replace `new Buffer(...arguments)` with `Buffer.from(...arguments)`. + +Note that `Buffer.alloc()` is also _faster_ on the current Node.js versions than +`new Buffer(size).fill(0)`, which is what you would otherwise need to ensure zero-filling. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended to avoid accidential unsafe Buffer API usage. + +There is also a [JSCodeshift codemod](https://github.com/joyeecheung/node-dep-codemod#dep005) +for automatically migrating Buffer constructors to `Buffer.alloc()` or `Buffer.from()`. +Note that it currently only works with cases where the arguments are literals or where the +constructor is invoked with two arguments. + +_If you currently support those older Node.js versions and dropping them would be a semver-major change +for you, or if you support older branches of your packages, consider using [Variant 2](#variant-2) +or [Variant 3](#variant-3) on older branches, so people using those older branches will also receive +the fix. That way, you will eradicate potential issues caused by unguarded Buffer API usage and +your users will not observe a runtime deprecation warning when running your code on Node.js 10._ + + +## Variant 2: Use a polyfill + +Utilize [safer-buffer](https://www.npmjs.com/package/safer-buffer) as a polyfill to support older +Node.js versions. + +You would take exacly the same steps as in [Variant 1](#variant-1), but with a polyfill +`const Buffer = require('safer-buffer').Buffer` in all files where you use the new `Buffer` api. + +Make sure that you do not use old `new Buffer` API — in any files where the line above is added, +using old `new Buffer()` API will _throw_. It will be easy to notice that in CI, though. + +Alternatively, you could use [buffer-from](https://www.npmjs.com/package/buffer-from) and/or +[buffer-alloc](https://www.npmjs.com/package/buffer-alloc) [ponyfills](https://ponyfill.com/) — +those are great, the only downsides being 4 deps in the tree and slightly more code changes to +migrate off them (as you would be using e.g. `Buffer.from` under a different name). If you need only +`Buffer.from` polyfilled — `buffer-from` alone which comes with no extra dependencies. + +_Alternatively, you could use [safe-buffer](https://www.npmjs.com/package/safe-buffer) — it also +provides a polyfill, but takes a different approach which has +[it's drawbacks](https://github.com/chalker/safer-buffer#why-not-safe-buffer). It will allow you +to also use the older `new Buffer()` API in your code, though — but that's arguably a benefit, as +it is problematic, can cause issues in your code, and will start emitting runtime deprecation +warnings starting with Node.js 10._ + +Note that in either case, it is important that you also remove all calls to the old Buffer +API manually — just throwing in `safe-buffer` doesn't fix the problem by itself, it just provides +a polyfill for the new API. I have seen people doing that mistake. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended. + +_Don't forget to drop the polyfill usage once you drop support for Node.js < 4.5.0._ + + +## Variant 3 — manual detection, with safeguards + +This is useful if you create Buffer instances in only a few places (e.g. one), or you have your own +wrapper around them. + +### Buffer(0) + +This special case for creating empty buffers can be safely replaced with `Buffer.concat([])`, which +returns the same result all the way down to Node.js 0.8.x. + +### Buffer(notNumber) + +Before: + +```js +var buf = new Buffer(notNumber, encoding); +``` + +After: + +```js +var buf; +if (Buffer.from && Buffer.from !== Uint8Array.from) { + buf = Buffer.from(notNumber, encoding); +} else { + if (typeof notNumber === 'number') + throw new Error('The "size" argument must be of type number.'); + buf = new Buffer(notNumber, encoding); +} +``` + +`encoding` is optional. + +Note that the `typeof notNumber` before `new Buffer` is required (for cases when `notNumber` argument is not +hard-coded) and _is not caused by the deprecation of Buffer constructor_ — it's exactly _why_ the +Buffer constructor is deprecated. Ecosystem packages lacking this type-check caused numereous +security issues — situations when unsanitized user input could end up in the `Buffer(arg)` create +problems ranging from DoS to leaking sensitive information to the attacker from the process memory. + +When `notNumber` argument is hardcoded (e.g. literal `"abc"` or `[0,1,2]`), the `typeof` check can +be omitted. + +Also note that using TypeScript does not fix this problem for you — when libs written in +`TypeScript` are used from JS, or when user input ends up there — it behaves exactly as pure JS, as +all type checks are translation-time only and are not present in the actual JS code which TS +compiles to. + +### Buffer(number) + +For Node.js 0.10.x (and below) support: + +```js +var buf; +if (Buffer.alloc) { + buf = Buffer.alloc(number); +} else { + buf = new Buffer(number); + buf.fill(0); +} +``` + +Otherwise (Node.js ≥ 0.12.x): + +```js +const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0); +``` + +## Regarding Buffer.allocUnsafe + +Be extra cautious when using `Buffer.allocUnsafe`: + * Don't use it if you don't have a good reason to + * e.g. you probably won't ever see a performance difference for small buffers, in fact, those + might be even faster with `Buffer.alloc()`, + * if your code is not in the hot code path — you also probably won't notice a difference, + * keep in mind that zero-filling minimizes the potential risks. + * If you use it, make sure that you never return the buffer in a partially-filled state, + * if you are writing to it sequentially — always truncate it to the actuall written length + +Errors in handling buffers allocated with `Buffer.allocUnsafe` could result in various issues, +ranged from undefined behaviour of your code to sensitive data (user input, passwords, certs) +leaking to the remote attacker. + +_Note that the same applies to `new Buffer` usage without zero-filling, depending on the Node.js +version (and lacking type checks also adds DoS to the list of potential problems)._ + + +## FAQ + + +### What is wrong with the `Buffer` constructor? + +The `Buffer` constructor could be used to create a buffer in many different ways: + +- `new Buffer(42)` creates a `Buffer` of 42 bytes. Before Node.js 8, this buffer contained + *arbitrary memory* for performance reasons, which could include anything ranging from + program source code to passwords and encryption keys. +- `new Buffer('abc')` creates a `Buffer` that contains the UTF-8-encoded version of + the string `'abc'`. A second argument could specify another encoding: For example, + `new Buffer(string, 'base64')` could be used to convert a Base64 string into the original + sequence of bytes that it represents. +- There are several other combinations of arguments. + +This meant that, in code like `var buffer = new Buffer(foo);`, *it is not possible to tell +what exactly the contents of the generated buffer are* without knowing the type of `foo`. + +Sometimes, the value of `foo` comes from an external source. For example, this function +could be exposed as a service on a web server, converting a UTF-8 string into its Base64 form: + +``` +function stringToBase64(req, res) { + // The request body should have the format of `{ string: 'foobar' }` + const rawBytes = new Buffer(req.body.string) + const encoded = rawBytes.toString('base64') + res.end({ encoded: encoded }) +} +``` + +Note that this code does *not* validate the type of `req.body.string`: + +- `req.body.string` is expected to be a string. If this is the case, all goes well. +- `req.body.string` is controlled by the client that sends the request. +- If `req.body.string` is the *number* `50`, the `rawBytes` would be 50 bytes: + - Before Node.js 8, the content would be uninitialized + - After Node.js 8, the content would be `50` bytes with the value `0` + +Because of the missing type check, an attacker could intentionally send a number +as part of the request. Using this, they can either: + +- Read uninitialized memory. This **will** leak passwords, encryption keys and other + kinds of sensitive information. (Information leak) +- Force the program to allocate a large amount of memory. For example, when specifying + `500000000` as the input value, each request will allocate 500MB of memory. + This can be used to either exhaust the memory available of a program completely + and make it crash, or slow it down significantly. (Denial of Service) + +Both of these scenarios are considered serious security issues in a real-world +web server context. + +when using `Buffer.from(req.body.string)` instead, passing a number will always +throw an exception instead, giving a controlled behaviour that can always be +handled by the program. + + +### The `Buffer()` constructor has been deprecated for a while. Is this really an issue? + +Surveys of code in the `npm` ecosystem have shown that the `Buffer()` constructor is still +widely used. This includes new code, and overall usage of such code has actually been +*increasing*. diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/Readme.md b/js/node_modules/fsevents/node_modules/safer-buffer/Readme.md new file mode 100644 index 0000000..14b0822 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/Readme.md @@ -0,0 +1,156 @@ +# safer-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![javascript style guide][standard-image]][standard-url] [![Security Responsible Disclosure][secuirty-image]][secuirty-url] + +[travis-image]: https://travis-ci.org/ChALkeR/safer-buffer.svg?branch=master +[travis-url]: https://travis-ci.org/ChALkeR/safer-buffer +[npm-image]: https://img.shields.io/npm/v/safer-buffer.svg +[npm-url]: https://npmjs.org/package/safer-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com +[secuirty-image]: https://img.shields.io/badge/Security-Responsible%20Disclosure-green.svg +[secuirty-url]: https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md + +Modern Buffer API polyfill without footguns, working on Node.js from 0.8 to current. + +## How to use? + +First, port all `Buffer()` and `new Buffer()` calls to `Buffer.alloc()` and `Buffer.from()` API. + +Then, to achieve compatibility with outdated Node.js versions (`<4.5.0` and 5.x `<5.9.0`), use +`const Buffer = require('safer-buffer').Buffer` in all files where you make calls to the new +Buffer API. _Use `var` instead of `const` if you need that for your Node.js version range support._ + +Also, see the +[porting Buffer](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) guide. + +## Do I need it? + +Hopefully, not — dropping support for outdated Node.js versions should be fine nowdays, and that +is the recommended path forward. You _do_ need to port to the `Buffer.alloc()` and `Buffer.from()` +though. + +See the [porting guide](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) +for a better description. + +## Why not [safe-buffer](https://npmjs.com/safe-buffer)? + +_In short: while `safe-buffer` serves as a polyfill for the new API, it allows old API usage and +itself contains footguns._ + +`safe-buffer` could be used safely to get the new API while still keeping support for older +Node.js versions (like this module), but while analyzing ecosystem usage of the old Buffer API +I found out that `safe-buffer` is itself causing problems in some cases. + +For example, consider the following snippet: + +```console +$ cat example.unsafe.js +console.log(Buffer(20)) +$ ./node-v6.13.0-linux-x64/bin/node example.unsafe.js + +$ standard example.unsafe.js +standard: Use JavaScript Standard Style (https://standardjs.com) + /home/chalker/repo/safer-buffer/example.unsafe.js:2:13: 'Buffer()' was deprecated since v6. Use 'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<4.5.0') instead. +``` + +This is allocates and writes to console an uninitialized chunk of memory. +[standard](https://www.npmjs.com/package/standard) linter (among others) catch that and warn people +to avoid using unsafe API. + +Let's now throw in `safe-buffer`! + +```console +$ cat example.safe-buffer.js +const Buffer = require('safe-buffer').Buffer +console.log(Buffer(20)) +$ standard example.safe-buffer.js +$ ./node-v6.13.0-linux-x64/bin/node example.safe-buffer.js + +``` + +See the problem? Adding in `safe-buffer` _magically removes the lint warning_, but the behavior +remains identiсal to what we had before, and when launched on Node.js 6.x LTS — this dumps out +chunks of uninitialized memory. +_And this code will still emit runtime warnings on Node.js 10.x and above._ + +That was done by design. I first considered changing `safe-buffer`, prohibiting old API usage or +emitting warnings on it, but that significantly diverges from `safe-buffer` design. After some +discussion, it was decided to move my approach into a separate package, and _this is that separate +package_. + +This footgun is not imaginary — I observed top-downloaded packages doing that kind of thing, +«fixing» the lint warning by blindly including `safe-buffer` without any actual changes. + +Also in some cases, even if the API _was_ migrated to use of safe Buffer API — a random pull request +can bring unsafe Buffer API usage back to the codebase by adding new calls — and that could go +unnoticed even if you have a linter prohibiting that (becase of the reason stated above), and even +pass CI. _I also observed that being done in popular packages._ + +Some examples: + * [webdriverio](https://github.com/webdriverio/webdriverio/commit/05cbd3167c12e4930f09ef7cf93b127ba4effae4#diff-124380949022817b90b622871837d56cR31) + (a module with 548 759 downloads/month), + * [websocket-stream](https://github.com/maxogden/websocket-stream/commit/c9312bd24d08271687d76da0fe3c83493871cf61) + (218 288 d/m, fix in [maxogden/websocket-stream#142](https://github.com/maxogden/websocket-stream/pull/142)), + * [node-serialport](https://github.com/node-serialport/node-serialport/commit/e8d9d2b16c664224920ce1c895199b1ce2def48c) + (113 138 d/m, fix in [node-serialport/node-serialport#1510](https://github.com/node-serialport/node-serialport/pull/1510)), + * [karma](https://github.com/karma-runner/karma/commit/3d94b8cf18c695104ca195334dc75ff054c74eec) + (3 973 193 d/m, fix in [karma-runner/karma#2947](https://github.com/karma-runner/karma/pull/2947)), + * [spdy-transport](https://github.com/spdy-http2/spdy-transport/commit/5375ac33f4a62a4f65bcfc2827447d42a5dbe8b1) + (5 970 727 d/m, fix in [spdy-http2/spdy-transport#53](https://github.com/spdy-http2/spdy-transport/pull/53)). + * And there are a lot more over the ecosystem. + +I filed a PR at +[mysticatea/eslint-plugin-node#110](https://github.com/mysticatea/eslint-plugin-node/pull/110) to +partially fix that (for cases when that lint rule is used), but it is a semver-major change for +linter rules and presets, so it would take significant time for that to reach actual setups. +_It also hasn't been released yet (2018-03-20)._ + +Also, `safer-buffer` discourages the usage of `.allocUnsafe()`, which is often done by a mistake. +It still supports it with an explicit concern barier, by placing it under +`require('safer-buffer/dangereous')`. + +## But isn't throwing bad? + +Not really. It's an error that could be noticed and fixed early, instead of causing havoc later like +unguarded `new Buffer()` calls that end up receiving user input can do. + +This package affects only the files where `var Buffer = require('safer-buffer').Buffer` was done, so +it is really simple to keep track of things and make sure that you don't mix old API usage with that. +Also, CI should hint anything that you might have missed. + +New commits, if tested, won't land new usage of unsafe Buffer API this way. +_Node.js 10.x also deals with that by printing a runtime depecation warning._ + +### Would it affect third-party modules? + +No, unless you explicitly do an awful thing like monkey-patching or overriding the built-in `Buffer`. +Don't do that. + +### But I don't want throwing… + +That is also fine! + +Also, it could be better in some cases when you don't comprehensive enough test coverage. + +In that case — just don't override `Buffer` and use +`var SaferBuffer = require('safer-buffer').Buffer` instead. + +That way, everything using `Buffer` natively would still work, but there would be two drawbacks: + +* `Buffer.from`/`Buffer.alloc` won't be polyfilled — use `SaferBuffer.from` and + `SaferBuffer.alloc` instead. +* You are still open to accidentally using the insecure deprecated API — use a linter to catch that. + +Note that using a linter to catch accidential `Buffer` constructor usage in this case is strongly +recommended. `Buffer` is not overriden in this usecase, so linters won't get confused. + +## «Without footguns»? + +Well, it is still possible to do _some_ things with `Buffer` API, e.g. accessing `.buffer` property +on older versions and duping things from there. You shouldn't do that in your code, probabably. + +The intention is to remove the most significant footguns that affect lots of packages in the +ecosystem, and to do it in the proper way. + +Also, this package doesn't protect against security issues affecting some Node.js versions, so for +usage in your own production code, it is still recommended to update to a Node.js version +[supported by upstream](https://github.com/nodejs/release#release-schedule). diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/dangerous.js b/js/node_modules/fsevents/node_modules/safer-buffer/dangerous.js new file mode 100644 index 0000000..ca41fdc --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/dangerous.js @@ -0,0 +1,58 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer +var safer = require('./safer.js') +var Safer = safer.Buffer + +var dangerous = {} + +var key + +for (key in safer) { + if (!safer.hasOwnProperty(key)) continue + dangerous[key] = safer[key] +} + +var Dangereous = dangerous.Buffer = {} + +// Copy Safer API +for (key in Safer) { + if (!Safer.hasOwnProperty(key)) continue + Dangereous[key] = Safer[key] +} + +// Copy those missing unsafe methods, if they are present +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (Dangereous.hasOwnProperty(key)) continue + Dangereous[key] = Buffer[key] +} + +if (!Dangereous.allocUnsafe) { + Dangereous.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return Buffer(size) + } +} + +if (!Dangereous.allocUnsafeSlow) { + Dangereous.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return buffer.SlowBuffer(size) + } +} + +module.exports = dangerous diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/package.json b/js/node_modules/fsevents/node_modules/safer-buffer/package.json new file mode 100644 index 0000000..49d1acb --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/package.json @@ -0,0 +1,63 @@ +{ + "_args": [ + [ + "safer-buffer@2.1.2", + "/Users/eshanker/Code/fsevents" + ] + ], + "_from": "safer-buffer@2.1.2", + "_id": "safer-buffer@2.1.2", + "_inBundle": true, + "_integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "_location": "/fsevents/safer-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "safer-buffer@2.1.2", + "name": "safer-buffer", + "escapedName": "safer-buffer", + "rawSpec": "2.1.2", + "saveSpec": null, + "fetchSpec": "2.1.2" + }, + "_requiredBy": [ + "/fsevents/iconv-lite" + ], + "_resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "_spec": "2.1.2", + "_where": "/Users/eshanker/Code/fsevents", + "author": { + "name": "Nikita Skovoroda", + "email": "chalkerx@gmail.com", + "url": "https://github.com/ChALkeR" + }, + "bugs": { + "url": "https://github.com/ChALkeR/safer-buffer/issues" + }, + "description": "Modern Buffer API polyfill without footguns", + "devDependencies": { + "standard": "^11.0.1", + "tape": "^4.9.0" + }, + "files": [ + "Porting-Buffer.md", + "Readme.md", + "tests.js", + "dangerous.js", + "safer.js" + ], + "homepage": "https://github.com/ChALkeR/safer-buffer#readme", + "license": "MIT", + "main": "safer.js", + "name": "safer-buffer", + "repository": { + "type": "git", + "url": "git+https://github.com/ChALkeR/safer-buffer.git" + }, + "scripts": { + "browserify-test": "browserify --external tape tests.js > browserify-tests.js && tape browserify-tests.js", + "test": "standard && tape tests.js" + }, + "version": "2.1.2" +} diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/safer.js b/js/node_modules/fsevents/node_modules/safer-buffer/safer.js new file mode 100644 index 0000000..37c7e1a --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/safer.js @@ -0,0 +1,77 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer + +var safer = {} + +var key + +for (key in buffer) { + if (!buffer.hasOwnProperty(key)) continue + if (key === 'SlowBuffer' || key === 'Buffer') continue + safer[key] = buffer[key] +} + +var Safer = safer.Buffer = {} +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (key === 'allocUnsafe' || key === 'allocUnsafeSlow') continue + Safer[key] = Buffer[key] +} + +safer.Buffer.prototype = Buffer.prototype + +if (!Safer.from || Safer.from === Uint8Array.from) { + Safer.from = function (value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('The "value" argument must not be of type number. Received type ' + typeof value) + } + if (value && typeof value.length === 'undefined') { + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type ' + typeof value) + } + return Buffer(value, encodingOrOffset, length) + } +} + +if (!Safer.alloc) { + Safer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + var buf = Buffer(size) + if (!fill || fill.length === 0) { + buf.fill(0) + } else if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + return buf + } +} + +if (!safer.kStringMaxLength) { + try { + safer.kStringMaxLength = process.binding('buffer').kStringMaxLength + } catch (e) { + // we can't determine kStringMaxLength in environments where process.binding + // is unsupported, so let's not set it + } +} + +if (!safer.constants) { + safer.constants = { + MAX_LENGTH: safer.kMaxLength + } + if (safer.kStringMaxLength) { + safer.constants.MAX_STRING_LENGTH = safer.kStringMaxLength + } +} + +module.exports = safer diff --git a/js/node_modules/fsevents/node_modules/safer-buffer/tests.js b/js/node_modules/fsevents/node_modules/safer-buffer/tests.js new file mode 100644 index 0000000..7ed2777 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/safer-buffer/tests.js @@ -0,0 +1,406 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var test = require('tape') + +var buffer = require('buffer') + +var index = require('./') +var safer = require('./safer') +var dangerous = require('./dangerous') + +/* Inheritance tests */ + +test('Default is Safer', function (t) { + t.equal(index, safer) + t.notEqual(safer, dangerous) + t.notEqual(index, dangerous) + t.end() +}) + +test('Is not a function', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'object') + }); + [buffer].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'function') + }) + t.end() +}) + +test('Constructor throws', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer() }) + t.throws(function () { impl.Buffer(0) }) + t.throws(function () { impl.Buffer('a') }) + t.throws(function () { impl.Buffer('a', 'utf-8') }) + t.throws(function () { return new impl.Buffer() }) + t.throws(function () { return new impl.Buffer(0) }) + t.throws(function () { return new impl.Buffer('a') }) + t.throws(function () { return new impl.Buffer('a', 'utf-8') }) + }) + t.end() +}) + +test('Safe methods exist', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.alloc, 'function', 'alloc') + t.equal(typeof impl.Buffer.from, 'function', 'from') + }) + t.end() +}) + +test('Unsafe methods exist only in Dangerous', function (t) { + [index, safer].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'undefined') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'undefined') + }); + [dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'function') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'function') + }) + t.end() +}) + +test('Generic methods/properties are defined and equal', function (t) { + ['poolSize', 'isBuffer', 'concat', 'byteLength'].forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in buffer static methods/properties are inherited', function (t) { + Object.keys(buffer).forEach(function (method) { + if (method === 'SlowBuffer' || method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], buffer[method], method) + t.notEqual(typeof impl[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in Buffer static methods/properties are inherited', function (t) { + Object.keys(buffer.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('.prototype property of Buffer is inherited', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.prototype, buffer.Buffer.prototype, 'prototype') + t.notEqual(typeof impl.Buffer.prototype, 'undefined', 'prototype') + }) + t.end() +}) + +test('All Safer methods are present in Dangerous', function (t) { + Object.keys(safer).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], safer[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(safer.Buffer).forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], safer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Safe methods from Dangerous methods are present in Safer', function (t) { + Object.keys(dangerous).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], dangerous[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(dangerous.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], dangerous.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +/* Behaviour tests */ + +test('Methods return Buffers', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 'a'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10, 'x'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(9, 'ab'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(''))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string', 'utf-8'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([0, 42, 3]))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(new Uint8Array([0, 42, 3])))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([]))) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](0))) + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](10))) + }) + t.end() +}) + +test('Constructor is buffer.Buffer', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 'a').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10, 'x').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(9, 'ab').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string', 'utf-8').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').constructor, buffer.Buffer) + t.equal(impl.Buffer.from([0, 42, 3]).constructor, buffer.Buffer) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).constructor, buffer.Buffer) + t.equal(impl.Buffer.from([]).constructor, buffer.Buffer) + }); + [0, 10, 100].forEach(function (arg) { + t.equal(dangerous.Buffer.allocUnsafe(arg).constructor, buffer.Buffer) + t.equal(dangerous.Buffer.allocUnsafeSlow(arg).constructor, buffer.SlowBuffer(0).constructor) + }) + t.end() +}) + +test('Invalid calls throw', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer.from(0) }) + t.throws(function () { impl.Buffer.from(10) }) + t.throws(function () { impl.Buffer.from(10, 'utf-8') }) + t.throws(function () { impl.Buffer.from('string', 'invalid encoding') }) + t.throws(function () { impl.Buffer.from(-10) }) + t.throws(function () { impl.Buffer.from(1e90) }) + t.throws(function () { impl.Buffer.from(Infinity) }) + t.throws(function () { impl.Buffer.from(-Infinity) }) + t.throws(function () { impl.Buffer.from(NaN) }) + t.throws(function () { impl.Buffer.from(null) }) + t.throws(function () { impl.Buffer.from(undefined) }) + t.throws(function () { impl.Buffer.from() }) + t.throws(function () { impl.Buffer.from({}) }) + t.throws(function () { impl.Buffer.alloc('') }) + t.throws(function () { impl.Buffer.alloc('string') }) + t.throws(function () { impl.Buffer.alloc('string', 'utf-8') }) + t.throws(function () { impl.Buffer.alloc('b25ldHdvdGhyZWU=', 'base64') }) + t.throws(function () { impl.Buffer.alloc(-10) }) + t.throws(function () { impl.Buffer.alloc(1e90) }) + t.throws(function () { impl.Buffer.alloc(2 * (1 << 30)) }) + t.throws(function () { impl.Buffer.alloc(Infinity) }) + t.throws(function () { impl.Buffer.alloc(-Infinity) }) + t.throws(function () { impl.Buffer.alloc(null) }) + t.throws(function () { impl.Buffer.alloc(undefined) }) + t.throws(function () { impl.Buffer.alloc() }) + t.throws(function () { impl.Buffer.alloc([]) }) + t.throws(function () { impl.Buffer.alloc([0, 42, 3]) }) + t.throws(function () { impl.Buffer.alloc({}) }) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.throws(function () { dangerous.Buffer[method]('') }) + t.throws(function () { dangerous.Buffer[method]('string') }) + t.throws(function () { dangerous.Buffer[method]('string', 'utf-8') }) + t.throws(function () { dangerous.Buffer[method](2 * (1 << 30)) }) + t.throws(function () { dangerous.Buffer[method](Infinity) }) + if (dangerous.Buffer[method] === buffer.Buffer.allocUnsafe) { + t.skip('Skipping, older impl of allocUnsafe coerced negative sizes to 0') + } else { + t.throws(function () { dangerous.Buffer[method](-10) }) + t.throws(function () { dangerous.Buffer[method](-1e90) }) + t.throws(function () { dangerous.Buffer[method](-Infinity) }) + } + t.throws(function () { dangerous.Buffer[method](null) }) + t.throws(function () { dangerous.Buffer[method](undefined) }) + t.throws(function () { dangerous.Buffer[method]() }) + t.throws(function () { dangerous.Buffer[method]([]) }) + t.throws(function () { dangerous.Buffer[method]([0, 42, 3]) }) + t.throws(function () { dangerous.Buffer[method]({}) }) + }) + t.end() +}) + +test('Buffers have appropriate lengths', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).length, 0) + t.equal(impl.Buffer.alloc(10).length, 10) + t.equal(impl.Buffer.from('').length, 0) + t.equal(impl.Buffer.from('string').length, 6) + t.equal(impl.Buffer.from('string', 'utf-8').length, 6) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').length, 11) + t.equal(impl.Buffer.from([0, 42, 3]).length, 3) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).length, 3) + t.equal(impl.Buffer.from([]).length, 0) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.equal(dangerous.Buffer[method](0).length, 0) + t.equal(dangerous.Buffer[method](10).length, 10) + }) + t.end() +}) + +test('Buffers have appropriate lengths (2)', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true; + [ safer.Buffer.alloc, + dangerous.Buffer.allocUnsafe, + dangerous.Buffer.allocUnsafeSlow + ].forEach(function (method) { + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 1e5) + var buf = method(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + } + }) + t.ok(ok) + t.end() +}) + +test('.alloc(size) is zero-filled and has correct length', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = index.Buffer.alloc(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.allocUnsafe / .allocUnsafeSlow are fillable and have correct lengths', function (t) { + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = dangerous.Buffer[method](length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + buf.fill(0, 0, length) + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1, 0, length) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok, method) + }) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.deepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 97)) + t.notDeepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 98)) + + var tmp = new buffer.Buffer(2) + tmp.fill('ok') + if (tmp[1] === tmp[0]) { + // Outdated Node.js + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('ooooo')) + } else { + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('okoko')) + } + t.notDeepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('kokok')) + + t.end() +}) + +test('safer.Buffer.from returns results same as Buffer constructor', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), new buffer.Buffer('')) + t.deepEqual(impl.Buffer.from('string'), new buffer.Buffer('string')) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), new buffer.Buffer('string', 'utf-8')) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), new buffer.Buffer('b25ldHdvdGhyZWU=', 'base64')) + t.deepEqual(impl.Buffer.from([0, 42, 3]), new buffer.Buffer([0, 42, 3])) + t.deepEqual(impl.Buffer.from(new Uint8Array([0, 42, 3])), new buffer.Buffer(new Uint8Array([0, 42, 3]))) + t.deepEqual(impl.Buffer.from([]), new buffer.Buffer([])) + }) + t.end() +}) + +test('safer.Buffer.from returns consistent results', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from([]), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from(new Uint8Array([])), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), impl.Buffer.from('string')) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from([115, 116, 114, 105, 110, 103])) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from(impl.Buffer.from('string'))) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), impl.Buffer.from('onetwothree')) + t.notDeepEqual(impl.Buffer.from('b25ldHdvdGhyZWU='), impl.Buffer.from('onetwothree')) + }) + t.end() +}) diff --git a/js/node_modules/fsevents/node_modules/sax/LICENSE b/js/node_modules/fsevents/node_modules/sax/LICENSE new file mode 100644 index 0000000..ccffa08 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/sax/LICENSE @@ -0,0 +1,41 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +==== + +`String.fromCodePoint` by Mathias Bynens used according to terms of MIT +License, as follows: + + Copyright Mathias Bynens + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/js/node_modules/fsevents/node_modules/sax/README.md b/js/node_modules/fsevents/node_modules/sax/README.md new file mode 100644 index 0000000..afcd3f3 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/sax/README.md @@ -0,0 +1,225 @@ +# sax js + +A sax-style parser for XML and HTML. + +Designed with [node](http://nodejs.org/) in mind, but should work fine in +the browser or other CommonJS implementations. + +## What This Is + +* A very simple tool to parse through an XML string. +* A stepping stone to a streaming HTML parser. +* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML + docs. + +## What This Is (probably) Not + +* An HTML Parser - That's a fine goal, but this isn't it. It's just + XML. +* A DOM Builder - You can use it to build an object model out of XML, + but it doesn't do that out of the box. +* XSLT - No DOM = no querying. +* 100% Compliant with (some other SAX implementation) - Most SAX + implementations are in Java and do a lot more than this does. +* An XML Validator - It does a little validation when in strict mode, but + not much. +* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic + masochism. +* A DTD-aware Thing - Fetching DTDs is a much bigger job. + +## Regarding `Hello, world!').close(); + +// stream usage +// takes the same options as the parser +var saxStream = require("sax").createStream(strict, options) +saxStream.on("error", function (e) { + // unhandled errors will throw, since this is a proper node + // event emitter. + console.error("error!", e) + // clear the error + this._parser.error = null + this._parser.resume() +}) +saxStream.on("opentag", function (node) { + // same object as above +}) +// pipe is supported, and it's readable/writable +// same chunks coming in also go out. +fs.createReadStream("file.xml") + .pipe(saxStream) + .pipe(fs.createWriteStream("file-copy.xml")) +``` + + +## Arguments + +Pass the following arguments to the parser function. All are optional. + +`strict` - Boolean. Whether or not to be a jerk. Default: `false`. + +`opt` - Object bag of settings regarding string formatting. All default to `false`. + +Settings supported: + +* `trim` - Boolean. Whether or not to trim text and comment nodes. +* `normalize` - Boolean. If true, then turn any whitespace into a single + space. +* `lowercase` - Boolean. If true, then lowercase tag names and attribute names + in loose mode, rather than uppercasing them. +* `xmlns` - Boolean. If true, then namespaces are supported. +* `position` - Boolean. If false, then don't track line/col/position. +* `strictEntities` - Boolean. If true, only parse [predefined XML + entities](http://www.w3.org/TR/REC-xml/#sec-predefined-ent) + (`&`, `'`, `>`, `<`, and `"`) + +## Methods + +`write` - Write bytes onto the stream. You don't have to do this all at +once. You can keep writing as much as you want. + +`close` - Close the stream. Once closed, no more data may be written until +it is done processing the buffer, which is signaled by the `end` event. + +`resume` - To gracefully handle errors, assign a listener to the `error` +event. Then, when the error is taken care of, you can call `resume` to +continue parsing. Otherwise, the parser will not continue while in an error +state. + +## Members + +At all times, the parser object will have the following members: + +`line`, `column`, `position` - Indications of the position in the XML +document where the parser currently is looking. + +`startTagPosition` - Indicates the position where the current tag starts. + +`closed` - Boolean indicating whether or not the parser can be written to. +If it's `true`, then wait for the `ready` event to write again. + +`strict` - Boolean indicating whether or not the parser is a jerk. + +`opt` - Any options passed into the constructor. + +`tag` - The current tag being dealt with. + +And a bunch of other stuff that you probably shouldn't touch. + +## Events + +All events emit with a single argument. To listen to an event, assign a +function to `on`. Functions get executed in the this-context of +the parser object. The list of supported events are also in the exported +`EVENTS` array. + +When using the stream interface, assign handlers using the EventEmitter +`on` function in the normal fashion. + +`error` - Indication that something bad happened. The error will be hanging +out on `parser.error`, and must be deleted before parsing can continue. By +listening to this event, you can keep an eye on that kind of stuff. Note: +this happens *much* more in strict mode. Argument: instance of `Error`. + +`text` - Text node. Argument: string of text. + +`doctype` - The ``. Argument: +object with `name` and `body` members. Attributes are not parsed, as +processing instructions have implementation dependent semantics. + +`sgmldeclaration` - Random SGML declarations. Stuff like `` +would trigger this kind of event. This is a weird thing to support, so it +might go away at some point. SAX isn't intended to be used to parse SGML, +after all. + +`opentagstart` - Emitted immediately when the tag name is available, +but before any attributes are encountered. Argument: object with a +`name` field and an empty `attributes` set. Note that this is the +same object that will later be emitted in the `opentag` event. + +`opentag` - An opening tag. Argument: object with `name` and `attributes`. +In non-strict mode, tag names are uppercased, unless the `lowercase` +option is set. If the `xmlns` option is set, then it will contain +namespace binding information on the `ns` member, and will have a +`local`, `prefix`, and `uri` member. + +`closetag` - A closing tag. In loose mode, tags are auto-closed if their +parent closes. In strict mode, well-formedness is enforced. Note that +self-closing tags will have `closeTag` emitted immediately after `openTag`. +Argument: tag name. + +`attribute` - An attribute node. Argument: object with `name` and `value`. +In non-strict mode, attribute names are uppercased, unless the `lowercase` +option is set. If the `xmlns` option is set, it will also contains namespace +information. + +`comment` - A comment node. Argument: the string of the comment. + +`opencdata` - The opening tag of a ``) of a `` tags trigger a `"script"` +event, and their contents are not checked for special xml characters. +If you pass `noscript: true`, then this behavior is suppressed. + +## Reporting Problems + +It's best to write a failing test if you find an issue. I will always +accept pull requests with failing tests if they demonstrate intended +behavior, but it is very hard to figure out what issue you're describing +without a test. Writing a test is also the best way for you yourself +to figure out if you really understand the issue you think you have with +sax-js. diff --git a/js/node_modules/fsevents/node_modules/sax/lib/sax.js b/js/node_modules/fsevents/node_modules/sax/lib/sax.js new file mode 100644 index 0000000..795d607 --- /dev/null +++ b/js/node_modules/fsevents/node_modules/sax/lib/sax.js @@ -0,0 +1,1565 @@ +;(function (sax) { // wrapper for non-node envs + sax.parser = function (strict, opt) { return new SAXParser(strict, opt) } + sax.SAXParser = SAXParser + sax.SAXStream = SAXStream + sax.createStream = createStream + + // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns. + // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)), + // since that's the earliest that a buffer overrun could occur. This way, checks are + // as rare as required, but as often as necessary to ensure never crossing this bound. + // Furthermore, buffers are only tested at most once per write(), so passing a very + // large string into write() might have undesirable effects, but this is manageable by + // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme + // edge case, result in creating at most one complete copy of the string passed in. + // Set to Infinity to have unlimited buffers. + sax.MAX_BUFFER_LENGTH = 64 * 1024 + + var buffers = [ + 'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype', + 'procInstName', 'procInstBody', 'entity', 'attribName', + 'attribValue', 'cdata', 'script' + ] + + sax.EVENTS = [ + 'text', + 'processinginstruction', + 'sgmldeclaration', + 'doctype', + 'comment', + 'opentagstart', + 'attribute', + 'opentag', + 'closetag', + 'opencdata', + 'cdata', + 'closecdata', + 'error', + 'end', + 'ready', + 'script', + 'opennamespace', + 'closenamespace' + ] + + function SAXParser (strict, opt) { + if (!(this instanceof SAXParser)) { + return new SAXParser(strict, opt) + } + + var parser = this + clearBuffers(parser) + parser.q = parser.c = '' + parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH + parser.opt = opt || {} + parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags + parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase' + parser.tags = [] + parser.closed = parser.closedRoot = parser.sawRoot = false + parser.tag = parser.error = null + parser.strict = !!strict + parser.noscript = !!(strict || parser.opt.noscript) + parser.state = S.BEGIN + parser.strictEntities = parser.opt.strictEntities + parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES) + parser.attribList = [] + + // namespaces form a prototype chain. + // it always points at the current tag, + // which protos to its parent tag. + if (parser.opt.xmlns) { + parser.ns = Object.create(rootNS) + } + + // mostly just for error reporting + parser.trackPosition = parser.opt.position !== false + if (parser.trackPosition) { + parser.position = parser.line = parser.column = 0 + } + emit(parser, 'onready') + } + + if (!Object.create) { + Object.create = function (o) { + function F () {} + F.prototype = o + var newf = new F() + return newf + } + } + + if (!Object.keys) { + Object.keys = function (o) { + var a = [] + for (var i in o) if (o.hasOwnProperty(i)) a.push(i) + return a + } + } + + function checkBufferLength (parser) { + var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10) + var maxActual = 0 + for (var i = 0, l = buffers.length; i < l; i++) { + var len = parser[buffers[i]].length + if (len > maxAllowed) { + // Text/cdata nodes can get big, and since they're buffered, + // we can get here under normal conditions. + // Avoid issues by emitting the text node now, + // so at least it won't get any bigger. + switch (buffers[i]) { + case 'textNode': + closeText(parser) + break + + case 'cdata': + emitNode(parser, 'oncdata', parser.cdata) + parser.cdata = '' + break + + case 'script': + emitNode(parser, 'onscript', parser.script) + parser.script = '' + break + + default: + error(parser, 'Max buffer length exceeded: ' + buffers[i]) + } + } + maxActual = Math.max(maxActual, len) + } + // schedule the next check for the earliest possible buffer overrun. + var m = sax.MAX_BUFFER_LENGTH - maxActual + parser.bufferCheckPosition = m + parser.position + } + + function clearBuffers (parser) { + for (var i = 0, l = buffers.length; i < l; i++) { + parser[buffers[i]] = '' + } + } + + function flushBuffers (parser) { + closeText(parser) + if (parser.cdata !== '') { + emitNode(parser, 'oncdata', parser.cdata) + parser.cdata = '' + } + if (parser.script !== '') { + emitNode(parser, 'onscript', parser.script) + parser.script = '' + } + } + + SAXParser.prototype = { + end: function () { end(this) }, + write: write, + resume: function () { this.error = null; return this }, + close: function () { return this.write(null) }, + flush: function () { flushBuffers(this) } + } + + var Stream + try { + Stream = require('stream').Stream + } catch (ex) { + Stream = function () {} + } + + var streamWraps = sax.EVENTS.filter(function (ev) { + return ev !== 'error' && ev !== 'end' + }) + + function createStream (strict, opt) { + return new SAXStream(strict, opt) + } + + function SAXStream (strict, opt) { + if (!(this instanceof SAXStream)) { + return new SAXStream(strict, opt) + } + + Stream.apply(this) + + this._parser = new SAXParser(strict, opt) + this.writable = true + this.readable = true + + var me = this + + this._parser.onend = function () { + me.emit('end') + } + + this._parser.onerror = function (er) { + me.emit('error', er) + + // if didn't throw, then means error was handled. + // go ahead and clear error, so we can write again. + me._parser.error = null + } + + this._decoder = null + + streamWraps.forEach(function (ev) { + Object.defineProperty(me, 'on' + ev, { + get: function () { + return me._parser['on' + ev] + }, + set: function (h) { + if (!h) { + me.removeAllListeners(ev) + me._parser['on' + ev] = h + return h + } + me.on(ev, h) + }, + enumerable: true, + configurable: false + }) + }) + } + + SAXStream.prototype = Object.create(Stream.prototype, { + constructor: { + value: SAXStream + } + }) + + SAXStream.prototype.write = function (data) { + if (typeof Buffer === 'function' && + typeof Buffer.isBuffer === 'function' && + Buffer.isBuffer(data)) { + if (!this._decoder) { + var SD = require('string_decoder').StringDecoder + this._decoder = new SD('utf8') + } + data = this._decoder.write(data) + } + + this._parser.write(data.toString()) + this.emit('data', data) + return true + } + + SAXStream.prototype.end = function (chunk) { + if (chunk && chunk.length) { + this.write(chunk) + } + this._parser.end() + return true + } + + SAXStream.prototype.on = function (ev, handler) { + var me = this + if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) { + me._parser['on' + ev] = function () { + var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments) + args.splice(0, 0, ev) + me.emit.apply(me, args) + } + } + + return Stream.prototype.on.call(me, ev, handler) + } + + // this really needs to be replaced with character classes. + // XML allows all manner of ridiculous numbers and digits. + var CDATA = '[CDATA[' + var DOCTYPE = 'DOCTYPE' + var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace' + var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/' + var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE } + + // http://www.w3.org/TR/REC-xml/#NT-NameStartChar + // This implementation works on strings, a single character at a time + // as such, it cannot ever support astral-plane characters (10000-EFFFF) + // without a significant breaking change to either this parser, or the + // JavaScript language. Implementation of an emoji-capable xml parser + // is left as an exercise for the reader. + var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ + + var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/ + + var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ + var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/ + + function isWhitespace (c) { + return c === ' ' || c === '\n' || c === '\r' || c === '\t' + } + + function isQuote (c) { + return c === '"' || c === '\'' + } + + function isAttribEnd (c) { + return c === '>' || isWhitespace(c) + } + + function isMatch (regex, c) { + return regex.test(c) + } + + function notMatch (regex, c) { + return !isMatch(regex, c) + } + + var S = 0 + sax.STATE = { + BEGIN: S++, // leading byte order mark or whitespace + BEGIN_WHITESPACE: S++, // leading whitespace + TEXT: S++, // general stuff + TEXT_ENTITY: S++, // & and such. + OPEN_WAKA: S++, // < + SGML_DECL: S++, // + SCRIPT: S++, // + +-------------------------------------------------------------------------------- + + + + + +## Table of Contents + +- [Examples](#examples) + - [Consuming a source map](#consuming-a-source-map) + - [Generating a source map](#generating-a-source-map) + - [With SourceNode (high level API)](#with-sourcenode-high-level-api) + - [With SourceMapGenerator (low level API)](#with-sourcemapgenerator-low-level-api) +- [API](#api) + - [SourceMapConsumer](#sourcemapconsumer) + - [new SourceMapConsumer(rawSourceMap)](#new-sourcemapconsumerrawsourcemap) + - [SourceMapConsumer.prototype.computeColumnSpans()](#sourcemapconsumerprototypecomputecolumnspans) + - [SourceMapConsumer.prototype.originalPositionFor(generatedPosition)](#sourcemapconsumerprototypeoriginalpositionforgeneratedposition) + - [SourceMapConsumer.prototype.generatedPositionFor(originalPosition)](#sourcemapconsumerprototypegeneratedpositionfororiginalposition) + - [SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition)](#sourcemapconsumerprototypeallgeneratedpositionsfororiginalposition) + - [SourceMapConsumer.prototype.hasContentsOfAllSources()](#sourcemapconsumerprototypehascontentsofallsources) + - [SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing])](#sourcemapconsumerprototypesourcecontentforsource-returnnullonmissing) + - [SourceMapConsumer.prototype.eachMapping(callback, context, order)](#sourcemapconsumerprototypeeachmappingcallback-context-order) + - [SourceMapGenerator](#sourcemapgenerator) + - [new SourceMapGenerator([startOfSourceMap])](#new-sourcemapgeneratorstartofsourcemap) + - [SourceMapGenerator.fromSourceMap(sourceMapConsumer)](#sourcemapgeneratorfromsourcemapsourcemapconsumer) + - [SourceMapGenerator.prototype.addMapping(mapping)](#sourcemapgeneratorprototypeaddmappingmapping) + - [SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)](#sourcemapgeneratorprototypesetsourcecontentsourcefile-sourcecontent) + - [SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]])](#sourcemapgeneratorprototypeapplysourcemapsourcemapconsumer-sourcefile-sourcemappath) + - [SourceMapGenerator.prototype.toString()](#sourcemapgeneratorprototypetostring) + - [SourceNode](#sourcenode) + - [new SourceNode([line, column, source[, chunk[, name]]])](#new-sourcenodeline-column-source-chunk-name) + - [SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath])](#sourcenodefromstringwithsourcemapcode-sourcemapconsumer-relativepath) + - [SourceNode.prototype.add(chunk)](#sourcenodeprototypeaddchunk) + - [SourceNode.prototype.prepend(chunk)](#sourcenodeprototypeprependchunk) + - [SourceNode.prototype.setSourceContent(sourceFile, sourceContent)](#sourcenodeprototypesetsourcecontentsourcefile-sourcecontent) + - [SourceNode.prototype.walk(fn)](#sourcenodeprototypewalkfn) + - [SourceNode.prototype.walkSourceContents(fn)](#sourcenodeprototypewalksourcecontentsfn) + - [SourceNode.prototype.join(sep)](#sourcenodeprototypejoinsep) + - [SourceNode.prototype.replaceRight(pattern, replacement)](#sourcenodeprototypereplacerightpattern-replacement) + - [SourceNode.prototype.toString()](#sourcenodeprototypetostring) + - [SourceNode.prototype.toStringWithSourceMap([startOfSourceMap])](#sourcenodeprototypetostringwithsourcemapstartofsourcemap) + + + +## Examples + +### Consuming a source map + +```js +var rawSourceMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: 'http://example.com/www/js/', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' +}; + +var smc = new SourceMapConsumer(rawSourceMap); + +console.log(smc.sources); +// [ 'http://example.com/www/js/one.js', +// 'http://example.com/www/js/two.js' ] + +console.log(smc.originalPositionFor({ + line: 2, + column: 28 +})); +// { source: 'http://example.com/www/js/two.js', +// line: 2, +// column: 10, +// name: 'n' } + +console.log(smc.generatedPositionFor({ + source: 'http://example.com/www/js/two.js', + line: 2, + column: 10 +})); +// { line: 2, column: 28 } + +smc.eachMapping(function (m) { + // ... +}); +``` + +### Generating a source map + +In depth guide: +[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) + +#### With SourceNode (high level API) + +```js +function compile(ast) { + switch (ast.type) { + case 'BinaryExpression': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + [compile(ast.left), " + ", compile(ast.right)] + ); + case 'Literal': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + String(ast.value) + ); + // ... + default: + throw new Error("Bad AST"); + } +} + +var ast = parse("40 + 2", "add.js"); +console.log(compile(ast).toStringWithSourceMap({ + file: 'add.js' +})); +// { code: '40 + 2', +// map: [object SourceMapGenerator] } +``` + +#### With SourceMapGenerator (low level API) + +```js +var map = new SourceMapGenerator({ + file: "source-mapped.js" +}); + +map.addMapping({ + generated: { + line: 10, + column: 35 + }, + source: "foo.js", + original: { + line: 33, + column: 2 + }, + name: "christopher" +}); + +console.log(map.toString()); +// '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' +``` + +## API + +Get a reference to the module: + +```js +// Node.js +var sourceMap = require('source-map'); + +// Browser builds +var sourceMap = window.sourceMap; + +// Inside Firefox +const sourceMap = require("devtools/toolkit/sourcemap/source-map.js"); +``` + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: Optional. The generated filename this source map is associated with. + +```js +var consumer = new sourceMap.SourceMapConsumer(rawSourceMapJsonData); +``` + +#### SourceMapConsumer.prototype.computeColumnSpans() + +Compute the last column for each generated mapping. The last column is +inclusive. + +```js +// Before: +consumer.allGeneratedPositionsFor({ line: 2, source: "foo.coffee" }) +// [ { line: 2, +// column: 1 }, +// { line: 2, +// column: 10 }, +// { line: 2, +// column: 20 } ] + +consumer.computeColumnSpans(); + +// After: +consumer.allGeneratedPositionsFor({ line: 2, source: "foo.coffee" }) +// [ { line: 2, +// column: 1, +// lastColumn: 9 }, +// { line: 2, +// column: 10, +// lastColumn: 19 }, +// { line: 2, +// column: 20, +// lastColumn: Infinity } ] + +``` + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +* `bias`: Either `SourceMapConsumer.GREATEST_LOWER_BOUND` or + `SourceMapConsumer.LEAST_UPPER_BOUND`. Specifies whether to return the closest + element that is smaller than or greater than the one we are searching for, + respectively, if the exact element cannot be found. Defaults to + `SourceMapConsumer.GREATEST_LOWER_BOUND`. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +```js +consumer.originalPositionFor({ line: 2, column: 10 }) +// { source: 'foo.coffee', +// line: 2, +// column: 2, +// name: null } + +consumer.originalPositionFor({ line: 99999999999999999, column: 999999999999999 }) +// { source: null, +// line: null, +// column: null, +// name: null } +``` + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +```js +consumer.generatedPositionFor({ source: "example.js", line: 2, column: 10 }) +// { line: 1, +// column: 56 } +``` + +#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition) + +Returns all generated line and column information for the original source, line, +and column provided. If no column is provided, returns all mappings +corresponding to a either the line we are searching for or the next closest line +that has any mappings. Otherwise, returns all mappings corresponding to the +given line and either the column we are searching for or the next closest column +that has any offsets. + +The only argument is an object with the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: Optional. The column number in the original source. + +and an array of objects is returned, each with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +```js +consumer.allGeneratedpositionsfor({ line: 2, source: "foo.coffee" }) +// [ { line: 2, +// column: 1 }, +// { line: 2, +// column: 10 }, +// { line: 2, +// column: 20 } ] +``` + +#### SourceMapConsumer.prototype.hasContentsOfAllSources() + +Return true if we have the embedded source content for every source listed in +the source map, false otherwise. + +In other words, if this method returns `true`, then +`consumer.sourceContentFor(s)` will succeed for every source `s` in +`consumer.sources`. + +```js +// ... +if (consumer.hasContentsOfAllSources()) { + consumerReadyCallback(consumer); +} else { + fetchSources(consumer, consumerReadyCallback); +} +// ... +``` + +#### SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing]) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +If the source content for the given source is not found, then an error is +thrown. Optionally, pass `true` as the second param to have `null` returned +instead. + +```js +consumer.sources +// [ "my-cool-lib.clj" ] + +consumer.sourceContentFor("my-cool-lib.clj") +// "..." + +consumer.sourceContentFor("this is not in the source map"); +// Error: "this is not in the source map" is not in the source map + +consumer.sourceContentFor("this is not in the source map", true); +// null +``` + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. Mappings have the + form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, + name }` + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +```js +consumer.eachMapping(function (m) { console.log(m); }) +// ... +// { source: 'illmatic.js', +// generatedLine: 1, +// generatedColumn: 0, +// originalLine: 1, +// originalColumn: 0, +// name: null } +// { source: 'illmatic.js', +// generatedLine: 2, +// generatedColumn: 0, +// originalLine: 2, +// originalColumn: 0, +// name: null } +// ... +``` +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator([startOfSourceMap]) + +You may pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: A root for all relative URLs in this source map. + +* `skipValidation`: Optional. When `true`, disables validation of mappings as + they are added. This can improve performance but should be used with + discretion, as a last resort. Even then, one should avoid using this flag when + running tests, if possible. + +```js +var generator = new sourceMap.SourceMapGenerator({ + file: "my-generated-javascript-file.js", + sourceRoot: "http://example.com/app/js/" +}); +``` + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new `SourceMapGenerator` from an existing `SourceMapConsumer` instance. + +* `sourceMapConsumer` The SourceMap. + +```js +var generator = sourceMap.SourceMapGenerator.fromSourceMap(consumer); +``` + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +```js +generator.addMapping({ + source: "module-one.scm", + original: { line: 128, column: 0 }, + generated: { line: 3, column: 456 } +}) +``` + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +```js +generator.setSourceContent("module-one.scm", + fs.readFileSync("path/to/module-one.scm")) +``` + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimum of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used, if it exists. + Otherwise an error will be thrown. + +* `sourceMapPath`: Optional. The dirname of the path to the SourceMap + to be applied. If relative, it is relative to the SourceMap. + + This parameter is needed when the two SourceMaps aren't in the same + directory, and the SourceMap to be applied contains relative source + paths. If so, those relative source paths need to be rewritten + relative to the SourceMap. + + If omitted, it is assumed that both SourceMaps are in the same directory, + thus not needing any rewriting. (Supplying `'.'` has the same effect.) + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +```js +generator.toString() +// '{"version":3,"sources":["module-one.scm"],"names":[],"mappings":"...snip...","file":"my-generated-javascript-file.js","sourceRoot":"http://example.com/app/js/"}' +``` + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode([line, column, source[, chunk[, name]]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename; null if no filename is provided. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +```js +var node = new SourceNode(1, 2, "a.cpp", [ + new SourceNode(3, 4, "b.cpp", "extern int status;\n"), + new SourceNode(5, 6, "c.cpp", "std::string* make_string(size_t n);\n"), + new SourceNode(7, 8, "d.cpp", "int main(int argc, char** argv) {}\n"), +]); +``` + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath]) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +* `relativePath` The optional path that relative sources in `sourceMapConsumer` + should be relative to. + +```js +var consumer = new SourceMapConsumer(fs.readFileSync("path/to/my-file.js.map", "utf8")); +var node = SourceNode.fromStringWithSourceMap(fs.readFileSync("path/to/my-file.js"), + consumer); +``` + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +```js +node.add(" + "); +node.add(otherNode); +node.add([leftHandOperandNode, " + ", rightHandOperandNode]); +``` + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +```js +node.prepend("/** Build Id: f783haef86324gf **/\n\n"); +``` + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +```js +node.setSourceContent("module-one.scm", + fs.readFileSync("path/to/module-one.scm")) +``` + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +```js +var node = new SourceNode(1, 2, "a.js", [ + new SourceNode(3, 4, "b.js", "uno"), + "dos", + [ + "tres", + new SourceNode(5, 6, "c.js", "quatro") + ] +]); + +node.walk(function (code, loc) { console.log("WALK:", code, loc); }) +// WALK: uno { source: 'b.js', line: 3, column: 4, name: null } +// WALK: dos { source: 'a.js', line: 1, column: 2, name: null } +// WALK: tres { source: 'a.js', line: 1, column: 2, name: null } +// WALK: quatro { source: 'c.js', line: 5, column: 6, name: null } +``` + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +```js +var a = new SourceNode(1, 2, "a.js", "generated from a"); +a.setSourceContent("a.js", "original a"); +var b = new SourceNode(1, 2, "b.js", "generated from b"); +b.setSourceContent("b.js", "original b"); +var c = new SourceNode(1, 2, "c.js", "generated from c"); +c.setSourceContent("c.js", "original c"); + +var node = new SourceNode(null, null, null, [a, b, c]); +node.walkSourceContents(function (source, contents) { console.log("WALK:", source, ":", contents); }) +// WALK: a.js : original a +// WALK: b.js : original b +// WALK: c.js : original c +``` + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +```js +var lhs = new SourceNode(1, 2, "a.rs", "my_copy"); +var operand = new SourceNode(3, 4, "a.rs", "="); +var rhs = new SourceNode(5, 6, "a.rs", "orig.clone()"); + +var node = new SourceNode(null, null, null, [ lhs, operand, rhs ]); +var joinedNode = node.join(" "); +``` + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming white space from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +```js +// Trim trailing white space. +node.replaceRight(/\s*$/, ""); +``` + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +```js +var node = new SourceNode(1, 2, "a.js", [ + new SourceNode(3, 4, "b.js", "uno"), + "dos", + [ + "tres", + new SourceNode(5, 6, "c.js", "quatro") + ] +]); + +node.toString() +// 'unodostresquatro' +``` + +#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap]) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +```js +var node = new SourceNode(1, 2, "a.js", [ + new SourceNode(3, 4, "b.js", "uno"), + "dos", + [ + "tres", + new SourceNode(5, 6, "c.js", "quatro") + ] +]); + +node.toStringWithSourceMap({ file: "my-output-file.js" }) +// { code: 'unodostresquatro', +// map: [object SourceMapGenerator] } +``` diff --git a/js/node_modules/source-map/dist/source-map.debug.js b/js/node_modules/source-map/dist/source-map.debug.js new file mode 100644 index 0000000..b5ab638 --- /dev/null +++ b/js/node_modules/source-map/dist/source-map.debug.js @@ -0,0 +1,3091 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["sourceMap"] = factory(); + else + root["sourceMap"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + /* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ + exports.SourceMapGenerator = __webpack_require__(1).SourceMapGenerator; + exports.SourceMapConsumer = __webpack_require__(7).SourceMapConsumer; + exports.SourceNode = __webpack_require__(10).SourceNode; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var base64VLQ = __webpack_require__(2); + var util = __webpack_require__(4); + var ArraySet = __webpack_require__(5).ArraySet; + var MappingList = __webpack_require__(6).MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null) { + source = String(source); + if (!this._sources.has(source)) { + this._sources.add(source); + } + } + + if (name != null) { + name = String(name); + if (!this._names.has(name)) { + this._names.add(name); + } + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = Object.create(null); + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + // When aOriginal is truthy but has empty values for .line and .column, + // it is most likely a programmer error. In this case we throw a very + // specific error message to try to guide them the right way. + // For example: https://github.com/Polymer/polymer-bundler/pull/519 + if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { + throw new Error( + 'original.line and original.column are not numbers -- you probably meant to omit ' + + 'the original mapping entirely and only map the generated position. If so, pass ' + + 'null for the original mapping instead of an object with empty or null values.' + ); + } + + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var next; + var mapping; + var nameIdx; + var sourceIdx; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + next = '' + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + next += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; + } + next += ','; + } + } + + next += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + next += base64VLQ.encode(sourceIdx - previousSource); + previousSource = sourceIdx; + + // lines are stored 0-based in SourceMap spec version 3 + next += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + next += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + next += base64VLQ.encode(nameIdx - previousName); + previousName = nameIdx; + } + } + + result += next; + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + var base64 = __webpack_require__(3); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; + }; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); + }; + + /** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ + exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consecutive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); + }; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; + } + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; + } + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); + } + exports.relative = relative; + + var supportsNullProto = (function () { + var obj = Object.create(null); + return !('__proto__' in obj); + }()); + + function identity (s) { + return s; + } + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + if (isProtoString(aStr)) { + return '$' + aStr; + } + + return aStr; + } + exports.toSetString = supportsNullProto ? identity : toSetString; + + function fromSetString(aStr) { + if (isProtoString(aStr)) { + return aStr.slice(1); + } + + return aStr; + } + exports.fromSetString = supportsNullProto ? identity : fromSetString; + + function isProtoString(s) { + if (!s) { + return false; + } + + var length = s.length; + + if (length < 9 /* "__proto__".length */) { + return false; + } + + if (s.charCodeAt(length - 1) !== 95 /* '_' */ || + s.charCodeAt(length - 2) !== 95 /* '_' */ || + s.charCodeAt(length - 3) !== 111 /* 'o' */ || + s.charCodeAt(length - 4) !== 116 /* 't' */ || + s.charCodeAt(length - 5) !== 111 /* 'o' */ || + s.charCodeAt(length - 6) !== 114 /* 'r' */ || + s.charCodeAt(length - 7) !== 112 /* 'p' */ || + s.charCodeAt(length - 8) !== 95 /* '_' */ || + s.charCodeAt(length - 9) !== 95 /* '_' */) { + return false; + } + + for (var i = length - 10; i >= 0; i--) { + if (s.charCodeAt(i) !== 36 /* '$' */) { + return false; + } + } + + return true; + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + } + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + } + exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + + function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; + } + + /** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ + function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(4); + var has = Object.prototype.hasOwnProperty; + var hasNativeMap = typeof Map !== "undefined"; + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = hasNativeMap ? new Map() : Object.create(null); + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ + ArraySet.prototype.size = function ArraySet_size() { + return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = hasNativeMap ? aStr : util.toSetString(aStr); + var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + if (hasNativeMap) { + this._set.set(aStr, idx); + } else { + this._set[sStr] = idx; + } + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + if (hasNativeMap) { + return this._set.has(aStr); + } else { + var sStr = util.toSetString(aStr); + return has.call(this._set, sStr); + } + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (hasNativeMap) { + var idx = this._set.get(aStr); + if (idx >= 0) { + return idx; + } + } else { + var sStr = util.toSetString(aStr); + if (has.call(this._set, sStr)) { + return this._set[sStr]; + } + } + + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(4); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(4); + var binarySearch = __webpack_require__(8); + var ArraySet = __webpack_require__(5).ArraySet; + var base64VLQ = __webpack_require__(2); + var quickSort = __webpack_require__(9).quickSort; + + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); + } + + SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + SourceMapConsumer.GREATEST_LOWER_BOUND = 1; + SourceMapConsumer.LEAST_UPPER_BOUND = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; + + /** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; + } + needle.source = this._sources.indexOf(needle.source); + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } + } + + return mappings; + }; + + exports.SourceMapConsumer = SourceMapConsumer; + + /** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + sources = sources + .map(String) + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) + ? util.relative(sourceRoot, source) + : source; + }); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names.map(String), true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; + + /** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer + */ + BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); + } + + destGeneratedMappings.push(destMapping); + } + + quickSort(smc.__originalMappings, util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + BasicSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Provide the JIT with a nice shape / hidden class. + */ + function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; + } + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; + } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + str = aStr.slice(index, end); + + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + cachedSegments[str] = segment; + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } + } + } + + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; + + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); + } + if (!this._sources.has(source)) { + return { + line: null, + column: null, + lastColumn: null + }; + } + source = this._sources.indexOf(source); + + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + + /** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ + function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); + + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); + } + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); + + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) + } + }); + } + + IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; + + /** + * The version of the source mapping spec that we are consuming. + */ + IndexedSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); + } + } + return sources; + } + }); + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[j]; + + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); + } + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.generatedColumn + + (section.generatedOffset.generatedLine === mapping.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; + + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } + } + } + + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; + + exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + exports.GREATEST_LOWER_BOUND = 1; + exports.LEAST_UPPER_BOUND = 2; + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } + + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } + + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ + exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } + + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } + + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } + + return index; + }; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + // It turns out that some (most?) JavaScript engines don't self-host + // `Array.prototype.sort`. This makes sense because C++ will likely remain + // faster than JS when doing raw CPU-intensive sorting. However, when using a + // custom comparator function, calling back and forth between the VM's C++ and + // JIT'd JS is rather slow *and* loses JIT type information, resulting in + // worse generated code for the comparator function than would be optimal. In + // fact, when sorting with a comparator, these costs outweigh the benefits of + // sorting in C++. By using our own JS-implemented Quick Sort (below), we get + // a ~3500ms mean speed-up in `bench/bench.html`. + + /** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ + function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; + } + + /** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ + function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); + } + + /** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ + function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. + + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. + + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; + + swap(ary, pivotIndex, r); + var pivot = ary[r]; + + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); + } + } + + swap(ary, i + 1, j); + var q = i + 1; + + // (2) Recurse on each half. + + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } + } + + /** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ + exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); + }; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var SourceMapGenerator = __webpack_require__(1).SourceMapGenerator; + var util = __webpack_require__(4); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are accessed by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var remainingLinesIndex = 0; + var shiftNextLine = function() { + var lineContents = getNextLine(); + // The last line of a file might not have a newline. + var newLine = getNextLine() || ""; + return lineContents + newLine; + + function getNextLine() { + return remainingLinesIndex < remainingLines.length ? + remainingLines[remainingLinesIndex++] : undefined; + } + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[remainingLinesIndex]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[remainingLinesIndex]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLinesIndex < remainingLines.length) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.splice(remainingLinesIndex).join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + + +/***/ }) +/******/ ]) +}); +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCBlNDczOGZjNzJhN2IyMzAzOTg4OSIsIndlYnBhY2s6Ly8vLi9zb3VyY2UtbWFwLmpzIiwid2VicGFjazovLy8uL2xpYi9zb3VyY2UtbWFwLWdlbmVyYXRvci5qcyIsIndlYnBhY2s6Ly8vLi9saWIvYmFzZTY0LXZscS5qcyIsIndlYnBhY2s6Ly8vLi9saWIvYmFzZTY0LmpzIiwid2VicGFjazovLy8uL2xpYi91dGlsLmpzIiwid2VicGFjazovLy8uL2xpYi9hcnJheS1zZXQuanMiLCJ3ZWJwYWNrOi8vLy4vbGliL21hcHBpbmctbGlzdC5qcyIsIndlYnBhY2s6Ly8vLi9saWIvc291cmNlLW1hcC1jb25zdW1lci5qcyIsIndlYnBhY2s6Ly8vLi9saWIvYmluYXJ5LXNlYXJjaC5qcyIsIndlYnBhY2s6Ly8vLi9saWIvcXVpY2stc29ydC5qcyIsIndlYnBhY2s6Ly8vLi9saWIvc291cmNlLW5vZGUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELE87QUNWQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx1QkFBZTtBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7Ozs7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUNQQSxpQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxNQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsTUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTBDLFNBQVM7QUFDbkQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxxQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7O0FDL1pBLGlCQUFnQixvQkFBb0I7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDREQUEyRDtBQUMzRCxxQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRzs7QUFFSDtBQUNBO0FBQ0E7Ozs7Ozs7QUMzSUEsaUJBQWdCLG9CQUFvQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWdCO0FBQ2hCLGlCQUFnQjs7QUFFaEIsb0JBQW1CO0FBQ25CLHFCQUFvQjs7QUFFcEIsaUJBQWdCO0FBQ2hCLGlCQUFnQjs7QUFFaEIsaUJBQWdCO0FBQ2hCLGtCQUFpQjs7QUFFakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7Ozs7QUNsRUEsaUJBQWdCLG9CQUFvQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIO0FBQ0EsSUFBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0NBQThDLFFBQVE7QUFDdEQ7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMO0FBQ0EsTUFBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDRCQUEyQixRQUFRO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7Ozs7QUNoYUEsaUJBQWdCLG9CQUFvQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXNDLFNBQVM7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7OztBQ3hIQSxpQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWdCO0FBQ2hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7OztBQzlFQSxpQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1REFBc0Q7QUFDdEQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxvQkFBbUI7QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVc7O0FBRVg7QUFDQTtBQUNBLFFBQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTJCLE1BQU07QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1REFBc0Q7QUFDdEQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHVEQUFzRCxZQUFZO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBLEVBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0NBQW1DO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBeUIsY0FBYztBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXVCLHdDQUF3QztBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQStDLG1CQUFtQixFQUFFO0FBQ3BFOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFpQixvQkFBb0I7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE2QixNQUFNO0FBQ25DO0FBQ0EsUUFBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXNEO0FBQ3REOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFtQiwyQkFBMkI7QUFDOUMsc0JBQXFCLCtDQUErQztBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsUUFBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW1CLDJCQUEyQjtBQUM5Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBbUIsMkJBQTJCO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFtQiwyQkFBMkI7QUFDOUM7QUFDQTtBQUNBLHNCQUFxQiw0QkFBNEI7QUFDakQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOzs7Ozs7O0FDempDQSxpQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7OztBQzlHQSxpQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVcsTUFBTTtBQUNqQjtBQUNBLFlBQVcsT0FBTztBQUNsQjtBQUNBLFlBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFXLE9BQU87QUFDbEI7QUFDQSxZQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFXLE1BQU07QUFDakI7QUFDQSxZQUFXLFNBQVM7QUFDcEI7QUFDQSxZQUFXLE9BQU87QUFDbEI7QUFDQSxZQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFtQixPQUFPO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFXLE1BQU07QUFDakI7QUFDQSxZQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQ2pIQSxpQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBaUMsUUFBUTtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBNkMsU0FBUztBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBb0I7QUFDcEI7QUFDQTtBQUNBLHVDQUFzQztBQUN0QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBK0MsU0FBUztBQUN4RDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBDQUF5QyxTQUFTO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFlBQVc7QUFDWDtBQUNBLFVBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSw2Q0FBNEMsY0FBYztBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGNBQWE7QUFDYjtBQUNBLFlBQVc7QUFDWDtBQUNBLFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7QUFDQTtBQUNBLElBQUc7O0FBRUgsV0FBVTtBQUNWOztBQUVBIiwiZmlsZSI6InNvdXJjZS1tYXAuZGVidWcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gd2VicGFja1VuaXZlcnNhbE1vZHVsZURlZmluaXRpb24ocm9vdCwgZmFjdG9yeSkge1xuXHRpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7XG5cdGVsc2UgaWYodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKVxuXHRcdGRlZmluZShbXSwgZmFjdG9yeSk7XG5cdGVsc2UgaWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKVxuXHRcdGV4cG9ydHNbXCJzb3VyY2VNYXBcIl0gPSBmYWN0b3J5KCk7XG5cdGVsc2Vcblx0XHRyb290W1wic291cmNlTWFwXCJdID0gZmFjdG9yeSgpO1xufSkodGhpcywgZnVuY3Rpb24oKSB7XG5yZXR1cm4gXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svdW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbiIsIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKVxuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuXG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRleHBvcnRzOiB7fSxcbiBcdFx0XHRpZDogbW9kdWxlSWQsXG4gXHRcdFx0bG9hZGVkOiBmYWxzZVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sb2FkZWQgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svYm9vdHN0cmFwIGU0NzM4ZmM3MmE3YjIzMDM5ODg5IiwiLypcbiAqIENvcHlyaWdodCAyMDA5LTIwMTEgTW96aWxsYSBGb3VuZGF0aW9uIGFuZCBjb250cmlidXRvcnNcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBOZXcgQlNEIGxpY2Vuc2UuIFNlZSBMSUNFTlNFLnR4dCBvcjpcbiAqIGh0dHA6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9CU0QtMy1DbGF1c2VcbiAqL1xuZXhwb3J0cy5Tb3VyY2VNYXBHZW5lcmF0b3IgPSByZXF1aXJlKCcuL2xpYi9zb3VyY2UtbWFwLWdlbmVyYXRvcicpLlNvdXJjZU1hcEdlbmVyYXRvcjtcbmV4cG9ydHMuU291cmNlTWFwQ29uc3VtZXIgPSByZXF1aXJlKCcuL2xpYi9zb3VyY2UtbWFwLWNvbnN1bWVyJykuU291cmNlTWFwQ29uc3VtZXI7XG5leHBvcnRzLlNvdXJjZU5vZGUgPSByZXF1aXJlKCcuL2xpYi9zb3VyY2Utbm9kZScpLlNvdXJjZU5vZGU7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NvdXJjZS1tYXAuanNcbi8vIG1vZHVsZSBpZCA9IDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogLSotIE1vZGU6IGpzOyBqcy1pbmRlbnQtbGV2ZWw6IDI7IC0qLSAqL1xuLypcbiAqIENvcHlyaWdodCAyMDExIE1vemlsbGEgRm91bmRhdGlvbiBhbmQgY29udHJpYnV0b3JzXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTmV3IEJTRCBsaWNlbnNlLiBTZWUgTElDRU5TRSBvcjpcbiAqIGh0dHA6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9CU0QtMy1DbGF1c2VcbiAqL1xuXG52YXIgYmFzZTY0VkxRID0gcmVxdWlyZSgnLi9iYXNlNjQtdmxxJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xudmFyIEFycmF5U2V0ID0gcmVxdWlyZSgnLi9hcnJheS1zZXQnKS5BcnJheVNldDtcbnZhciBNYXBwaW5nTGlzdCA9IHJlcXVpcmUoJy4vbWFwcGluZy1saXN0JykuTWFwcGluZ0xpc3Q7XG5cbi8qKlxuICogQW4gaW5zdGFuY2Ugb2YgdGhlIFNvdXJjZU1hcEdlbmVyYXRvciByZXByZXNlbnRzIGEgc291cmNlIG1hcCB3aGljaCBpc1xuICogYmVpbmcgYnVpbHQgaW5jcmVtZW50YWxseS4gWW91IG1heSBwYXNzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmdcbiAqIHByb3BlcnRpZXM6XG4gKlxuICogICAtIGZpbGU6IFRoZSBmaWxlbmFtZSBvZiB0aGUgZ2VuZXJhdGVkIHNvdXJjZS5cbiAqICAgLSBzb3VyY2VSb290OiBBIHJvb3QgZm9yIGFsbCByZWxhdGl2ZSBVUkxzIGluIHRoaXMgc291cmNlIG1hcC5cbiAqL1xuZnVuY3Rpb24gU291cmNlTWFwR2VuZXJhdG9yKGFBcmdzKSB7XG4gIGlmICghYUFyZ3MpIHtcbiAgICBhQXJncyA9IHt9O1xuICB9XG4gIHRoaXMuX2ZpbGUgPSB1dGlsLmdldEFyZyhhQXJncywgJ2ZpbGUnLCBudWxsKTtcbiAgdGhpcy5fc291cmNlUm9vdCA9IHV0aWwuZ2V0QXJnKGFBcmdzLCAnc291cmNlUm9vdCcsIG51bGwpO1xuICB0aGlzLl9za2lwVmFsaWRhdGlvbiA9IHV0aWwuZ2V0QXJnKGFBcmdzLCAnc2tpcFZhbGlkYXRpb24nLCBmYWxzZSk7XG4gIHRoaXMuX3NvdXJjZXMgPSBuZXcgQXJyYXlTZXQoKTtcbiAgdGhpcy5fbmFtZXMgPSBuZXcgQXJyYXlTZXQoKTtcbiAgdGhpcy5fbWFwcGluZ3MgPSBuZXcgTWFwcGluZ0xpc3QoKTtcbiAgdGhpcy5fc291cmNlc0NvbnRlbnRzID0gbnVsbDtcbn1cblxuU291cmNlTWFwR2VuZXJhdG9yLnByb3RvdHlwZS5fdmVyc2lvbiA9IDM7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBTb3VyY2VNYXBHZW5lcmF0b3IgYmFzZWQgb24gYSBTb3VyY2VNYXBDb25zdW1lclxuICpcbiAqIEBwYXJhbSBhU291cmNlTWFwQ29uc3VtZXIgVGhlIFNvdXJjZU1hcC5cbiAqL1xuU291cmNlTWFwR2VuZXJhdG9yLmZyb21Tb3VyY2VNYXAgPVxuICBmdW5jdGlvbiBTb3VyY2VNYXBHZW5lcmF0b3JfZnJvbVNvdXJjZU1hcChhU291cmNlTWFwQ29uc3VtZXIpIHtcbiAgICB2YXIgc291cmNlUm9vdCA9IGFTb3VyY2VNYXBDb25zdW1lci5zb3VyY2VSb290O1xuICAgIHZhciBnZW5lcmF0b3IgPSBuZXcgU291cmNlTWFwR2VuZXJhdG9yKHtcbiAgICAgIGZpbGU6IGFTb3VyY2VNYXBDb25zdW1lci5maWxlLFxuICAgICAgc291cmNlUm9vdDogc291cmNlUm9vdFxuICAgIH0pO1xuICAgIGFTb3VyY2VNYXBDb25zdW1lci5lYWNoTWFwcGluZyhmdW5jdGlvbiAobWFwcGluZykge1xuICAgICAgdmFyIG5ld01hcHBpbmcgPSB7XG4gICAgICAgIGdlbmVyYXRlZDoge1xuICAgICAgICAgIGxpbmU6IG1hcHBpbmcuZ2VuZXJhdGVkTGluZSxcbiAgICAgICAgICBjb2x1bW46IG1hcHBpbmcuZ2VuZXJhdGVkQ29sdW1uXG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmIChtYXBwaW5nLnNvdXJjZSAhPSBudWxsKSB7XG4gICAgICAgIG5ld01hcHBpbmcuc291cmNlID0gbWFwcGluZy5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2VSb290ICE9IG51bGwpIHtcbiAgICAgICAgICBuZXdNYXBwaW5nLnNvdXJjZSA9IHV0aWwucmVsYXRpdmUoc291cmNlUm9vdCwgbmV3TWFwcGluZy5zb3VyY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgbmV3TWFwcGluZy5vcmlnaW5hbCA9IHtcbiAgICAgICAgICBsaW5lOiBtYXBwaW5nLm9yaWdpbmFsTGluZSxcbiAgICAgICAgICBjb2x1bW46IG1hcHBpbmcub3JpZ2luYWxDb2x1bW5cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobWFwcGluZy5uYW1lICE9IG51bGwpIHtcbiAgICAgICAgICBuZXdNYXBwaW5nLm5hbWUgPSBtYXBwaW5nLm5hbWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZ2VuZXJhdG9yLmFkZE1hcHBpbmcobmV3TWFwcGluZyk7XG4gICAgfSk7XG4gICAgYVNvdXJjZU1hcENvbnN1bWVyLnNvdXJjZXMuZm9yRWFjaChmdW5jdGlvbiAoc291cmNlRmlsZSkge1xuICAgICAgdmFyIGNvbnRlbnQgPSBhU291cmNlTWFwQ29uc3VtZXIuc291cmNlQ29udGVudEZvcihzb3VyY2VGaWxlKTtcbiAgICAgIGlmIChjb250ZW50ICE9IG51bGwpIHtcbiAgICAgICAgZ2VuZXJhdG9yLnNldFNvdXJjZUNvbnRlbnQoc291cmNlRmlsZSwgY29udGVudCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGdlbmVyYXRvcjtcbiAgfTtcblxuLyoqXG4gKiBBZGQgYSBzaW5nbGUgbWFwcGluZyBmcm9tIG9yaWdpbmFsIHNvdXJjZSBsaW5lIGFuZCBjb2x1bW4gdG8gdGhlIGdlbmVyYXRlZFxuICogc291cmNlJ3MgbGluZSBhbmQgY29sdW1uIGZvciB0aGlzIHNvdXJjZSBtYXAgYmVpbmcgY3JlYXRlZC4gVGhlIG1hcHBpbmdcbiAqIG9iamVjdCBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIGdlbmVyYXRlZDogQW4gb2JqZWN0IHdpdGggdGhlIGdlbmVyYXRlZCBsaW5lIGFuZCBjb2x1bW4gcG9zaXRpb25zLlxuICogICAtIG9yaWdpbmFsOiBBbiBvYmplY3Qgd2l0aCB0aGUgb3JpZ2luYWwgbGluZSBhbmQgY29sdW1uIHBvc2l0aW9ucy5cbiAqICAgLSBzb3VyY2U6IFRoZSBvcmlnaW5hbCBzb3VyY2UgZmlsZSAocmVsYXRpdmUgdG8gdGhlIHNvdXJjZVJvb3QpLlxuICogICAtIG5hbWU6IEFuIG9wdGlvbmFsIG9yaWdpbmFsIHRva2VuIG5hbWUgZm9yIHRoaXMgbWFwcGluZy5cbiAqL1xuU291cmNlTWFwR2VuZXJhdG9yLnByb3RvdHlwZS5hZGRNYXBwaW5nID1cbiAgZnVuY3Rpb24gU291cmNlTWFwR2VuZXJhdG9yX2FkZE1hcHBpbmcoYUFyZ3MpIHtcbiAgICB2YXIgZ2VuZXJhdGVkID0gdXRpbC5nZXRBcmcoYUFyZ3MsICdnZW5lcmF0ZWQnKTtcbiAgICB2YXIgb3JpZ2luYWwgPSB1dGlsLmdldEFyZyhhQXJncywgJ29yaWdpbmFsJywgbnVsbCk7XG4gICAgdmFyIHNvdXJjZSA9IHV0aWwuZ2V0QXJnKGFBcmdzLCAnc291cmNlJywgbnVsbCk7XG4gICAgdmFyIG5hbWUgPSB1dGlsLmdldEFyZyhhQXJncywgJ25hbWUnLCBudWxsKTtcblxuICAgIGlmICghdGhpcy5fc2tpcFZhbGlkYXRpb24pIHtcbiAgICAgIHRoaXMuX3ZhbGlkYXRlTWFwcGluZyhnZW5lcmF0ZWQsIG9yaWdpbmFsLCBzb3VyY2UsIG5hbWUpO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2UgIT0gbnVsbCkge1xuICAgICAgc291cmNlID0gU3RyaW5nKHNvdXJjZSk7XG4gICAgICBpZiAoIXRoaXMuX3NvdXJjZXMuaGFzKHNvdXJjZSkpIHtcbiAgICAgICAgdGhpcy5fc291cmNlcy5hZGQoc291cmNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobmFtZSAhPSBudWxsKSB7XG4gICAgICBuYW1lID0gU3RyaW5nKG5hbWUpO1xuICAgICAgaWYgKCF0aGlzLl9uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgICAgdGhpcy5fbmFtZXMuYWRkKG5hbWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX21hcHBpbmdzLmFkZCh7XG4gICAgICBnZW5lcmF0ZWRMaW5lOiBnZW5lcmF0ZWQubGluZSxcbiAgICAgIGdlbmVyYXRlZENvbHVtbjogZ2VuZXJhdGVkLmNvbHVtbixcbiAgICAgIG9yaWdpbmFsTGluZTogb3JpZ2luYWwgIT0gbnVsbCAmJiBvcmlnaW5hbC5saW5lLFxuICAgICAgb3JpZ2luYWxDb2x1bW46IG9yaWdpbmFsICE9IG51bGwgJiYgb3JpZ2luYWwuY29sdW1uLFxuICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICBuYW1lOiBuYW1lXG4gICAgfSk7XG4gIH07XG5cbi8qKlxuICogU2V0IHRoZSBzb3VyY2UgY29udGVudCBmb3IgYSBzb3VyY2UgZmlsZS5cbiAqL1xuU291cmNlTWFwR2VuZXJhdG9yLnByb3RvdHlwZS5zZXRTb3VyY2VDb250ZW50ID1cbiAgZnVuY3Rpb24gU291cmNlTWFwR2VuZXJhdG9yX3NldFNvdXJjZUNvbnRlbnQoYVNvdXJjZUZpbGUsIGFTb3VyY2VDb250ZW50KSB7XG4gICAgdmFyIHNvdXJjZSA9IGFTb3VyY2VGaWxlO1xuICAgIGlmICh0aGlzLl9zb3VyY2VSb290ICE9IG51bGwpIHtcbiAgICAgIHNvdXJjZSA9IHV0aWwucmVsYXRpdmUodGhpcy5fc291cmNlUm9vdCwgc291cmNlKTtcbiAgICB9XG5cbiAgICBpZiAoYVNvdXJjZUNvbnRlbnQgIT0gbnVsbCkge1xuICAgICAgLy8gQWRkIHRoZSBzb3VyY2UgY29udGVudCB0byB0aGUgX3NvdXJjZXNDb250ZW50cyBtYXAuXG4gICAgICAvLyBDcmVhdGUgYSBuZXcgX3NvdXJjZXNDb250ZW50cyBtYXAgaWYgdGhlIHByb3BlcnR5IGlzIG51bGwuXG4gICAgICBpZiAoIXRoaXMuX3NvdXJjZXNDb250ZW50cykge1xuICAgICAgICB0aGlzLl9zb3VyY2VzQ29udGVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgfVxuICAgICAgdGhpcy5fc291cmNlc0NvbnRlbnRzW3V0aWwudG9TZXRTdHJpbmcoc291cmNlKV0gPSBhU291cmNlQ29udGVudDtcbiAgICB9IGVsc2UgaWYgKHRoaXMuX3NvdXJjZXNDb250ZW50cykge1xuICAgICAgLy8gUmVtb3ZlIHRoZSBzb3VyY2UgZmlsZSBmcm9tIHRoZSBfc291cmNlc0NvbnRlbnRzIG1hcC5cbiAgICAgIC8vIElmIHRoZSBfc291cmNlc0NvbnRlbnRzIG1hcCBpcyBlbXB0eSwgc2V0IHRoZSBwcm9wZXJ0eSB0byBudWxsLlxuICAgICAgZGVsZXRlIHRoaXMuX3NvdXJjZXNDb250ZW50c1t1dGlsLnRvU2V0U3RyaW5nKHNvdXJjZSldO1xuICAgICAgaWYgKE9iamVjdC5rZXlzKHRoaXMuX3NvdXJjZXNDb250ZW50cykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRoaXMuX3NvdXJjZXNDb250ZW50cyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4vKipcbiAqIEFwcGxpZXMgdGhlIG1hcHBpbmdzIG9mIGEgc3ViLXNvdXJjZS1tYXAgZm9yIGEgc3BlY2lmaWMgc291cmNlIGZpbGUgdG8gdGhlXG4gKiBzb3VyY2UgbWFwIGJlaW5nIGdlbmVyYXRlZC4gRWFjaCBtYXBwaW5nIHRvIHRoZSBzdXBwbGllZCBzb3VyY2UgZmlsZSBpc1xuICogcmV3cml0dGVuIHVzaW5nIHRoZSBzdXBwbGllZCBzb3VyY2UgbWFwLiBOb3RlOiBUaGUgcmVzb2x1dGlvbiBmb3IgdGhlXG4gKiByZXN1bHRpbmcgbWFwcGluZ3MgaXMgdGhlIG1pbmltaXVtIG9mIHRoaXMgbWFwIGFuZCB0aGUgc3VwcGxpZWQgbWFwLlxuICpcbiAqIEBwYXJhbSBhU291cmNlTWFwQ29uc3VtZXIgVGhlIHNvdXJjZSBtYXAgdG8gYmUgYXBwbGllZC5cbiAqIEBwYXJhbSBhU291cmNlRmlsZSBPcHRpb25hbC4gVGhlIGZpbGVuYW1lIG9mIHRoZSBzb3VyY2UgZmlsZS5cbiAqICAgICAgICBJZiBvbWl0dGVkLCBTb3VyY2VNYXBDb25zdW1lcidzIGZpbGUgcHJvcGVydHkgd2lsbCBiZSB1c2VkLlxuICogQHBhcmFtIGFTb3VyY2VNYXBQYXRoIE9wdGlvbmFsLiBUaGUgZGlybmFtZSBvZiB0aGUgcGF0aCB0byB0aGUgc291cmNlIG1hcFxuICogICAgICAgIHRvIGJlIGFwcGxpZWQuIElmIHJlbGF0aXZlLCBpdCBpcyByZWxhdGl2ZSB0byB0aGUgU291cmNlTWFwQ29uc3VtZXIuXG4gKiAgICAgICAgVGhpcyBwYXJhbWV0ZXIgaXMgbmVlZGVkIHdoZW4gdGhlIHR3byBzb3VyY2UgbWFwcyBhcmVuJ3QgaW4gdGhlIHNhbWVcbiAqICAgICAgICBkaXJlY3RvcnksIGFuZCB0aGUgc291cmNlIG1hcCB0byBiZSBhcHBsaWVkIGNvbnRhaW5zIHJlbGF0aXZlIHNvdXJjZVxuICogICAgICAgIHBhdGhzLiBJZiBzbywgdGhvc2UgcmVsYXRpdmUgc291cmNlIHBhdGhzIG5lZWQgdG8gYmUgcmV3cml0dGVuXG4gKiAgICAgICAgcmVsYXRpdmUgdG8gdGhlIFNvdXJjZU1hcEdlbmVyYXRvci5cbiAqL1xuU291cmNlTWFwR2VuZXJhdG9yLnByb3RvdHlwZS5hcHBseVNvdXJjZU1hcCA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcEdlbmVyYXRvcl9hcHBseVNvdXJjZU1hcChhU291cmNlTWFwQ29uc3VtZXIsIGFTb3VyY2VGaWxlLCBhU291cmNlTWFwUGF0aCkge1xuICAgIHZhciBzb3VyY2VGaWxlID0gYVNvdXJjZUZpbGU7XG4gICAgLy8gSWYgYVNvdXJjZUZpbGUgaXMgb21pdHRlZCwgd2Ugd2lsbCB1c2UgdGhlIGZpbGUgcHJvcGVydHkgb2YgdGhlIFNvdXJjZU1hcFxuICAgIGlmIChhU291cmNlRmlsZSA9PSBudWxsKSB7XG4gICAgICBpZiAoYVNvdXJjZU1hcENvbnN1bWVyLmZpbGUgPT0gbnVsbCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ1NvdXJjZU1hcEdlbmVyYXRvci5wcm90b3R5cGUuYXBwbHlTb3VyY2VNYXAgcmVxdWlyZXMgZWl0aGVyIGFuIGV4cGxpY2l0IHNvdXJjZSBmaWxlLCAnICtcbiAgICAgICAgICAnb3IgdGhlIHNvdXJjZSBtYXBcXCdzIFwiZmlsZVwiIHByb3BlcnR5LiBCb3RoIHdlcmUgb21pdHRlZC4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzb3VyY2VGaWxlID0gYVNvdXJjZU1hcENvbnN1bWVyLmZpbGU7XG4gICAgfVxuICAgIHZhciBzb3VyY2VSb290ID0gdGhpcy5fc291cmNlUm9vdDtcbiAgICAvLyBNYWtlIFwic291cmNlRmlsZVwiIHJlbGF0aXZlIGlmIGFuIGFic29sdXRlIFVybCBpcyBwYXNzZWQuXG4gICAgaWYgKHNvdXJjZVJvb3QgIT0gbnVsbCkge1xuICAgICAgc291cmNlRmlsZSA9IHV0aWwucmVsYXRpdmUoc291cmNlUm9vdCwgc291cmNlRmlsZSk7XG4gICAgfVxuICAgIC8vIEFwcGx5aW5nIHRoZSBTb3VyY2VNYXAgY2FuIGFkZCBhbmQgcmVtb3ZlIGl0ZW1zIGZyb20gdGhlIHNvdXJjZXMgYW5kXG4gICAgLy8gdGhlIG5hbWVzIGFycmF5LlxuICAgIHZhciBuZXdTb3VyY2VzID0gbmV3IEFycmF5U2V0KCk7XG4gICAgdmFyIG5ld05hbWVzID0gbmV3IEFycmF5U2V0KCk7XG5cbiAgICAvLyBGaW5kIG1hcHBpbmdzIGZvciB0aGUgXCJzb3VyY2VGaWxlXCJcbiAgICB0aGlzLl9tYXBwaW5ncy51bnNvcnRlZEZvckVhY2goZnVuY3Rpb24gKG1hcHBpbmcpIHtcbiAgICAgIGlmIChtYXBwaW5nLnNvdXJjZSA9PT0gc291cmNlRmlsZSAmJiBtYXBwaW5nLm9yaWdpbmFsTGluZSAhPSBudWxsKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIGl0IGNhbiBiZSBtYXBwZWQgYnkgdGhlIHNvdXJjZSBtYXAsIHRoZW4gdXBkYXRlIHRoZSBtYXBwaW5nLlxuICAgICAgICB2YXIgb3JpZ2luYWwgPSBhU291cmNlTWFwQ29uc3VtZXIub3JpZ2luYWxQb3NpdGlvbkZvcih7XG4gICAgICAgICAgbGluZTogbWFwcGluZy5vcmlnaW5hbExpbmUsXG4gICAgICAgICAgY29sdW1uOiBtYXBwaW5nLm9yaWdpbmFsQ29sdW1uXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob3JpZ2luYWwuc291cmNlICE9IG51bGwpIHtcbiAgICAgICAgICAvLyBDb3B5IG1hcHBpbmdcbiAgICAgICAgICBtYXBwaW5nLnNvdXJjZSA9IG9yaWdpbmFsLnNvdXJjZTtcbiAgICAgICAgICBpZiAoYVNvdXJjZU1hcFBhdGggIT0gbnVsbCkge1xuICAgICAgICAgICAgbWFwcGluZy5zb3VyY2UgPSB1dGlsLmpvaW4oYVNvdXJjZU1hcFBhdGgsIG1hcHBpbmcuc291cmNlKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc291cmNlUm9vdCAhPSBudWxsKSB7XG4gICAgICAgICAgICBtYXBwaW5nLnNvdXJjZSA9IHV0aWwucmVsYXRpdmUoc291cmNlUm9vdCwgbWFwcGluZy5zb3VyY2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBtYXBwaW5nLm9yaWdpbmFsTGluZSA9IG9yaWdpbmFsLmxpbmU7XG4gICAgICAgICAgbWFwcGluZy5vcmlnaW5hbENvbHVtbiA9IG9yaWdpbmFsLmNvbHVtbjtcbiAgICAgICAgICBpZiAob3JpZ2luYWwubmFtZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBtYXBwaW5nLm5hbWUgPSBvcmlnaW5hbC5uYW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgc291cmNlID0gbWFwcGluZy5zb3VyY2U7XG4gICAgICBpZiAoc291cmNlICE9IG51bGwgJiYgIW5ld1NvdXJjZXMuaGFzKHNvdXJjZSkpIHtcbiAgICAgICAgbmV3U291cmNlcy5hZGQoc291cmNlKTtcbiAgICAgIH1cblxuICAgICAgdmFyIG5hbWUgPSBtYXBwaW5nLm5hbWU7XG4gICAgICBpZiAobmFtZSAhPSBudWxsICYmICFuZXdOYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgICAgbmV3TmFtZXMuYWRkKG5hbWUpO1xuICAgICAgfVxuXG4gICAgfSwgdGhpcyk7XG4gICAgdGhpcy5fc291cmNlcyA9IG5ld1NvdXJjZXM7XG4gICAgdGhpcy5fbmFtZXMgPSBuZXdOYW1lcztcblxuICAgIC8vIENvcHkgc291cmNlc0NvbnRlbnRzIG9mIGFwcGxpZWQgbWFwLlxuICAgIGFTb3VyY2VNYXBDb25zdW1lci5zb3VyY2VzLmZvckVhY2goZnVuY3Rpb24gKHNvdXJjZUZpbGUpIHtcbiAgICAgIHZhciBjb250ZW50ID0gYVNvdXJjZU1hcENvbnN1bWVyLnNvdXJjZUNvbnRlbnRGb3Ioc291cmNlRmlsZSk7XG4gICAgICBpZiAoY29udGVudCAhPSBudWxsKSB7XG4gICAgICAgIGlmIChhU291cmNlTWFwUGF0aCAhPSBudWxsKSB7XG4gICAgICAgICAgc291cmNlRmlsZSA9IHV0aWwuam9pbihhU291cmNlTWFwUGF0aCwgc291cmNlRmlsZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNvdXJjZVJvb3QgIT0gbnVsbCkge1xuICAgICAgICAgIHNvdXJjZUZpbGUgPSB1dGlsLnJlbGF0aXZlKHNvdXJjZVJvb3QsIHNvdXJjZUZpbGUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0U291cmNlQ29udGVudChzb3VyY2VGaWxlLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9LCB0aGlzKTtcbiAgfTtcblxuLyoqXG4gKiBBIG1hcHBpbmcgY2FuIGhhdmUgb25lIG9mIHRoZSB0aHJlZSBsZXZlbHMgb2YgZGF0YTpcbiAqXG4gKiAgIDEuIEp1c3QgdGhlIGdlbmVyYXRlZCBwb3NpdGlvbi5cbiAqICAgMi4gVGhlIEdlbmVyYXRlZCBwb3NpdGlvbiwgb3JpZ2luYWwgcG9zaXRpb24sIGFuZCBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIDMuIEdlbmVyYXRlZCBhbmQgb3JpZ2luYWwgcG9zaXRpb24sIG9yaWdpbmFsIHNvdXJjZSwgYXMgd2VsbCBhcyBhIG5hbWVcbiAqICAgICAgdG9rZW4uXG4gKlxuICogVG8gbWFpbnRhaW4gY29uc2lzdGVuY3ksIHdlIHZhbGlkYXRlIHRoYXQgYW55IG5ldyBtYXBwaW5nIGJlaW5nIGFkZGVkIGZhbGxzXG4gKiBpbiB0byBvbmUgb2YgdGhlc2UgY2F0ZWdvcmllcy5cbiAqL1xuU291cmNlTWFwR2VuZXJhdG9yLnByb3RvdHlwZS5fdmFsaWRhdGVNYXBwaW5nID1cbiAgZnVuY3Rpb24gU291cmNlTWFwR2VuZXJhdG9yX3ZhbGlkYXRlTWFwcGluZyhhR2VuZXJhdGVkLCBhT3JpZ2luYWwsIGFTb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYU5hbWUpIHtcbiAgICAvLyBXaGVuIGFPcmlnaW5hbCBpcyB0cnV0aHkgYnV0IGhhcyBlbXB0eSB2YWx1ZXMgZm9yIC5saW5lIGFuZCAuY29sdW1uLFxuICAgIC8vIGl0IGlzIG1vc3QgbGlrZWx5IGEgcHJvZ3JhbW1lciBlcnJvci4gSW4gdGhpcyBjYXNlIHdlIHRocm93IGEgdmVyeVxuICAgIC8vIHNwZWNpZmljIGVycm9yIG1lc3NhZ2UgdG8gdHJ5IHRvIGd1aWRlIHRoZW0gdGhlIHJpZ2h0IHdheS5cbiAgICAvLyBGb3IgZXhhbXBsZTogaHR0cHM6Ly9naXRodWIuY29tL1BvbHltZXIvcG9seW1lci1idW5kbGVyL3B1bGwvNTE5XG4gICAgaWYgKGFPcmlnaW5hbCAmJiB0eXBlb2YgYU9yaWdpbmFsLmxpbmUgIT09ICdudW1iZXInICYmIHR5cGVvZiBhT3JpZ2luYWwuY29sdW1uICE9PSAnbnVtYmVyJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnb3JpZ2luYWwubGluZSBhbmQgb3JpZ2luYWwuY29sdW1uIGFyZSBub3QgbnVtYmVycyAtLSB5b3UgcHJvYmFibHkgbWVhbnQgdG8gb21pdCAnICtcbiAgICAgICAgICAgICd0aGUgb3JpZ2luYWwgbWFwcGluZyBlbnRpcmVseSBhbmQgb25seSBtYXAgdGhlIGdlbmVyYXRlZCBwb3NpdGlvbi4gSWYgc28sIHBhc3MgJyArXG4gICAgICAgICAgICAnbnVsbCBmb3IgdGhlIG9yaWdpbmFsIG1hcHBpbmcgaW5zdGVhZCBvZiBhbiBvYmplY3Qgd2l0aCBlbXB0eSBvciBudWxsIHZhbHVlcy4nXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKGFHZW5lcmF0ZWQgJiYgJ2xpbmUnIGluIGFHZW5lcmF0ZWQgJiYgJ2NvbHVtbicgaW4gYUdlbmVyYXRlZFxuICAgICAgICAmJiBhR2VuZXJhdGVkLmxpbmUgPiAwICYmIGFHZW5lcmF0ZWQuY29sdW1uID49IDBcbiAgICAgICAgJiYgIWFPcmlnaW5hbCAmJiAhYVNvdXJjZSAmJiAhYU5hbWUpIHtcbiAgICAgIC8vIENhc2UgMS5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZWxzZSBpZiAoYUdlbmVyYXRlZCAmJiAnbGluZScgaW4gYUdlbmVyYXRlZCAmJiAnY29sdW1uJyBpbiBhR2VuZXJhdGVkXG4gICAgICAgICAgICAgJiYgYU9yaWdpbmFsICYmICdsaW5lJyBpbiBhT3JpZ2luYWwgJiYgJ2NvbHVtbicgaW4gYU9yaWdpbmFsXG4gICAgICAgICAgICAgJiYgYUdlbmVyYXRlZC5saW5lID4gMCAmJiBhR2VuZXJhdGVkLmNvbHVtbiA+PSAwXG4gICAgICAgICAgICAgJiYgYU9yaWdpbmFsLmxpbmUgPiAwICYmIGFPcmlnaW5hbC5jb2x1bW4gPj0gMFxuICAgICAgICAgICAgICYmIGFTb3VyY2UpIHtcbiAgICAgIC8vIENhc2VzIDIgYW5kIDMuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1hcHBpbmc6ICcgKyBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGdlbmVyYXRlZDogYUdlbmVyYXRlZCxcbiAgICAgICAgc291cmNlOiBhU291cmNlLFxuICAgICAgICBvcmlnaW5hbDogYU9yaWdpbmFsLFxuICAgICAgICBuYW1lOiBhTmFtZVxuICAgICAgfSkpO1xuICAgIH1cbiAgfTtcblxuLyoqXG4gKiBTZXJpYWxpemUgdGhlIGFjY3VtdWxhdGVkIG1hcHBpbmdzIGluIHRvIHRoZSBzdHJlYW0gb2YgYmFzZSA2NCBWTFFzXG4gKiBzcGVjaWZpZWQgYnkgdGhlIHNvdXJjZSBtYXAgZm9ybWF0LlxuICovXG5Tb3VyY2VNYXBHZW5lcmF0b3IucHJvdG90eXBlLl9zZXJpYWxpemVNYXBwaW5ncyA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcEdlbmVyYXRvcl9zZXJpYWxpemVNYXBwaW5ncygpIHtcbiAgICB2YXIgcHJldmlvdXNHZW5lcmF0ZWRDb2x1bW4gPSAwO1xuICAgIHZhciBwcmV2aW91c0dlbmVyYXRlZExpbmUgPSAxO1xuICAgIHZhciBwcmV2aW91c09yaWdpbmFsQ29sdW1uID0gMDtcbiAgICB2YXIgcHJldmlvdXNPcmlnaW5hbExpbmUgPSAwO1xuICAgIHZhciBwcmV2aW91c05hbWUgPSAwO1xuICAgIHZhciBwcmV2aW91c1NvdXJjZSA9IDA7XG4gICAgdmFyIHJlc3VsdCA9ICcnO1xuICAgIHZhciBuZXh0O1xuICAgIHZhciBtYXBwaW5nO1xuICAgIHZhciBuYW1lSWR4O1xuICAgIHZhciBzb3VyY2VJZHg7XG5cbiAgICB2YXIgbWFwcGluZ3MgPSB0aGlzLl9tYXBwaW5ncy50b0FycmF5KCk7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IG1hcHBpbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBtYXBwaW5nID0gbWFwcGluZ3NbaV07XG4gICAgICBuZXh0ID0gJydcblxuICAgICAgaWYgKG1hcHBpbmcuZ2VuZXJhdGVkTGluZSAhPT0gcHJldmlvdXNHZW5lcmF0ZWRMaW5lKSB7XG4gICAgICAgIHByZXZpb3VzR2VuZXJhdGVkQ29sdW1uID0gMDtcbiAgICAgICAgd2hpbGUgKG1hcHBpbmcuZ2VuZXJhdGVkTGluZSAhPT0gcHJldmlvdXNHZW5lcmF0ZWRMaW5lKSB7XG4gICAgICAgICAgbmV4dCArPSAnOyc7XG4gICAgICAgICAgcHJldmlvdXNHZW5lcmF0ZWRMaW5lKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBpZiAoaSA+IDApIHtcbiAgICAgICAgICBpZiAoIXV0aWwuY29tcGFyZUJ5R2VuZXJhdGVkUG9zaXRpb25zSW5mbGF0ZWQobWFwcGluZywgbWFwcGluZ3NbaSAtIDFdKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIG5leHQgKz0gJywnO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG5leHQgKz0gYmFzZTY0VkxRLmVuY29kZShtYXBwaW5nLmdlbmVyYXRlZENvbHVtblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLSBwcmV2aW91c0dlbmVyYXRlZENvbHVtbik7XG4gICAgICBwcmV2aW91c0dlbmVyYXRlZENvbHVtbiA9IG1hcHBpbmcuZ2VuZXJhdGVkQ29sdW1uO1xuXG4gICAgICBpZiAobWFwcGluZy5zb3VyY2UgIT0gbnVsbCkge1xuICAgICAgICBzb3VyY2VJZHggPSB0aGlzLl9zb3VyY2VzLmluZGV4T2YobWFwcGluZy5zb3VyY2UpO1xuICAgICAgICBuZXh0ICs9IGJhc2U2NFZMUS5lbmNvZGUoc291cmNlSWR4IC0gcHJldmlvdXNTb3VyY2UpO1xuICAgICAgICBwcmV2aW91c1NvdXJjZSA9IHNvdXJjZUlkeDtcblxuICAgICAgICAvLyBsaW5lcyBhcmUgc3RvcmVkIDAtYmFzZWQgaW4gU291cmNlTWFwIHNwZWMgdmVyc2lvbiAzXG4gICAgICAgIG5leHQgKz0gYmFzZTY0VkxRLmVuY29kZShtYXBwaW5nLm9yaWdpbmFsTGluZSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLSBwcmV2aW91c09yaWdpbmFsTGluZSk7XG4gICAgICAgIHByZXZpb3VzT3JpZ2luYWxMaW5lID0gbWFwcGluZy5vcmlnaW5hbExpbmUgLSAxO1xuXG4gICAgICAgIG5leHQgKz0gYmFzZTY0VkxRLmVuY29kZShtYXBwaW5nLm9yaWdpbmFsQ29sdW1uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0gcHJldmlvdXNPcmlnaW5hbENvbHVtbik7XG4gICAgICAgIHByZXZpb3VzT3JpZ2luYWxDb2x1bW4gPSBtYXBwaW5nLm9yaWdpbmFsQ29sdW1uO1xuXG4gICAgICAgIGlmIChtYXBwaW5nLm5hbWUgIT0gbnVsbCkge1xuICAgICAgICAgIG5hbWVJZHggPSB0aGlzLl9uYW1lcy5pbmRleE9mKG1hcHBpbmcubmFtZSk7XG4gICAgICAgICAgbmV4dCArPSBiYXNlNjRWTFEuZW5jb2RlKG5hbWVJZHggLSBwcmV2aW91c05hbWUpO1xuICAgICAgICAgIHByZXZpb3VzTmFtZSA9IG5hbWVJZHg7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVzdWx0ICs9IG5leHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuU291cmNlTWFwR2VuZXJhdG9yLnByb3RvdHlwZS5fZ2VuZXJhdGVTb3VyY2VzQ29udGVudCA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcEdlbmVyYXRvcl9nZW5lcmF0ZVNvdXJjZXNDb250ZW50KGFTb3VyY2VzLCBhU291cmNlUm9vdCkge1xuICAgIHJldHVybiBhU291cmNlcy5tYXAoZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgICAgaWYgKCF0aGlzLl9zb3VyY2VzQ29udGVudHMpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBpZiAoYVNvdXJjZVJvb3QgIT0gbnVsbCkge1xuICAgICAgICBzb3VyY2UgPSB1dGlsLnJlbGF0aXZlKGFTb3VyY2VSb290LCBzb3VyY2UpO1xuICAgICAgfVxuICAgICAgdmFyIGtleSA9IHV0aWwudG9TZXRTdHJpbmcoc291cmNlKTtcbiAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcy5fc291cmNlc0NvbnRlbnRzLCBrZXkpXG4gICAgICAgID8gdGhpcy5fc291cmNlc0NvbnRlbnRzW2tleV1cbiAgICAgICAgOiBudWxsO1xuICAgIH0sIHRoaXMpO1xuICB9O1xuXG4vKipcbiAqIEV4dGVybmFsaXplIHRoZSBzb3VyY2UgbWFwLlxuICovXG5Tb3VyY2VNYXBHZW5lcmF0b3IucHJvdG90eXBlLnRvSlNPTiA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcEdlbmVyYXRvcl90b0pTT04oKSB7XG4gICAgdmFyIG1hcCA9IHtcbiAgICAgIHZlcnNpb246IHRoaXMuX3ZlcnNpb24sXG4gICAgICBzb3VyY2VzOiB0aGlzLl9zb3VyY2VzLnRvQXJyYXkoKSxcbiAgICAgIG5hbWVzOiB0aGlzLl9uYW1lcy50b0FycmF5KCksXG4gICAgICBtYXBwaW5nczogdGhpcy5fc2VyaWFsaXplTWFwcGluZ3MoKVxuICAgIH07XG4gICAgaWYgKHRoaXMuX2ZpbGUgIT0gbnVsbCkge1xuICAgICAgbWFwLmZpbGUgPSB0aGlzLl9maWxlO1xuICAgIH1cbiAgICBpZiAodGhpcy5fc291cmNlUm9vdCAhPSBudWxsKSB7XG4gICAgICBtYXAuc291cmNlUm9vdCA9IHRoaXMuX3NvdXJjZVJvb3Q7XG4gICAgfVxuICAgIGlmICh0aGlzLl9zb3VyY2VzQ29udGVudHMpIHtcbiAgICAgIG1hcC5zb3VyY2VzQ29udGVudCA9IHRoaXMuX2dlbmVyYXRlU291cmNlc0NvbnRlbnQobWFwLnNvdXJjZXMsIG1hcC5zb3VyY2VSb290KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWFwO1xuICB9O1xuXG4vKipcbiAqIFJlbmRlciB0aGUgc291cmNlIG1hcCBiZWluZyBnZW5lcmF0ZWQgdG8gYSBzdHJpbmcuXG4gKi9cblNvdXJjZU1hcEdlbmVyYXRvci5wcm90b3R5cGUudG9TdHJpbmcgPVxuICBmdW5jdGlvbiBTb3VyY2VNYXBHZW5lcmF0b3JfdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMudG9KU09OKCkpO1xuICB9O1xuXG5leHBvcnRzLlNvdXJjZU1hcEdlbmVyYXRvciA9IFNvdXJjZU1hcEdlbmVyYXRvcjtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbGliL3NvdXJjZS1tYXAtZ2VuZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIC0qLSBNb2RlOiBqczsganMtaW5kZW50LWxldmVsOiAyOyAtKi0gKi9cbi8qXG4gKiBDb3B5cmlnaHQgMjAxMSBNb3ppbGxhIEZvdW5kYXRpb24gYW5kIGNvbnRyaWJ1dG9yc1xuICogTGljZW5zZWQgdW5kZXIgdGhlIE5ldyBCU0QgbGljZW5zZS4gU2VlIExJQ0VOU0Ugb3I6XG4gKiBodHRwOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvQlNELTMtQ2xhdXNlXG4gKlxuICogQmFzZWQgb24gdGhlIEJhc2UgNjQgVkxRIGltcGxlbWVudGF0aW9uIGluIENsb3N1cmUgQ29tcGlsZXI6XG4gKiBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nsb3N1cmUtY29tcGlsZXIvc291cmNlL2Jyb3dzZS90cnVuay9zcmMvY29tL2dvb2dsZS9kZWJ1Z2dpbmcvc291cmNlbWFwL0Jhc2U2NFZMUS5qYXZhXG4gKlxuICogQ29weXJpZ2h0IDIwMTEgVGhlIENsb3N1cmUgQ29tcGlsZXIgQXV0aG9ycy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dFxuICogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZVxuICogbWV0OlxuICpcbiAqICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0XG4gKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gKiAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlXG4gKiAgICBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZ1xuICogICAgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkXG4gKiAgICB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKiAgKiBOZWl0aGVyIHRoZSBuYW1lIG9mIEdvb2dsZSBJbmMuIG5vciB0aGUgbmFtZXMgb2YgaXRzXG4gKiAgICBjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWRcbiAqICAgIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0IHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi5cbiAqXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTXG4gKiBcIkFTIElTXCIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UXG4gKiBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1JcbiAqIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUXG4gKiBPV05FUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCxcbiAqIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1RcbiAqIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLFxuICogREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZXG4gKiBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0VcbiAqIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKi9cblxudmFyIGJhc2U2NCA9IHJlcXVpcmUoJy4vYmFzZTY0Jyk7XG5cbi8vIEEgc2luZ2xlIGJhc2UgNjQgZGlnaXQgY2FuIGNvbnRhaW4gNiBiaXRzIG9mIGRhdGEuIEZvciB0aGUgYmFzZSA2NCB2YXJpYWJsZVxuLy8gbGVuZ3RoIHF1YW50aXRpZXMgd2UgdXNlIGluIHRoZSBzb3VyY2UgbWFwIHNwZWMsIHRoZSBmaXJzdCBiaXQgaXMgdGhlIHNpZ24sXG4vLyB0aGUgbmV4dCBmb3VyIGJpdHMgYXJlIHRoZSBhY3R1YWwgdmFsdWUsIGFuZCB0aGUgNnRoIGJpdCBpcyB0aGVcbi8vIGNvbnRpbnVhdGlvbiBiaXQuIFRoZSBjb250aW51YXRpb24gYml0IHRlbGxzIHVzIHdoZXRoZXIgdGhlcmUgYXJlIG1vcmVcbi8vIGRpZ2l0cyBpbiB0aGlzIHZhbHVlIGZvbGxvd2luZyB0aGlzIGRpZ2l0LlxuLy9cbi8vICAgQ29udGludWF0aW9uXG4vLyAgIHwgICAgU2lnblxuLy8gICB8ICAgIHxcbi8vICAgViAgICBWXG4vLyAgIDEwMTAxMVxuXG52YXIgVkxRX0JBU0VfU0hJRlQgPSA1O1xuXG4vLyBiaW5hcnk6IDEwMDAwMFxudmFyIFZMUV9CQVNFID0gMSA8PCBWTFFfQkFTRV9TSElGVDtcblxuLy8gYmluYXJ5OiAwMTExMTFcbnZhciBWTFFfQkFTRV9NQVNLID0gVkxRX0JBU0UgLSAxO1xuXG4vLyBiaW5hcnk6IDEwMDAwMFxudmFyIFZMUV9DT05USU5VQVRJT05fQklUID0gVkxRX0JBU0U7XG5cbi8qKlxuICogQ29udmVydHMgZnJvbSBhIHR3by1jb21wbGVtZW50IHZhbHVlIHRvIGEgdmFsdWUgd2hlcmUgdGhlIHNpZ24gYml0IGlzXG4gKiBwbGFjZWQgaW4gdGhlIGxlYXN0IHNpZ25pZmljYW50IGJpdC4gIEZvciBleGFtcGxlLCBhcyBkZWNpbWFsczpcbiAqICAgMSBiZWNvbWVzIDIgKDEwIGJpbmFyeSksIC0xIGJlY29tZXMgMyAoMTEgYmluYXJ5KVxuICogICAyIGJlY29tZXMgNCAoMTAwIGJpbmFyeSksIC0yIGJlY29tZXMgNSAoMTAxIGJpbmFyeSlcbiAqL1xuZnVuY3Rpb24gdG9WTFFTaWduZWQoYVZhbHVlKSB7XG4gIHJldHVybiBhVmFsdWUgPCAwXG4gICAgPyAoKC1hVmFsdWUpIDw8IDEpICsgMVxuICAgIDogKGFWYWx1ZSA8PCAxKSArIDA7XG59XG5cbi8qKlxuICogQ29udmVydHMgdG8gYSB0d28tY29tcGxlbWVudCB2YWx1ZSBmcm9tIGEgdmFsdWUgd2hlcmUgdGhlIHNpZ24gYml0IGlzXG4gKiBwbGFjZWQgaW4gdGhlIGxlYXN0IHNpZ25pZmljYW50IGJpdC4gIEZvciBleGFtcGxlLCBhcyBkZWNpbWFsczpcbiAqICAgMiAoMTAgYmluYXJ5KSBiZWNvbWVzIDEsIDMgKDExIGJpbmFyeSkgYmVjb21lcyAtMVxuICogICA0ICgxMDAgYmluYXJ5KSBiZWNvbWVzIDIsIDUgKDEwMSBiaW5hcnkpIGJlY29tZXMgLTJcbiAqL1xuZnVuY3Rpb24gZnJvbVZMUVNpZ25lZChhVmFsdWUpIHtcbiAgdmFyIGlzTmVnYXRpdmUgPSAoYVZhbHVlICYgMSkgPT09IDE7XG4gIHZhciBzaGlmdGVkID0gYVZhbHVlID4+IDE7XG4gIHJldHVybiBpc05lZ2F0aXZlXG4gICAgPyAtc2hpZnRlZFxuICAgIDogc2hpZnRlZDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBiYXNlIDY0IFZMUSBlbmNvZGVkIHZhbHVlLlxuICovXG5leHBvcnRzLmVuY29kZSA9IGZ1bmN0aW9uIGJhc2U2NFZMUV9lbmNvZGUoYVZhbHVlKSB7XG4gIHZhciBlbmNvZGVkID0gXCJcIjtcbiAgdmFyIGRpZ2l0O1xuXG4gIHZhciB2bHEgPSB0b1ZMUVNpZ25lZChhVmFsdWUpO1xuXG4gIGRvIHtcbiAgICBkaWdpdCA9IHZscSAmIFZMUV9CQVNFX01BU0s7XG4gICAgdmxxID4+Pj0gVkxRX0JBU0VfU0hJRlQ7XG4gICAgaWYgKHZscSA+IDApIHtcbiAgICAgIC8vIFRoZXJlIGFyZSBzdGlsbCBtb3JlIGRpZ2l0cyBpbiB0aGlzIHZhbHVlLCBzbyB3ZSBtdXN0IG1ha2Ugc3VyZSB0aGVcbiAgICAgIC8vIGNvbnRpbnVhdGlvbiBiaXQgaXMgbWFya2VkLlxuICAgICAgZGlnaXQgfD0gVkxRX0NPTlRJTlVBVElPTl9CSVQ7XG4gICAgfVxuICAgIGVuY29kZWQgKz0gYmFzZTY0LmVuY29kZShkaWdpdCk7XG4gIH0gd2hpbGUgKHZscSA+IDApO1xuXG4gIHJldHVybiBlbmNvZGVkO1xufTtcblxuLyoqXG4gKiBEZWNvZGVzIHRoZSBuZXh0IGJhc2UgNjQgVkxRIHZhbHVlIGZyb20gdGhlIGdpdmVuIHN0cmluZyBhbmQgcmV0dXJucyB0aGVcbiAqIHZhbHVlIGFuZCB0aGUgcmVzdCBvZiB0aGUgc3RyaW5nIHZpYSB0aGUgb3V0IHBhcmFtZXRlci5cbiAqL1xuZXhwb3J0cy5kZWNvZGUgPSBmdW5jdGlvbiBiYXNlNjRWTFFfZGVjb2RlKGFTdHIsIGFJbmRleCwgYU91dFBhcmFtKSB7XG4gIHZhciBzdHJMZW4gPSBhU3RyLmxlbmd0aDtcbiAgdmFyIHJlc3VsdCA9IDA7XG4gIHZhciBzaGlmdCA9IDA7XG4gIHZhciBjb250aW51YXRpb24sIGRpZ2l0O1xuXG4gIGRvIHtcbiAgICBpZiAoYUluZGV4ID49IHN0ckxlbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRXhwZWN0ZWQgbW9yZSBkaWdpdHMgaW4gYmFzZSA2NCBWTFEgdmFsdWUuXCIpO1xuICAgIH1cblxuICAgIGRpZ2l0ID0gYmFzZTY0LmRlY29kZShhU3RyLmNoYXJDb2RlQXQoYUluZGV4KyspKTtcbiAgICBpZiAoZGlnaXQgPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGJhc2U2NCBkaWdpdDogXCIgKyBhU3RyLmNoYXJBdChhSW5kZXggLSAxKSk7XG4gICAgfVxuXG4gICAgY29udGludWF0aW9uID0gISEoZGlnaXQgJiBWTFFfQ09OVElOVUFUSU9OX0JJVCk7XG4gICAgZGlnaXQgJj0gVkxRX0JBU0VfTUFTSztcbiAgICByZXN1bHQgPSByZXN1bHQgKyAoZGlnaXQgPDwgc2hpZnQpO1xuICAgIHNoaWZ0ICs9IFZMUV9CQVNFX1NISUZUO1xuICB9IHdoaWxlIChjb250aW51YXRpb24pO1xuXG4gIGFPdXRQYXJhbS52YWx1ZSA9IGZyb21WTFFTaWduZWQocmVzdWx0KTtcbiAgYU91dFBhcmFtLnJlc3QgPSBhSW5kZXg7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvYmFzZTY0LXZscS5qc1xuLy8gbW9kdWxlIGlkID0gMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiAtKi0gTW9kZToganM7IGpzLWluZGVudC1sZXZlbDogMjsgLSotICovXG4vKlxuICogQ29weXJpZ2h0IDIwMTEgTW96aWxsYSBGb3VuZGF0aW9uIGFuZCBjb250cmlidXRvcnNcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBOZXcgQlNEIGxpY2Vuc2UuIFNlZSBMSUNFTlNFIG9yOlxuICogaHR0cDovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL0JTRC0zLUNsYXVzZVxuICovXG5cbnZhciBpbnRUb0NoYXJNYXAgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLycuc3BsaXQoJycpO1xuXG4vKipcbiAqIEVuY29kZSBhbiBpbnRlZ2VyIGluIHRoZSByYW5nZSBvZiAwIHRvIDYzIHRvIGEgc2luZ2xlIGJhc2UgNjQgZGlnaXQuXG4gKi9cbmV4cG9ydHMuZW5jb2RlID0gZnVuY3Rpb24gKG51bWJlcikge1xuICBpZiAoMCA8PSBudW1iZXIgJiYgbnVtYmVyIDwgaW50VG9DaGFyTWFwLmxlbmd0aCkge1xuICAgIHJldHVybiBpbnRUb0NoYXJNYXBbbnVtYmVyXTtcbiAgfVxuICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDYzOiBcIiArIG51bWJlcik7XG59O1xuXG4vKipcbiAqIERlY29kZSBhIHNpbmdsZSBiYXNlIDY0IGNoYXJhY3RlciBjb2RlIGRpZ2l0IHRvIGFuIGludGVnZXIuIFJldHVybnMgLTEgb25cbiAqIGZhaWx1cmUuXG4gKi9cbmV4cG9ydHMuZGVjb2RlID0gZnVuY3Rpb24gKGNoYXJDb2RlKSB7XG4gIHZhciBiaWdBID0gNjU7ICAgICAvLyAnQSdcbiAgdmFyIGJpZ1ogPSA5MDsgICAgIC8vICdaJ1xuXG4gIHZhciBsaXR0bGVBID0gOTc7ICAvLyAnYSdcbiAgdmFyIGxpdHRsZVogPSAxMjI7IC8vICd6J1xuXG4gIHZhciB6ZXJvID0gNDg7ICAgICAvLyAnMCdcbiAgdmFyIG5pbmUgPSA1NzsgICAgIC8vICc5J1xuXG4gIHZhciBwbHVzID0gNDM7ICAgICAvLyAnKydcbiAgdmFyIHNsYXNoID0gNDc7ICAgIC8vICcvJ1xuXG4gIHZhciBsaXR0bGVPZmZzZXQgPSAyNjtcbiAgdmFyIG51bWJlck9mZnNldCA9IDUyO1xuXG4gIC8vIDAgLSAyNTogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpcbiAgaWYgKGJpZ0EgPD0gY2hhckNvZGUgJiYgY2hhckNvZGUgPD0gYmlnWikge1xuICAgIHJldHVybiAoY2hhckNvZGUgLSBiaWdBKTtcbiAgfVxuXG4gIC8vIDI2IC0gNTE6IGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XG4gIGlmIChsaXR0bGVBIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IGxpdHRsZVopIHtcbiAgICByZXR1cm4gKGNoYXJDb2RlIC0gbGl0dGxlQSArIGxpdHRsZU9mZnNldCk7XG4gIH1cblxuICAvLyA1MiAtIDYxOiAwMTIzNDU2Nzg5XG4gIGlmICh6ZXJvIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IG5pbmUpIHtcbiAgICByZXR1cm4gKGNoYXJDb2RlIC0gemVybyArIG51bWJlck9mZnNldCk7XG4gIH1cblxuICAvLyA2MjogK1xuICBpZiAoY2hhckNvZGUgPT0gcGx1cykge1xuICAgIHJldHVybiA2MjtcbiAgfVxuXG4gIC8vIDYzOiAvXG4gIGlmIChjaGFyQ29kZSA9PSBzbGFzaCkge1xuICAgIHJldHVybiA2MztcbiAgfVxuXG4gIC8vIEludmFsaWQgYmFzZTY0IGRpZ2l0LlxuICByZXR1cm4gLTE7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvYmFzZTY0LmpzXG4vLyBtb2R1bGUgaWQgPSAzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIC0qLSBNb2RlOiBqczsganMtaW5kZW50LWxldmVsOiAyOyAtKi0gKi9cbi8qXG4gKiBDb3B5cmlnaHQgMjAxMSBNb3ppbGxhIEZvdW5kYXRpb24gYW5kIGNvbnRyaWJ1dG9yc1xuICogTGljZW5zZWQgdW5kZXIgdGhlIE5ldyBCU0QgbGljZW5zZS4gU2VlIExJQ0VOU0Ugb3I6XG4gKiBodHRwOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvQlNELTMtQ2xhdXNlXG4gKi9cblxuLyoqXG4gKiBUaGlzIGlzIGEgaGVscGVyIGZ1bmN0aW9uIGZvciBnZXR0aW5nIHZhbHVlcyBmcm9tIHBhcmFtZXRlci9vcHRpb25zXG4gKiBvYmplY3RzLlxuICpcbiAqIEBwYXJhbSBhcmdzIFRoZSBvYmplY3Qgd2UgYXJlIGV4dHJhY3RpbmcgdmFsdWVzIGZyb21cbiAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB3ZSBhcmUgZ2V0dGluZy5cbiAqIEBwYXJhbSBkZWZhdWx0VmFsdWUgQW4gb3B0aW9uYWwgdmFsdWUgdG8gcmV0dXJuIGlmIHRoZSBwcm9wZXJ0eSBpcyBtaXNzaW5nXG4gKiBmcm9tIHRoZSBvYmplY3QuIElmIHRoaXMgaXMgbm90IHNwZWNpZmllZCBhbmQgdGhlIHByb3BlcnR5IGlzIG1pc3NpbmcsIGFuXG4gKiBlcnJvciB3aWxsIGJlIHRocm93bi5cbiAqL1xuZnVuY3Rpb24gZ2V0QXJnKGFBcmdzLCBhTmFtZSwgYURlZmF1bHRWYWx1ZSkge1xuICBpZiAoYU5hbWUgaW4gYUFyZ3MpIHtcbiAgICByZXR1cm4gYUFyZ3NbYU5hbWVdO1xuICB9IGVsc2UgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpIHtcbiAgICByZXR1cm4gYURlZmF1bHRWYWx1ZTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1wiJyArIGFOYW1lICsgJ1wiIGlzIGEgcmVxdWlyZWQgYXJndW1lbnQuJyk7XG4gIH1cbn1cbmV4cG9ydHMuZ2V0QXJnID0gZ2V0QXJnO1xuXG52YXIgdXJsUmVnZXhwID0gL14oPzooW1xcdytcXC0uXSspOik/XFwvXFwvKD86KFxcdys6XFx3KylAKT8oW1xcdy5dKikoPzo6KFxcZCspKT8oXFxTKikkLztcbnZhciBkYXRhVXJsUmVnZXhwID0gL15kYXRhOi4rXFwsLiskLztcblxuZnVuY3Rpb24gdXJsUGFyc2UoYVVybCkge1xuICB2YXIgbWF0Y2ggPSBhVXJsLm1hdGNoKHVybFJlZ2V4cCk7XG4gIGlmICghbWF0Y2gpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4ge1xuICAgIHNjaGVtZTogbWF0Y2hbMV0sXG4gICAgYXV0aDogbWF0Y2hbMl0sXG4gICAgaG9zdDogbWF0Y2hbM10sXG4gICAgcG9ydDogbWF0Y2hbNF0sXG4gICAgcGF0aDogbWF0Y2hbNV1cbiAgfTtcbn1cbmV4cG9ydHMudXJsUGFyc2UgPSB1cmxQYXJzZTtcblxuZnVuY3Rpb24gdXJsR2VuZXJhdGUoYVBhcnNlZFVybCkge1xuICB2YXIgdXJsID0gJyc7XG4gIGlmIChhUGFyc2VkVXJsLnNjaGVtZSkge1xuICAgIHVybCArPSBhUGFyc2VkVXJsLnNjaGVtZSArICc6JztcbiAgfVxuICB1cmwgKz0gJy8vJztcbiAgaWYgKGFQYXJzZWRVcmwuYXV0aCkge1xuICAgIHVybCArPSBhUGFyc2VkVXJsLmF1dGggKyAnQCc7XG4gIH1cbiAgaWYgKGFQYXJzZWRVcmwuaG9zdCkge1xuICAgIHVybCArPSBhUGFyc2VkVXJsLmhvc3Q7XG4gIH1cbiAgaWYgKGFQYXJzZWRVcmwucG9ydCkge1xuICAgIHVybCArPSBcIjpcIiArIGFQYXJzZWRVcmwucG9ydFxuICB9XG4gIGlmIChhUGFyc2VkVXJsLnBhdGgpIHtcbiAgICB1cmwgKz0gYVBhcnNlZFVybC5wYXRoO1xuICB9XG4gIHJldHVybiB1cmw7XG59XG5leHBvcnRzLnVybEdlbmVyYXRlID0gdXJsR2VuZXJhdGU7XG5cbi8qKlxuICogTm9ybWFsaXplcyBhIHBhdGgsIG9yIHRoZSBwYXRoIHBvcnRpb24gb2YgYSBVUkw6XG4gKlxuICogLSBSZXBsYWNlcyBjb25zZWN1dGl2ZSBzbGFzaGVzIHdpdGggb25lIHNsYXNoLlxuICogLSBSZW1vdmVzIHVubmVjZXNzYXJ5ICcuJyBwYXJ0cy5cbiAqIC0gUmVtb3ZlcyB1bm5lY2Vzc2FyeSAnPGRpcj4vLi4nIHBhcnRzLlxuICpcbiAqIEJhc2VkIG9uIGNvZGUgaW4gdGhlIE5vZGUuanMgJ3BhdGgnIGNvcmUgbW9kdWxlLlxuICpcbiAqIEBwYXJhbSBhUGF0aCBUaGUgcGF0aCBvciB1cmwgdG8gbm9ybWFsaXplLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemUoYVBhdGgpIHtcbiAgdmFyIHBhdGggPSBhUGF0aDtcbiAgdmFyIHVybCA9IHVybFBhcnNlKGFQYXRoKTtcbiAgaWYgKHVybCkge1xuICAgIGlmICghdXJsLnBhdGgpIHtcbiAgICAgIHJldHVybiBhUGF0aDtcbiAgICB9XG4gICAgcGF0aCA9IHVybC5wYXRoO1xuICB9XG4gIHZhciBpc0Fic29sdXRlID0gZXhwb3J0cy5pc0Fic29sdXRlKHBhdGgpO1xuXG4gIHZhciBwYXJ0cyA9IHBhdGguc3BsaXQoL1xcLysvKTtcbiAgZm9yICh2YXIgcGFydCwgdXAgPSAwLCBpID0gcGFydHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBwYXJ0ID0gcGFydHNbaV07XG4gICAgaWYgKHBhcnQgPT09ICcuJykge1xuICAgICAgcGFydHMuc3BsaWNlKGksIDEpO1xuICAgIH0gZWxzZSBpZiAocGFydCA9PT0gJy4uJykge1xuICAgICAgdXArKztcbiAgICB9IGVsc2UgaWYgKHVwID4gMCkge1xuICAgICAgaWYgKHBhcnQgPT09ICcnKSB7XG4gICAgICAgIC8vIFRoZSBmaXJzdCBwYXJ0IGlzIGJsYW5rIGlmIHRoZSBwYXRoIGlzIGFic29sdXRlLiBUcnlpbmcgdG8gZ29cbiAgICAgICAgLy8gYWJvdmUgdGhlIHJvb3QgaXMgYSBuby1vcC4gVGhlcmVmb3JlIHdlIGNhbiByZW1vdmUgYWxsICcuLicgcGFydHNcbiAgICAgICAgLy8gZGlyZWN0bHkgYWZ0ZXIgdGhlIHJvb3QuXG4gICAgICAgIHBhcnRzLnNwbGljZShpICsgMSwgdXApO1xuICAgICAgICB1cCA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXJ0cy5zcGxpY2UoaSwgMik7XG4gICAgICAgIHVwLS07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHBhdGggPSBwYXJ0cy5qb2luKCcvJyk7XG5cbiAgaWYgKHBhdGggPT09ICcnKSB7XG4gICAgcGF0aCA9IGlzQWJzb2x1dGUgPyAnLycgOiAnLic7XG4gIH1cblxuICBpZiAodXJsKSB7XG4gICAgdXJsLnBhdGggPSBwYXRoO1xuICAgIHJldHVybiB1cmxHZW5lcmF0ZSh1cmwpO1xuICB9XG4gIHJldHVybiBwYXRoO1xufVxuZXhwb3J0cy5ub3JtYWxpemUgPSBub3JtYWxpemU7XG5cbi8qKlxuICogSm9pbnMgdHdvIHBhdGhzL1VSTHMuXG4gKlxuICogQHBhcmFtIGFSb290IFRoZSByb290IHBhdGggb3IgVVJMLlxuICogQHBhcmFtIGFQYXRoIFRoZSBwYXRoIG9yIFVSTCB0byBiZSBqb2luZWQgd2l0aCB0aGUgcm9vdC5cbiAqXG4gKiAtIElmIGFQYXRoIGlzIGEgVVJMIG9yIGEgZGF0YSBVUkksIGFQYXRoIGlzIHJldHVybmVkLCB1bmxlc3MgYVBhdGggaXMgYVxuICogICBzY2hlbWUtcmVsYXRpdmUgVVJMOiBUaGVuIHRoZSBzY2hlbWUgb2YgYVJvb3QsIGlmIGFueSwgaXMgcHJlcGVuZGVkXG4gKiAgIGZpcnN0LlxuICogLSBPdGhlcndpc2UgYVBhdGggaXMgYSBwYXRoLiBJZiBhUm9vdCBpcyBhIFVSTCwgdGhlbiBpdHMgcGF0aCBwb3J0aW9uXG4gKiAgIGlzIHVwZGF0ZWQgd2l0aCB0aGUgcmVzdWx0IGFuZCBhUm9vdCBpcyByZXR1cm5lZC4gT3RoZXJ3aXNlIHRoZSByZXN1bHRcbiAqICAgaXMgcmV0dXJuZWQuXG4gKiAgIC0gSWYgYVBhdGggaXMgYWJzb2x1dGUsIHRoZSByZXN1bHQgaXMgYVBhdGguXG4gKiAgIC0gT3RoZXJ3aXNlIHRoZSB0d28gcGF0aHMgYXJlIGpvaW5lZCB3aXRoIGEgc2xhc2guXG4gKiAtIEpvaW5pbmcgZm9yIGV4YW1wbGUgJ2h0dHA6Ly8nIGFuZCAnd3d3LmV4YW1wbGUuY29tJyBpcyBhbHNvIHN1cHBvcnRlZC5cbiAqL1xuZnVuY3Rpb24gam9pbihhUm9vdCwgYVBhdGgpIHtcbiAgaWYgKGFSb290ID09PSBcIlwiKSB7XG4gICAgYVJvb3QgPSBcIi5cIjtcbiAgfVxuICBpZiAoYVBhdGggPT09IFwiXCIpIHtcbiAgICBhUGF0aCA9IFwiLlwiO1xuICB9XG4gIHZhciBhUGF0aFVybCA9IHVybFBhcnNlKGFQYXRoKTtcbiAgdmFyIGFSb290VXJsID0gdXJsUGFyc2UoYVJvb3QpO1xuICBpZiAoYVJvb3RVcmwpIHtcbiAgICBhUm9vdCA9IGFSb290VXJsLnBhdGggfHwgJy8nO1xuICB9XG5cbiAgLy8gYGpvaW4oZm9vLCAnLy93d3cuZXhhbXBsZS5vcmcnKWBcbiAgaWYgKGFQYXRoVXJsICYmICFhUGF0aFVybC5zY2hlbWUpIHtcbiAgICBpZiAoYVJvb3RVcmwpIHtcbiAgICAgIGFQYXRoVXJsLnNjaGVtZSA9IGFSb290VXJsLnNjaGVtZTtcbiAgICB9XG4gICAgcmV0dXJuIHVybEdlbmVyYXRlKGFQYXRoVXJsKTtcbiAgfVxuXG4gIGlmIChhUGF0aFVybCB8fCBhUGF0aC5tYXRjaChkYXRhVXJsUmVnZXhwKSkge1xuICAgIHJldHVybiBhUGF0aDtcbiAgfVxuXG4gIC8vIGBqb2luKCdodHRwOi8vJywgJ3d3dy5leGFtcGxlLmNvbScpYFxuICBpZiAoYVJvb3RVcmwgJiYgIWFSb290VXJsLmhvc3QgJiYgIWFSb290VXJsLnBhdGgpIHtcbiAgICBhUm9vdFVybC5ob3N0ID0gYVBhdGg7XG4gICAgcmV0dXJuIHVybEdlbmVyYXRlKGFSb290VXJsKTtcbiAgfVxuXG4gIHZhciBqb2luZWQgPSBhUGF0aC5jaGFyQXQoMCkgPT09ICcvJ1xuICAgID8gYVBhdGhcbiAgICA6IG5vcm1hbGl6ZShhUm9vdC5yZXBsYWNlKC9cXC8rJC8sICcnKSArICcvJyArIGFQYXRoKTtcblxuICBpZiAoYVJvb3RVcmwpIHtcbiAgICBhUm9vdFVybC5wYXRoID0gam9pbmVkO1xuICAgIHJldHVybiB1cmxHZW5lcmF0ZShhUm9vdFVybCk7XG4gIH1cbiAgcmV0dXJuIGpvaW5lZDtcbn1cbmV4cG9ydHMuam9pbiA9IGpvaW47XG5cbmV4cG9ydHMuaXNBYnNvbHV0ZSA9IGZ1bmN0aW9uIChhUGF0aCkge1xuICByZXR1cm4gYVBhdGguY2hhckF0KDApID09PSAnLycgfHwgISFhUGF0aC5tYXRjaCh1cmxSZWdleHApO1xufTtcblxuLyoqXG4gKiBNYWtlIGEgcGF0aCByZWxhdGl2ZSB0byBhIFVSTCBvciBhbm90aGVyIHBhdGguXG4gKlxuICogQHBhcmFtIGFSb290IFRoZSByb290IHBhdGggb3IgVVJMLlxuICogQHBhcmFtIGFQYXRoIFRoZSBwYXRoIG9yIFVSTCB0byBiZSBtYWRlIHJlbGF0aXZlIHRvIGFSb290LlxuICovXG5mdW5jdGlvbiByZWxhdGl2ZShhUm9vdCwgYVBhdGgpIHtcbiAgaWYgKGFSb290ID09PSBcIlwiKSB7XG4gICAgYVJvb3QgPSBcIi5cIjtcbiAgfVxuXG4gIGFSb290ID0gYVJvb3QucmVwbGFjZSgvXFwvJC8sICcnKTtcblxuICAvLyBJdCBpcyBwb3NzaWJsZSBmb3IgdGhlIHBhdGggdG8gYmUgYWJvdmUgdGhlIHJvb3QuIEluIHRoaXMgY2FzZSwgc2ltcGx5XG4gIC8vIGNoZWNraW5nIHdoZXRoZXIgdGhlIHJvb3QgaXMgYSBwcmVmaXggb2YgdGhlIHBhdGggd29uJ3Qgd29yay4gSW5zdGVhZCwgd2VcbiAgLy8gbmVlZCB0byByZW1vdmUgY29tcG9uZW50cyBmcm9tIHRoZSByb290IG9uZSBieSBvbmUsIHVudGlsIGVpdGhlciB3ZSBmaW5kXG4gIC8vIGEgcHJlZml4IHRoYXQgZml0cywgb3Igd2UgcnVuIG91dCBvZiBjb21wb25lbnRzIHRvIHJlbW92ZS5cbiAgdmFyIGxldmVsID0gMDtcbiAgd2hpbGUgKGFQYXRoLmluZGV4T2YoYVJvb3QgKyAnLycpICE9PSAwKSB7XG4gICAgdmFyIGluZGV4ID0gYVJvb3QubGFzdEluZGV4T2YoXCIvXCIpO1xuICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgIHJldHVybiBhUGF0aDtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGUgb25seSBwYXJ0IG9mIHRoZSByb290IHRoYXQgaXMgbGVmdCBpcyB0aGUgc2NoZW1lIChpLmUuIGh0dHA6Ly8sXG4gICAgLy8gZmlsZTovLy8sIGV0Yy4pLCBvbmUgb3IgbW9yZSBzbGFzaGVzICgvKSwgb3Igc2ltcGx5IG5vdGhpbmcgYXQgYWxsLCB3ZVxuICAgIC8vIGhhdmUgZXhoYXVzdGVkIGFsbCBjb21wb25lbnRzLCBzbyB0aGUgcGF0aCBpcyBub3QgcmVsYXRpdmUgdG8gdGhlIHJvb3QuXG4gICAgYVJvb3QgPSBhUm9vdC5zbGljZSgwLCBpbmRleCk7XG4gICAgaWYgKGFSb290Lm1hdGNoKC9eKFteXFwvXSs6XFwvKT9cXC8qJC8pKSB7XG4gICAgICByZXR1cm4gYVBhdGg7XG4gICAgfVxuXG4gICAgKytsZXZlbDtcbiAgfVxuXG4gIC8vIE1ha2Ugc3VyZSB3ZSBhZGQgYSBcIi4uL1wiIGZvciBlYWNoIGNvbXBvbmVudCB3ZSByZW1vdmVkIGZyb20gdGhlIHJvb3QuXG4gIHJldHVybiBBcnJheShsZXZlbCArIDEpLmpvaW4oXCIuLi9cIikgKyBhUGF0aC5zdWJzdHIoYVJvb3QubGVuZ3RoICsgMSk7XG59XG5leHBvcnRzLnJlbGF0aXZlID0gcmVsYXRpdmU7XG5cbnZhciBzdXBwb3J0c051bGxQcm90byA9IChmdW5jdGlvbiAoKSB7XG4gIHZhciBvYmogPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICByZXR1cm4gISgnX19wcm90b19fJyBpbiBvYmopO1xufSgpKTtcblxuZnVuY3Rpb24gaWRlbnRpdHkgKHMpIHtcbiAgcmV0dXJuIHM7XG59XG5cbi8qKlxuICogQmVjYXVzZSBiZWhhdmlvciBnb2VzIHdhY2t5IHdoZW4geW91IHNldCBgX19wcm90b19fYCBvbiBvYmplY3RzLCB3ZVxuICogaGF2ZSB0byBwcmVmaXggYWxsIHRoZSBzdHJpbmdzIGluIG91ciBzZXQgd2l0aCBhbiBhcmJpdHJhcnkgY2hhcmFjdGVyLlxuICpcbiAqIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbW96aWxsYS9zb3VyY2UtbWFwL3B1bGwvMzEgYW5kXG4gKiBodHRwczovL2dpdGh1Yi5jb20vbW96aWxsYS9zb3VyY2UtbWFwL2lzc3Vlcy8zMFxuICpcbiAqIEBwYXJhbSBTdHJpbmcgYVN0clxuICovXG5mdW5jdGlvbiB0b1NldFN0cmluZyhhU3RyKSB7XG4gIGlmIChpc1Byb3RvU3RyaW5nKGFTdHIpKSB7XG4gICAgcmV0dXJuICckJyArIGFTdHI7XG4gIH1cblxuICByZXR1cm4gYVN0cjtcbn1cbmV4cG9ydHMudG9TZXRTdHJpbmcgPSBzdXBwb3J0c051bGxQcm90byA/IGlkZW50aXR5IDogdG9TZXRTdHJpbmc7XG5cbmZ1bmN0aW9uIGZyb21TZXRTdHJpbmcoYVN0cikge1xuICBpZiAoaXNQcm90b1N0cmluZyhhU3RyKSkge1xuICAgIHJldHVybiBhU3RyLnNsaWNlKDEpO1xuICB9XG5cbiAgcmV0dXJuIGFTdHI7XG59XG5leHBvcnRzLmZyb21TZXRTdHJpbmcgPSBzdXBwb3J0c051bGxQcm90byA/IGlkZW50aXR5IDogZnJvbVNldFN0cmluZztcblxuZnVuY3Rpb24gaXNQcm90b1N0cmluZyhzKSB7XG4gIGlmICghcykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciBsZW5ndGggPSBzLmxlbmd0aDtcblxuICBpZiAobGVuZ3RoIDwgOSAvKiBcIl9fcHJvdG9fX1wiLmxlbmd0aCAqLykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChzLmNoYXJDb2RlQXQobGVuZ3RoIC0gMSkgIT09IDk1ICAvKiAnXycgKi8gfHxcbiAgICAgIHMuY2hhckNvZGVBdChsZW5ndGggLSAyKSAhPT0gOTUgIC8qICdfJyAqLyB8fFxuICAgICAgcy5jaGFyQ29kZUF0KGxlbmd0aCAtIDMpICE9PSAxMTEgLyogJ28nICovIHx8XG4gICAgICBzLmNoYXJDb2RlQXQobGVuZ3RoIC0gNCkgIT09IDExNiAvKiAndCcgKi8gfHxcbiAgICAgIHMuY2hhckNvZGVBdChsZW5ndGggLSA1KSAhPT0gMTExIC8qICdvJyAqLyB8fFxuICAgICAgcy5jaGFyQ29kZUF0KGxlbmd0aCAtIDYpICE9PSAxMTQgLyogJ3InICovIHx8XG4gICAgICBzLmNoYXJDb2RlQXQobGVuZ3RoIC0gNykgIT09IDExMiAvKiAncCcgKi8gfHxcbiAgICAgIHMuY2hhckNvZGVBdChsZW5ndGggLSA4KSAhPT0gOTUgIC8qICdfJyAqLyB8fFxuICAgICAgcy5jaGFyQ29kZUF0KGxlbmd0aCAtIDkpICE9PSA5NSAgLyogJ18nICovKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IGxlbmd0aCAtIDEwOyBpID49IDA7IGktLSkge1xuICAgIGlmIChzLmNoYXJDb2RlQXQoaSkgIT09IDM2IC8qICckJyAqLykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIENvbXBhcmF0b3IgYmV0d2VlbiB0d28gbWFwcGluZ3Mgd2hlcmUgdGhlIG9yaWdpbmFsIHBvc2l0aW9ucyBhcmUgY29tcGFyZWQuXG4gKlxuICogT3B0aW9uYWxseSBwYXNzIGluIGB0cnVlYCBhcyBgb25seUNvbXBhcmVHZW5lcmF0ZWRgIHRvIGNvbnNpZGVyIHR3b1xuICogbWFwcGluZ3Mgd2l0aCB0aGUgc2FtZSBvcmlnaW5hbCBzb3VyY2UvbGluZS9jb2x1bW4sIGJ1dCBkaWZmZXJlbnQgZ2VuZXJhdGVkXG4gKiBsaW5lIGFuZCBjb2x1bW4gdGhlIHNhbWUuIFVzZWZ1bCB3aGVuIHNlYXJjaGluZyBmb3IgYSBtYXBwaW5nIHdpdGggYVxuICogc3R1YmJlZCBvdXQgbWFwcGluZy5cbiAqL1xuZnVuY3Rpb24gY29tcGFyZUJ5T3JpZ2luYWxQb3NpdGlvbnMobWFwcGluZ0EsIG1hcHBpbmdCLCBvbmx5Q29tcGFyZU9yaWdpbmFsKSB7XG4gIHZhciBjbXAgPSBtYXBwaW5nQS5zb3VyY2UgLSBtYXBwaW5nQi5zb3VyY2U7XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgY21wID0gbWFwcGluZ0Eub3JpZ2luYWxMaW5lIC0gbWFwcGluZ0Iub3JpZ2luYWxMaW5lO1xuICBpZiAoY21wICE9PSAwKSB7XG4gICAgcmV0dXJuIGNtcDtcbiAgfVxuXG4gIGNtcCA9IG1hcHBpbmdBLm9yaWdpbmFsQ29sdW1uIC0gbWFwcGluZ0Iub3JpZ2luYWxDb2x1bW47XG4gIGlmIChjbXAgIT09IDAgfHwgb25seUNvbXBhcmVPcmlnaW5hbCkge1xuICAgIHJldHVybiBjbXA7XG4gIH1cblxuICBjbXAgPSBtYXBwaW5nQS5nZW5lcmF0ZWRDb2x1bW4gLSBtYXBwaW5nQi5nZW5lcmF0ZWRDb2x1bW47XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgY21wID0gbWFwcGluZ0EuZ2VuZXJhdGVkTGluZSAtIG1hcHBpbmdCLmdlbmVyYXRlZExpbmU7XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgcmV0dXJuIG1hcHBpbmdBLm5hbWUgLSBtYXBwaW5nQi5uYW1lO1xufVxuZXhwb3J0cy5jb21wYXJlQnlPcmlnaW5hbFBvc2l0aW9ucyA9IGNvbXBhcmVCeU9yaWdpbmFsUG9zaXRpb25zO1xuXG4vKipcbiAqIENvbXBhcmF0b3IgYmV0d2VlbiB0d28gbWFwcGluZ3Mgd2l0aCBkZWZsYXRlZCBzb3VyY2UgYW5kIG5hbWUgaW5kaWNlcyB3aGVyZVxuICogdGhlIGdlbmVyYXRlZCBwb3NpdGlvbnMgYXJlIGNvbXBhcmVkLlxuICpcbiAqIE9wdGlvbmFsbHkgcGFzcyBpbiBgdHJ1ZWAgYXMgYG9ubHlDb21wYXJlR2VuZXJhdGVkYCB0byBjb25zaWRlciB0d29cbiAqIG1hcHBpbmdzIHdpdGggdGhlIHNhbWUgZ2VuZXJhdGVkIGxpbmUgYW5kIGNvbHVtbiwgYnV0IGRpZmZlcmVudFxuICogc291cmNlL25hbWUvb3JpZ2luYWwgbGluZSBhbmQgY29sdW1uIHRoZSBzYW1lLiBVc2VmdWwgd2hlbiBzZWFyY2hpbmcgZm9yIGFcbiAqIG1hcHBpbmcgd2l0aCBhIHN0dWJiZWQgb3V0IG1hcHBpbmcuXG4gKi9cbmZ1bmN0aW9uIGNvbXBhcmVCeUdlbmVyYXRlZFBvc2l0aW9uc0RlZmxhdGVkKG1hcHBpbmdBLCBtYXBwaW5nQiwgb25seUNvbXBhcmVHZW5lcmF0ZWQpIHtcbiAgdmFyIGNtcCA9IG1hcHBpbmdBLmdlbmVyYXRlZExpbmUgLSBtYXBwaW5nQi5nZW5lcmF0ZWRMaW5lO1xuICBpZiAoY21wICE9PSAwKSB7XG4gICAgcmV0dXJuIGNtcDtcbiAgfVxuXG4gIGNtcCA9IG1hcHBpbmdBLmdlbmVyYXRlZENvbHVtbiAtIG1hcHBpbmdCLmdlbmVyYXRlZENvbHVtbjtcbiAgaWYgKGNtcCAhPT0gMCB8fCBvbmx5Q29tcGFyZUdlbmVyYXRlZCkge1xuICAgIHJldHVybiBjbXA7XG4gIH1cblxuICBjbXAgPSBtYXBwaW5nQS5zb3VyY2UgLSBtYXBwaW5nQi5zb3VyY2U7XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgY21wID0gbWFwcGluZ0Eub3JpZ2luYWxMaW5lIC0gbWFwcGluZ0Iub3JpZ2luYWxMaW5lO1xuICBpZiAoY21wICE9PSAwKSB7XG4gICAgcmV0dXJuIGNtcDtcbiAgfVxuXG4gIGNtcCA9IG1hcHBpbmdBLm9yaWdpbmFsQ29sdW1uIC0gbWFwcGluZ0Iub3JpZ2luYWxDb2x1bW47XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgcmV0dXJuIG1hcHBpbmdBLm5hbWUgLSBtYXBwaW5nQi5uYW1lO1xufVxuZXhwb3J0cy5jb21wYXJlQnlHZW5lcmF0ZWRQb3NpdGlvbnNEZWZsYXRlZCA9IGNvbXBhcmVCeUdlbmVyYXRlZFBvc2l0aW9uc0RlZmxhdGVkO1xuXG5mdW5jdGlvbiBzdHJjbXAoYVN0cjEsIGFTdHIyKSB7XG4gIGlmIChhU3RyMSA9PT0gYVN0cjIpIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIGlmIChhU3RyMSA+IGFTdHIyKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cblxuICByZXR1cm4gLTE7XG59XG5cbi8qKlxuICogQ29tcGFyYXRvciBiZXR3ZWVuIHR3byBtYXBwaW5ncyB3aXRoIGluZmxhdGVkIHNvdXJjZSBhbmQgbmFtZSBzdHJpbmdzIHdoZXJlXG4gKiB0aGUgZ2VuZXJhdGVkIHBvc2l0aW9ucyBhcmUgY29tcGFyZWQuXG4gKi9cbmZ1bmN0aW9uIGNvbXBhcmVCeUdlbmVyYXRlZFBvc2l0aW9uc0luZmxhdGVkKG1hcHBpbmdBLCBtYXBwaW5nQikge1xuICB2YXIgY21wID0gbWFwcGluZ0EuZ2VuZXJhdGVkTGluZSAtIG1hcHBpbmdCLmdlbmVyYXRlZExpbmU7XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgY21wID0gbWFwcGluZ0EuZ2VuZXJhdGVkQ29sdW1uIC0gbWFwcGluZ0IuZ2VuZXJhdGVkQ29sdW1uO1xuICBpZiAoY21wICE9PSAwKSB7XG4gICAgcmV0dXJuIGNtcDtcbiAgfVxuXG4gIGNtcCA9IHN0cmNtcChtYXBwaW5nQS5zb3VyY2UsIG1hcHBpbmdCLnNvdXJjZSk7XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgY21wID0gbWFwcGluZ0Eub3JpZ2luYWxMaW5lIC0gbWFwcGluZ0Iub3JpZ2luYWxMaW5lO1xuICBpZiAoY21wICE9PSAwKSB7XG4gICAgcmV0dXJuIGNtcDtcbiAgfVxuXG4gIGNtcCA9IG1hcHBpbmdBLm9yaWdpbmFsQ29sdW1uIC0gbWFwcGluZ0Iub3JpZ2luYWxDb2x1bW47XG4gIGlmIChjbXAgIT09IDApIHtcbiAgICByZXR1cm4gY21wO1xuICB9XG5cbiAgcmV0dXJuIHN0cmNtcChtYXBwaW5nQS5uYW1lLCBtYXBwaW5nQi5uYW1lKTtcbn1cbmV4cG9ydHMuY29tcGFyZUJ5R2VuZXJhdGVkUG9zaXRpb25zSW5mbGF0ZWQgPSBjb21wYXJlQnlHZW5lcmF0ZWRQb3NpdGlvbnNJbmZsYXRlZDtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbGliL3V0aWwuanNcbi8vIG1vZHVsZSBpZCA9IDRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogLSotIE1vZGU6IGpzOyBqcy1pbmRlbnQtbGV2ZWw6IDI7IC0qLSAqL1xuLypcbiAqIENvcHlyaWdodCAyMDExIE1vemlsbGEgRm91bmRhdGlvbiBhbmQgY29udHJpYnV0b3JzXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTmV3IEJTRCBsaWNlbnNlLiBTZWUgTElDRU5TRSBvcjpcbiAqIGh0dHA6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9CU0QtMy1DbGF1c2VcbiAqL1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xudmFyIGhhcyA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG52YXIgaGFzTmF0aXZlTWFwID0gdHlwZW9mIE1hcCAhPT0gXCJ1bmRlZmluZWRcIjtcblxuLyoqXG4gKiBBIGRhdGEgc3RydWN0dXJlIHdoaWNoIGlzIGEgY29tYmluYXRpb24gb2YgYW4gYXJyYXkgYW5kIGEgc2V0LiBBZGRpbmcgYSBuZXdcbiAqIG1lbWJlciBpcyBPKDEpLCB0ZXN0aW5nIGZvciBtZW1iZXJzaGlwIGlzIE8oMSksIGFuZCBmaW5kaW5nIHRoZSBpbmRleCBvZiBhblxuICogZWxlbWVudCBpcyBPKDEpLiBSZW1vdmluZyBlbGVtZW50cyBmcm9tIHRoZSBzZXQgaXMgbm90IHN1cHBvcnRlZC4gT25seVxuICogc3RyaW5ncyBhcmUgc3VwcG9ydGVkIGZvciBtZW1iZXJzaGlwLlxuICovXG5mdW5jdGlvbiBBcnJheVNldCgpIHtcbiAgdGhpcy5fYXJyYXkgPSBbXTtcbiAgdGhpcy5fc2V0ID0gaGFzTmF0aXZlTWFwID8gbmV3IE1hcCgpIDogT2JqZWN0LmNyZWF0ZShudWxsKTtcbn1cblxuLyoqXG4gKiBTdGF0aWMgbWV0aG9kIGZvciBjcmVhdGluZyBBcnJheVNldCBpbnN0YW5jZXMgZnJvbSBhbiBleGlzdGluZyBhcnJheS5cbiAqL1xuQXJyYXlTZXQuZnJvbUFycmF5ID0gZnVuY3Rpb24gQXJyYXlTZXRfZnJvbUFycmF5KGFBcnJheSwgYUFsbG93RHVwbGljYXRlcykge1xuICB2YXIgc2V0ID0gbmV3IEFycmF5U2V0KCk7XG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhQXJyYXkubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICBzZXQuYWRkKGFBcnJheVtpXSwgYUFsbG93RHVwbGljYXRlcyk7XG4gIH1cbiAgcmV0dXJuIHNldDtcbn07XG5cbi8qKlxuICogUmV0dXJuIGhvdyBtYW55IHVuaXF1ZSBpdGVtcyBhcmUgaW4gdGhpcyBBcnJheVNldC4gSWYgZHVwbGljYXRlcyBoYXZlIGJlZW5cbiAqIGFkZGVkLCB0aGFuIHRob3NlIGRvIG5vdCBjb3VudCB0b3dhcmRzIHRoZSBzaXplLlxuICpcbiAqIEByZXR1cm5zIE51bWJlclxuICovXG5BcnJheVNldC5wcm90b3R5cGUuc2l6ZSA9IGZ1bmN0aW9uIEFycmF5U2V0X3NpemUoKSB7XG4gIHJldHVybiBoYXNOYXRpdmVNYXAgPyB0aGlzLl9zZXQuc2l6ZSA6IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMuX3NldCkubGVuZ3RoO1xufTtcblxuLyoqXG4gKiBBZGQgdGhlIGdpdmVuIHN0cmluZyB0byB0aGlzIHNldC5cbiAqXG4gKiBAcGFyYW0gU3RyaW5nIGFTdHJcbiAqL1xuQXJyYXlTZXQucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIEFycmF5U2V0X2FkZChhU3RyLCBhQWxsb3dEdXBsaWNhdGVzKSB7XG4gIHZhciBzU3RyID0gaGFzTmF0aXZlTWFwID8gYVN0ciA6IHV0aWwudG9TZXRTdHJpbmcoYVN0cik7XG4gIHZhciBpc0R1cGxpY2F0ZSA9IGhhc05hdGl2ZU1hcCA/IHRoaXMuaGFzKGFTdHIpIDogaGFzLmNhbGwodGhpcy5fc2V0LCBzU3RyKTtcbiAgdmFyIGlkeCA9IHRoaXMuX2FycmF5Lmxlbmd0aDtcbiAgaWYgKCFpc0R1cGxpY2F0ZSB8fCBhQWxsb3dEdXBsaWNhdGVzKSB7XG4gICAgdGhpcy5fYXJyYXkucHVzaChhU3RyKTtcbiAgfVxuICBpZiAoIWlzRHVwbGljYXRlKSB7XG4gICAgaWYgKGhhc05hdGl2ZU1hcCkge1xuICAgICAgdGhpcy5fc2V0LnNldChhU3RyLCBpZHgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zZXRbc1N0cl0gPSBpZHg7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIElzIHRoZSBnaXZlbiBzdHJpbmcgYSBtZW1iZXIgb2YgdGhpcyBzZXQ/XG4gKlxuICogQHBhcmFtIFN0cmluZyBhU3RyXG4gKi9cbkFycmF5U2V0LnByb3RvdHlwZS5oYXMgPSBmdW5jdGlvbiBBcnJheVNldF9oYXMoYVN0cikge1xuICBpZiAoaGFzTmF0aXZlTWFwKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NldC5oYXMoYVN0cik7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHNTdHIgPSB1dGlsLnRvU2V0U3RyaW5nKGFTdHIpO1xuICAgIHJldHVybiBoYXMuY2FsbCh0aGlzLl9zZXQsIHNTdHIpO1xuICB9XG59O1xuXG4vKipcbiAqIFdoYXQgaXMgdGhlIGluZGV4IG9mIHRoZSBnaXZlbiBzdHJpbmcgaW4gdGhlIGFycmF5P1xuICpcbiAqIEBwYXJhbSBTdHJpbmcgYVN0clxuICovXG5BcnJheVNldC5wcm90b3R5cGUuaW5kZXhPZiA9IGZ1bmN0aW9uIEFycmF5U2V0X2luZGV4T2YoYVN0cikge1xuICBpZiAoaGFzTmF0aXZlTWFwKSB7XG4gICAgdmFyIGlkeCA9IHRoaXMuX3NldC5nZXQoYVN0cik7XG4gICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgIHJldHVybiBpZHg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBzU3RyID0gdXRpbC50b1NldFN0cmluZyhhU3RyKTtcbiAgICBpZiAoaGFzLmNhbGwodGhpcy5fc2V0LCBzU3RyKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX3NldFtzU3RyXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ1wiJyArIGFTdHIgKyAnXCIgaXMgbm90IGluIHRoZSBzZXQuJyk7XG59O1xuXG4vKipcbiAqIFdoYXQgaXMgdGhlIGVsZW1lbnQgYXQgdGhlIGdpdmVuIGluZGV4P1xuICpcbiAqIEBwYXJhbSBOdW1iZXIgYUlkeFxuICovXG5BcnJheVNldC5wcm90b3R5cGUuYXQgPSBmdW5jdGlvbiBBcnJheVNldF9hdChhSWR4KSB7XG4gIGlmIChhSWR4ID49IDAgJiYgYUlkeCA8IHRoaXMuX2FycmF5Lmxlbmd0aCkge1xuICAgIHJldHVybiB0aGlzLl9hcnJheVthSWR4XTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGVsZW1lbnQgaW5kZXhlZCBieSAnICsgYUlkeCk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGFycmF5IHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgc2V0ICh3aGljaCBoYXMgdGhlIHByb3BlciBpbmRpY2VzXG4gKiBpbmRpY2F0ZWQgYnkgaW5kZXhPZikuIE5vdGUgdGhhdCB0aGlzIGlzIGEgY29weSBvZiB0aGUgaW50ZXJuYWwgYXJyYXkgdXNlZFxuICogZm9yIHN0b3JpbmcgdGhlIG1lbWJlcnMgc28gdGhhdCBubyBvbmUgY2FuIG1lc3Mgd2l0aCBpbnRlcm5hbCBzdGF0ZS5cbiAqL1xuQXJyYXlTZXQucHJvdG90eXBlLnRvQXJyYXkgPSBmdW5jdGlvbiBBcnJheVNldF90b0FycmF5KCkge1xuICByZXR1cm4gdGhpcy5fYXJyYXkuc2xpY2UoKTtcbn07XG5cbmV4cG9ydHMuQXJyYXlTZXQgPSBBcnJheVNldDtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbGliL2FycmF5LXNldC5qc1xuLy8gbW9kdWxlIGlkID0gNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiAtKi0gTW9kZToganM7IGpzLWluZGVudC1sZXZlbDogMjsgLSotICovXG4vKlxuICogQ29weXJpZ2h0IDIwMTQgTW96aWxsYSBGb3VuZGF0aW9uIGFuZCBjb250cmlidXRvcnNcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBOZXcgQlNEIGxpY2Vuc2UuIFNlZSBMSUNFTlNFIG9yOlxuICogaHR0cDovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL0JTRC0zLUNsYXVzZVxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgbWFwcGluZ0IgaXMgYWZ0ZXIgbWFwcGluZ0Egd2l0aCByZXNwZWN0IHRvIGdlbmVyYXRlZFxuICogcG9zaXRpb24uXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlZFBvc2l0aW9uQWZ0ZXIobWFwcGluZ0EsIG1hcHBpbmdCKSB7XG4gIC8vIE9wdGltaXplZCBmb3IgbW9zdCBjb21tb24gY2FzZVxuICB2YXIgbGluZUEgPSBtYXBwaW5nQS5nZW5lcmF0ZWRMaW5lO1xuICB2YXIgbGluZUIgPSBtYXBwaW5nQi5nZW5lcmF0ZWRMaW5lO1xuICB2YXIgY29sdW1uQSA9IG1hcHBpbmdBLmdlbmVyYXRlZENvbHVtbjtcbiAgdmFyIGNvbHVtbkIgPSBtYXBwaW5nQi5nZW5lcmF0ZWRDb2x1bW47XG4gIHJldHVybiBsaW5lQiA+IGxpbmVBIHx8IGxpbmVCID09IGxpbmVBICYmIGNvbHVtbkIgPj0gY29sdW1uQSB8fFxuICAgICAgICAgdXRpbC5jb21wYXJlQnlHZW5lcmF0ZWRQb3NpdGlvbnNJbmZsYXRlZChtYXBwaW5nQSwgbWFwcGluZ0IpIDw9IDA7XG59XG5cbi8qKlxuICogQSBkYXRhIHN0cnVjdHVyZSB0byBwcm92aWRlIGEgc29ydGVkIHZpZXcgb2YgYWNjdW11bGF0ZWQgbWFwcGluZ3MgaW4gYVxuICogcGVyZm9ybWFuY2UgY29uc2Npb3VzIG1hbm5lci4gSXQgdHJhZGVzIGEgbmVnbGliYWJsZSBvdmVyaGVhZCBpbiBnZW5lcmFsXG4gKiBjYXNlIGZvciBhIGxhcmdlIHNwZWVkdXAgaW4gY2FzZSBvZiBtYXBwaW5ncyBiZWluZyBhZGRlZCBpbiBvcmRlci5cbiAqL1xuZnVuY3Rpb24gTWFwcGluZ0xpc3QoKSB7XG4gIHRoaXMuX2FycmF5ID0gW107XG4gIHRoaXMuX3NvcnRlZCA9IHRydWU7XG4gIC8vIFNlcnZlcyBhcyBpbmZpbXVtXG4gIHRoaXMuX2xhc3QgPSB7Z2VuZXJhdGVkTGluZTogLTEsIGdlbmVyYXRlZENvbHVtbjogMH07XG59XG5cbi8qKlxuICogSXRlcmF0ZSB0aHJvdWdoIGludGVybmFsIGl0ZW1zLiBUaGlzIG1ldGhvZCB0YWtlcyB0aGUgc2FtZSBhcmd1bWVudHMgdGhhdFxuICogYEFycmF5LnByb3RvdHlwZS5mb3JFYWNoYCB0YWtlcy5cbiAqXG4gKiBOT1RFOiBUaGUgb3JkZXIgb2YgdGhlIG1hcHBpbmdzIGlzIE5PVCBndWFyYW50ZWVkLlxuICovXG5NYXBwaW5nTGlzdC5wcm90b3R5cGUudW5zb3J0ZWRGb3JFYWNoID1cbiAgZnVuY3Rpb24gTWFwcGluZ0xpc3RfZm9yRWFjaChhQ2FsbGJhY2ssIGFUaGlzQXJnKSB7XG4gICAgdGhpcy5fYXJyYXkuZm9yRWFjaChhQ2FsbGJhY2ssIGFUaGlzQXJnKTtcbiAgfTtcblxuLyoqXG4gKiBBZGQgdGhlIGdpdmVuIHNvdXJjZSBtYXBwaW5nLlxuICpcbiAqIEBwYXJhbSBPYmplY3QgYU1hcHBpbmdcbiAqL1xuTWFwcGluZ0xpc3QucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIE1hcHBpbmdMaXN0X2FkZChhTWFwcGluZykge1xuICBpZiAoZ2VuZXJhdGVkUG9zaXRpb25BZnRlcih0aGlzLl9sYXN0LCBhTWFwcGluZykpIHtcbiAgICB0aGlzLl9sYXN0ID0gYU1hcHBpbmc7XG4gICAgdGhpcy5fYXJyYXkucHVzaChhTWFwcGluZyk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5fc29ydGVkID0gZmFsc2U7XG4gICAgdGhpcy5fYXJyYXkucHVzaChhTWFwcGluZyk7XG4gIH1cbn07XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZmxhdCwgc29ydGVkIGFycmF5IG9mIG1hcHBpbmdzLiBUaGUgbWFwcGluZ3MgYXJlIHNvcnRlZCBieVxuICogZ2VuZXJhdGVkIHBvc2l0aW9uLlxuICpcbiAqIFdBUk5JTkc6IFRoaXMgbWV0aG9kIHJldHVybnMgaW50ZXJuYWwgZGF0YSB3aXRob3V0IGNvcHlpbmcsIGZvclxuICogcGVyZm9ybWFuY2UuIFRoZSByZXR1cm4gdmFsdWUgbXVzdCBOT1QgYmUgbXV0YXRlZCwgYW5kIHNob3VsZCBiZSB0cmVhdGVkIGFzXG4gKiBhbiBpbW11dGFibGUgYm9ycm93LiBJZiB5b3Ugd2FudCB0byB0YWtlIG93bmVyc2hpcCwgeW91IG11c3QgbWFrZSB5b3VyIG93blxuICogY29weS5cbiAqL1xuTWFwcGluZ0xpc3QucHJvdG90eXBlLnRvQXJyYXkgPSBmdW5jdGlvbiBNYXBwaW5nTGlzdF90b0FycmF5KCkge1xuICBpZiAoIXRoaXMuX3NvcnRlZCkge1xuICAgIHRoaXMuX2FycmF5LnNvcnQodXRpbC5jb21wYXJlQnlHZW5lcmF0ZWRQb3NpdGlvbnNJbmZsYXRlZCk7XG4gICAgdGhpcy5fc29ydGVkID0gdHJ1ZTtcbiAgfVxuICByZXR1cm4gdGhpcy5fYXJyYXk7XG59O1xuXG5leHBvcnRzLk1hcHBpbmdMaXN0ID0gTWFwcGluZ0xpc3Q7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL2xpYi9tYXBwaW5nLWxpc3QuanNcbi8vIG1vZHVsZSBpZCA9IDZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogLSotIE1vZGU6IGpzOyBqcy1pbmRlbnQtbGV2ZWw6IDI7IC0qLSAqL1xuLypcbiAqIENvcHlyaWdodCAyMDExIE1vemlsbGEgRm91bmRhdGlvbiBhbmQgY29udHJpYnV0b3JzXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTmV3IEJTRCBsaWNlbnNlLiBTZWUgTElDRU5TRSBvcjpcbiAqIGh0dHA6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9CU0QtMy1DbGF1c2VcbiAqL1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xudmFyIGJpbmFyeVNlYXJjaCA9IHJlcXVpcmUoJy4vYmluYXJ5LXNlYXJjaCcpO1xudmFyIEFycmF5U2V0ID0gcmVxdWlyZSgnLi9hcnJheS1zZXQnKS5BcnJheVNldDtcbnZhciBiYXNlNjRWTFEgPSByZXF1aXJlKCcuL2Jhc2U2NC12bHEnKTtcbnZhciBxdWlja1NvcnQgPSByZXF1aXJlKCcuL3F1aWNrLXNvcnQnKS5xdWlja1NvcnQ7XG5cbmZ1bmN0aW9uIFNvdXJjZU1hcENvbnN1bWVyKGFTb3VyY2VNYXApIHtcbiAgdmFyIHNvdXJjZU1hcCA9IGFTb3VyY2VNYXA7XG4gIGlmICh0eXBlb2YgYVNvdXJjZU1hcCA9PT0gJ3N0cmluZycpIHtcbiAgICBzb3VyY2VNYXAgPSBKU09OLnBhcnNlKGFTb3VyY2VNYXAucmVwbGFjZSgvXlxcKVxcXVxcfScvLCAnJykpO1xuICB9XG5cbiAgcmV0dXJuIHNvdXJjZU1hcC5zZWN0aW9ucyAhPSBudWxsXG4gICAgPyBuZXcgSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyKHNvdXJjZU1hcClcbiAgICA6IG5ldyBCYXNpY1NvdXJjZU1hcENvbnN1bWVyKHNvdXJjZU1hcCk7XG59XG5cblNvdXJjZU1hcENvbnN1bWVyLmZyb21Tb3VyY2VNYXAgPSBmdW5jdGlvbihhU291cmNlTWFwKSB7XG4gIHJldHVybiBCYXNpY1NvdXJjZU1hcENvbnN1bWVyLmZyb21Tb3VyY2VNYXAoYVNvdXJjZU1hcCk7XG59XG5cbi8qKlxuICogVGhlIHZlcnNpb24gb2YgdGhlIHNvdXJjZSBtYXBwaW5nIHNwZWMgdGhhdCB3ZSBhcmUgY29uc3VtaW5nLlxuICovXG5Tb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuX3ZlcnNpb24gPSAzO1xuXG4vLyBgX19nZW5lcmF0ZWRNYXBwaW5nc2AgYW5kIGBfX29yaWdpbmFsTWFwcGluZ3NgIGFyZSBhcnJheXMgdGhhdCBob2xkIHRoZVxuLy8gcGFyc2VkIG1hcHBpbmcgY29vcmRpbmF0ZXMgZnJvbSB0aGUgc291cmNlIG1hcCdzIFwibWFwcGluZ3NcIiBhdHRyaWJ1dGUuIFRoZXlcbi8vIGFyZSBsYXppbHkgaW5zdGFudGlhdGVkLCBhY2Nlc3NlZCB2aWEgdGhlIGBfZ2VuZXJhdGVkTWFwcGluZ3NgIGFuZFxuLy8gYF9vcmlnaW5hbE1hcHBpbmdzYCBnZXR0ZXJzIHJlc3BlY3RpdmVseSwgYW5kIHdlIG9ubHkgcGFyc2UgdGhlIG1hcHBpbmdzXG4vLyBhbmQgY3JlYXRlIHRoZXNlIGFycmF5cyBvbmNlIHF1ZXJpZWQgZm9yIGEgc291cmNlIGxvY2F0aW9uLiBXZSBqdW1wIHRocm91Z2hcbi8vIHRoZXNlIGhvb3BzIGJlY2F1c2UgdGhlcmUgY2FuIGJlIG1hbnkgdGhvdXNhbmRzIG9mIG1hcHBpbmdzLCBhbmQgcGFyc2luZ1xuLy8gdGhlbSBpcyBleHBlbnNpdmUsIHNvIHdlIG9ubHkgd2FudCB0byBkbyBpdCBpZiB3ZSBtdXN0LlxuLy9cbi8vIEVhY2ggb2JqZWN0IGluIHRoZSBhcnJheXMgaXMgb2YgdGhlIGZvcm06XG4vL1xuLy8gICAgIHtcbi8vICAgICAgIGdlbmVyYXRlZExpbmU6IFRoZSBsaW5lIG51bWJlciBpbiB0aGUgZ2VuZXJhdGVkIGNvZGUsXG4vLyAgICAgICBnZW5lcmF0ZWRDb2x1bW46IFRoZSBjb2x1bW4gbnVtYmVyIGluIHRoZSBnZW5lcmF0ZWQgY29kZSxcbi8vICAgICAgIHNvdXJjZTogVGhlIHBhdGggdG8gdGhlIG9yaWdpbmFsIHNvdXJjZSBmaWxlIHRoYXQgZ2VuZXJhdGVkIHRoaXNcbi8vICAgICAgICAgICAgICAgY2h1bmsgb2YgY29kZSxcbi8vICAgICAgIG9yaWdpbmFsTGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBvcmlnaW5hbCBzb3VyY2UgdGhhdFxuLy8gICAgICAgICAgICAgICAgICAgICBjb3JyZXNwb25kcyB0byB0aGlzIGNodW5rIG9mIGdlbmVyYXRlZCBjb2RlLFxuLy8gICAgICAgb3JpZ2luYWxDb2x1bW46IFRoZSBjb2x1bW4gbnVtYmVyIGluIHRoZSBvcmlnaW5hbCBzb3VyY2UgdGhhdFxuLy8gICAgICAgICAgICAgICAgICAgICAgIGNvcnJlc3BvbmRzIHRvIHRoaXMgY2h1bmsgb2YgZ2VuZXJhdGVkIGNvZGUsXG4vLyAgICAgICBuYW1lOiBUaGUgbmFtZSBvZiB0aGUgb3JpZ2luYWwgc3ltYm9sIHdoaWNoIGdlbmVyYXRlZCB0aGlzIGNodW5rIG9mXG4vLyAgICAgICAgICAgICBjb2RlLlxuLy8gICAgIH1cbi8vXG4vLyBBbGwgcHJvcGVydGllcyBleGNlcHQgZm9yIGBnZW5lcmF0ZWRMaW5lYCBhbmQgYGdlbmVyYXRlZENvbHVtbmAgY2FuIGJlXG4vLyBgbnVsbGAuXG4vL1xuLy8gYF9nZW5lcmF0ZWRNYXBwaW5nc2AgaXMgb3JkZXJlZCBieSB0aGUgZ2VuZXJhdGVkIHBvc2l0aW9ucy5cbi8vXG4vLyBgX29yaWdpbmFsTWFwcGluZ3NgIGlzIG9yZGVyZWQgYnkgdGhlIG9yaWdpbmFsIHBvc2l0aW9ucy5cblxuU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlLl9fZ2VuZXJhdGVkTWFwcGluZ3MgPSBudWxsO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KFNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZSwgJ19nZW5lcmF0ZWRNYXBwaW5ncycsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLl9fZ2VuZXJhdGVkTWFwcGluZ3MpIHtcbiAgICAgIHRoaXMuX3BhcnNlTWFwcGluZ3ModGhpcy5fbWFwcGluZ3MsIHRoaXMuc291cmNlUm9vdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX19nZW5lcmF0ZWRNYXBwaW5ncztcbiAgfVxufSk7XG5cblNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5fX29yaWdpbmFsTWFwcGluZ3MgPSBudWxsO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KFNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZSwgJ19vcmlnaW5hbE1hcHBpbmdzJywge1xuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuX19vcmlnaW5hbE1hcHBpbmdzKSB7XG4gICAgICB0aGlzLl9wYXJzZU1hcHBpbmdzKHRoaXMuX21hcHBpbmdzLCB0aGlzLnNvdXJjZVJvb3QpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9fb3JpZ2luYWxNYXBwaW5ncztcbiAgfVxufSk7XG5cblNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5fY2hhcklzTWFwcGluZ1NlcGFyYXRvciA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcENvbnN1bWVyX2NoYXJJc01hcHBpbmdTZXBhcmF0b3IoYVN0ciwgaW5kZXgpIHtcbiAgICB2YXIgYyA9IGFTdHIuY2hhckF0KGluZGV4KTtcbiAgICByZXR1cm4gYyA9PT0gXCI7XCIgfHwgYyA9PT0gXCIsXCI7XG4gIH07XG5cbi8qKlxuICogUGFyc2UgdGhlIG1hcHBpbmdzIGluIGEgc3RyaW5nIGluIHRvIGEgZGF0YSBzdHJ1Y3R1cmUgd2hpY2ggd2UgY2FuIGVhc2lseVxuICogcXVlcnkgKHRoZSBvcmRlcmVkIGFycmF5cyBpbiB0aGUgYHRoaXMuX19nZW5lcmF0ZWRNYXBwaW5nc2AgYW5kXG4gKiBgdGhpcy5fX29yaWdpbmFsTWFwcGluZ3NgIHByb3BlcnRpZXMpLlxuICovXG5Tb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuX3BhcnNlTWFwcGluZ3MgPVxuICBmdW5jdGlvbiBTb3VyY2VNYXBDb25zdW1lcl9wYXJzZU1hcHBpbmdzKGFTdHIsIGFTb3VyY2VSb290KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU3ViY2xhc3NlcyBtdXN0IGltcGxlbWVudCBfcGFyc2VNYXBwaW5nc1wiKTtcbiAgfTtcblxuU291cmNlTWFwQ29uc3VtZXIuR0VORVJBVEVEX09SREVSID0gMTtcblNvdXJjZU1hcENvbnN1bWVyLk9SSUdJTkFMX09SREVSID0gMjtcblxuU291cmNlTWFwQ29uc3VtZXIuR1JFQVRFU1RfTE9XRVJfQk9VTkQgPSAxO1xuU291cmNlTWFwQ29uc3VtZXIuTEVBU1RfVVBQRVJfQk9VTkQgPSAyO1xuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBlYWNoIG1hcHBpbmcgYmV0d2VlbiBhbiBvcmlnaW5hbCBzb3VyY2UvbGluZS9jb2x1bW4gYW5kIGFcbiAqIGdlbmVyYXRlZCBsaW5lL2NvbHVtbiBpbiB0aGlzIHNvdXJjZSBtYXAuXG4gKlxuICogQHBhcmFtIEZ1bmN0aW9uIGFDYWxsYmFja1xuICogICAgICAgIFRoZSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aXRoIGVhY2ggbWFwcGluZy5cbiAqIEBwYXJhbSBPYmplY3QgYUNvbnRleHRcbiAqICAgICAgICBPcHRpb25hbC4gSWYgc3BlY2lmaWVkLCB0aGlzIG9iamVjdCB3aWxsIGJlIHRoZSB2YWx1ZSBvZiBgdGhpc2AgZXZlcnlcbiAqICAgICAgICB0aW1lIHRoYXQgYGFDYWxsYmFja2AgaXMgY2FsbGVkLlxuICogQHBhcmFtIGFPcmRlclxuICogICAgICAgIEVpdGhlciBgU291cmNlTWFwQ29uc3VtZXIuR0VORVJBVEVEX09SREVSYCBvclxuICogICAgICAgIGBTb3VyY2VNYXBDb25zdW1lci5PUklHSU5BTF9PUkRFUmAuIFNwZWNpZmllcyB3aGV0aGVyIHlvdSB3YW50IHRvXG4gKiAgICAgICAgaXRlcmF0ZSBvdmVyIHRoZSBtYXBwaW5ncyBzb3J0ZWQgYnkgdGhlIGdlbmVyYXRlZCBmaWxlJ3MgbGluZS9jb2x1bW5cbiAqICAgICAgICBvcmRlciBvciB0aGUgb3JpZ2luYWwncyBzb3VyY2UvbGluZS9jb2x1bW4gb3JkZXIsIHJlc3BlY3RpdmVseS4gRGVmYXVsdHMgdG9cbiAqICAgICAgICBgU291cmNlTWFwQ29uc3VtZXIuR0VORVJBVEVEX09SREVSYC5cbiAqL1xuU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlLmVhY2hNYXBwaW5nID1cbiAgZnVuY3Rpb24gU291cmNlTWFwQ29uc3VtZXJfZWFjaE1hcHBpbmcoYUNhbGxiYWNrLCBhQ29udGV4dCwgYU9yZGVyKSB7XG4gICAgdmFyIGNvbnRleHQgPSBhQ29udGV4dCB8fCBudWxsO1xuICAgIHZhciBvcmRlciA9IGFPcmRlciB8fCBTb3VyY2VNYXBDb25zdW1lci5HRU5FUkFURURfT1JERVI7XG5cbiAgICB2YXIgbWFwcGluZ3M7XG4gICAgc3dpdGNoIChvcmRlcikge1xuICAgIGNhc2UgU291cmNlTWFwQ29uc3VtZXIuR0VORVJBVEVEX09SREVSOlxuICAgICAgbWFwcGluZ3MgPSB0aGlzLl9nZW5lcmF0ZWRNYXBwaW5ncztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgU291cmNlTWFwQ29uc3VtZXIuT1JJR0lOQUxfT1JERVI6XG4gICAgICBtYXBwaW5ncyA9IHRoaXMuX29yaWdpbmFsTWFwcGluZ3M7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBvcmRlciBvZiBpdGVyYXRpb24uXCIpO1xuICAgIH1cblxuICAgIHZhciBzb3VyY2VSb290ID0gdGhpcy5zb3VyY2VSb290O1xuICAgIG1hcHBpbmdzLm1hcChmdW5jdGlvbiAobWFwcGluZykge1xuICAgICAgdmFyIHNvdXJjZSA9IG1hcHBpbmcuc291cmNlID09PSBudWxsID8gbnVsbCA6IHRoaXMuX3NvdXJjZXMuYXQobWFwcGluZy5zb3VyY2UpO1xuICAgICAgaWYgKHNvdXJjZSAhPSBudWxsICYmIHNvdXJjZVJvb3QgIT0gbnVsbCkge1xuICAgICAgICBzb3VyY2UgPSB1dGlsLmpvaW4oc291cmNlUm9vdCwgc291cmNlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNvdXJjZTogc291cmNlLFxuICAgICAgICBnZW5lcmF0ZWRMaW5lOiBtYXBwaW5nLmdlbmVyYXRlZExpbmUsXG4gICAgICAgIGdlbmVyYXRlZENvbHVtbjogbWFwcGluZy5nZW5lcmF0ZWRDb2x1bW4sXG4gICAgICAgIG9yaWdpbmFsTGluZTogbWFwcGluZy5vcmlnaW5hbExpbmUsXG4gICAgICAgIG9yaWdpbmFsQ29sdW1uOiBtYXBwaW5nLm9yaWdpbmFsQ29sdW1uLFxuICAgICAgICBuYW1lOiBtYXBwaW5nLm5hbWUgPT09IG51bGwgPyBudWxsIDogdGhpcy5fbmFtZXMuYXQobWFwcGluZy5uYW1lKVxuICAgICAgfTtcbiAgICB9LCB0aGlzKS5mb3JFYWNoKGFDYWxsYmFjaywgY29udGV4dCk7XG4gIH07XG5cbi8qKlxuICogUmV0dXJucyBhbGwgZ2VuZXJhdGVkIGxpbmUgYW5kIGNvbHVtbiBpbmZvcm1hdGlvbiBmb3IgdGhlIG9yaWdpbmFsIHNvdXJjZSxcbiAqIGxpbmUsIGFuZCBjb2x1bW4gcHJvdmlkZWQuIElmIG5vIGNvbHVtbiBpcyBwcm92aWRlZCwgcmV0dXJucyBhbGwgbWFwcGluZ3NcbiAqIGNvcnJlc3BvbmRpbmcgdG8gYSBlaXRoZXIgdGhlIGxpbmUgd2UgYXJlIHNlYXJjaGluZyBmb3Igb3IgdGhlIG5leHRcbiAqIGNsb3Nlc3QgbGluZSB0aGF0IGhhcyBhbnkgbWFwcGluZ3MuIE90aGVyd2lzZSwgcmV0dXJucyBhbGwgbWFwcGluZ3NcbiAqIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIGxpbmUgYW5kIGVpdGhlciB0aGUgY29sdW1uIHdlIGFyZSBzZWFyY2hpbmcgZm9yXG4gKiBvciB0aGUgbmV4dCBjbG9zZXN0IGNvbHVtbiB0aGF0IGhhcyBhbnkgb2Zmc2V0cy5cbiAqXG4gKiBUaGUgb25seSBhcmd1bWVudCBpcyBhbiBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIHNvdXJjZTogVGhlIGZpbGVuYW1lIG9mIHRoZSBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIC0gbGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIC0gY29sdW1uOiBPcHRpb25hbC4gdGhlIGNvbHVtbiBudW1iZXIgaW4gdGhlIG9yaWdpbmFsIHNvdXJjZS5cbiAqXG4gKiBhbmQgYW4gYXJyYXkgb2Ygb2JqZWN0cyBpcyByZXR1cm5lZCwgZWFjaCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAqXG4gKiAgIC0gbGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBnZW5lcmF0ZWQgc291cmNlLCBvciBudWxsLlxuICogICAtIGNvbHVtbjogVGhlIGNvbHVtbiBudW1iZXIgaW4gdGhlIGdlbmVyYXRlZCBzb3VyY2UsIG9yIG51bGwuXG4gKi9cblNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5hbGxHZW5lcmF0ZWRQb3NpdGlvbnNGb3IgPVxuICBmdW5jdGlvbiBTb3VyY2VNYXBDb25zdW1lcl9hbGxHZW5lcmF0ZWRQb3NpdGlvbnNGb3IoYUFyZ3MpIHtcbiAgICB2YXIgbGluZSA9IHV0aWwuZ2V0QXJnKGFBcmdzLCAnbGluZScpO1xuXG4gICAgLy8gV2hlbiB0aGVyZSBpcyBubyBleGFjdCBtYXRjaCwgQmFzaWNTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuX2ZpbmRNYXBwaW5nXG4gICAgLy8gcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGNsb3Nlc3QgbWFwcGluZyBsZXNzIHRoYW4gdGhlIG5lZWRsZS4gQnlcbiAgICAvLyBzZXR0aW5nIG5lZWRsZS5vcmlnaW5hbENvbHVtbiB0byAwLCB3ZSB0aHVzIGZpbmQgdGhlIGxhc3QgbWFwcGluZyBmb3JcbiAgICAvLyB0aGUgZ2l2ZW4gbGluZSwgcHJvdmlkZWQgc3VjaCBhIG1hcHBpbmcgZXhpc3RzLlxuICAgIHZhciBuZWVkbGUgPSB7XG4gICAgICBzb3VyY2U6IHV0aWwuZ2V0QXJnKGFBcmdzLCAnc291cmNlJyksXG4gICAgICBvcmlnaW5hbExpbmU6IGxpbmUsXG4gICAgICBvcmlnaW5hbENvbHVtbjogdXRpbC5nZXRBcmcoYUFyZ3MsICdjb2x1bW4nLCAwKVxuICAgIH07XG5cbiAgICBpZiAodGhpcy5zb3VyY2VSb290ICE9IG51bGwpIHtcbiAgICAgIG5lZWRsZS5zb3VyY2UgPSB1dGlsLnJlbGF0aXZlKHRoaXMuc291cmNlUm9vdCwgbmVlZGxlLnNvdXJjZSk7XG4gICAgfVxuICAgIGlmICghdGhpcy5fc291cmNlcy5oYXMobmVlZGxlLnNvdXJjZSkpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgbmVlZGxlLnNvdXJjZSA9IHRoaXMuX3NvdXJjZXMuaW5kZXhPZihuZWVkbGUuc291cmNlKTtcblxuICAgIHZhciBtYXBwaW5ncyA9IFtdO1xuXG4gICAgdmFyIGluZGV4ID0gdGhpcy5fZmluZE1hcHBpbmcobmVlZGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX29yaWdpbmFsTWFwcGluZ3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJvcmlnaW5hbExpbmVcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm9yaWdpbmFsQ29sdW1uXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRpbC5jb21wYXJlQnlPcmlnaW5hbFBvc2l0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW5hcnlTZWFyY2guTEVBU1RfVVBQRVJfQk9VTkQpO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB2YXIgbWFwcGluZyA9IHRoaXMuX29yaWdpbmFsTWFwcGluZ3NbaW5kZXhdO1xuXG4gICAgICBpZiAoYUFyZ3MuY29sdW1uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIG9yaWdpbmFsTGluZSA9IG1hcHBpbmcub3JpZ2luYWxMaW5lO1xuXG4gICAgICAgIC8vIEl0ZXJhdGUgdW50aWwgZWl0aGVyIHdlIHJ1biBvdXQgb2YgbWFwcGluZ3MsIG9yIHdlIHJ1biBpbnRvXG4gICAgICAgIC8vIGEgbWFwcGluZyBmb3IgYSBkaWZmZXJlbnQgbGluZSB0aGFuIHRoZSBvbmUgd2UgZm91bmQuIFNpbmNlXG4gICAgICAgIC8vIG1hcHBpbmdzIGFyZSBzb3J0ZWQsIHRoaXMgaXMgZ3VhcmFudGVlZCB0byBmaW5kIGFsbCBtYXBwaW5ncyBmb3JcbiAgICAgICAgLy8gdGhlIGxpbmUgd2UgZm91bmQuXG4gICAgICAgIHdoaWxlIChtYXBwaW5nICYmIG1hcHBpbmcub3JpZ2luYWxMaW5lID09PSBvcmlnaW5hbExpbmUpIHtcbiAgICAgICAgICBtYXBwaW5ncy5wdXNoKHtcbiAgICAgICAgICAgIGxpbmU6IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdnZW5lcmF0ZWRMaW5lJywgbnVsbCksXG4gICAgICAgICAgICBjb2x1bW46IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdnZW5lcmF0ZWRDb2x1bW4nLCBudWxsKSxcbiAgICAgICAgICAgIGxhc3RDb2x1bW46IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdsYXN0R2VuZXJhdGVkQ29sdW1uJywgbnVsbClcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIG1hcHBpbmcgPSB0aGlzLl9vcmlnaW5hbE1hcHBpbmdzWysraW5kZXhdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgb3JpZ2luYWxDb2x1bW4gPSBtYXBwaW5nLm9yaWdpbmFsQ29sdW1uO1xuXG4gICAgICAgIC8vIEl0ZXJhdGUgdW50aWwgZWl0aGVyIHdlIHJ1biBvdXQgb2YgbWFwcGluZ3MsIG9yIHdlIHJ1biBpbnRvXG4gICAgICAgIC8vIGEgbWFwcGluZyBmb3IgYSBkaWZmZXJlbnQgbGluZSB0aGFuIHRoZSBvbmUgd2Ugd2VyZSBzZWFyY2hpbmcgZm9yLlxuICAgICAgICAvLyBTaW5jZSBtYXBwaW5ncyBhcmUgc29ydGVkLCB0aGlzIGlzIGd1YXJhbnRlZWQgdG8gZmluZCBhbGwgbWFwcGluZ3MgZm9yXG4gICAgICAgIC8vIHRoZSBsaW5lIHdlIGFyZSBzZWFyY2hpbmcgZm9yLlxuICAgICAgICB3aGlsZSAobWFwcGluZyAmJlxuICAgICAgICAgICAgICAgbWFwcGluZy5vcmlnaW5hbExpbmUgPT09IGxpbmUgJiZcbiAgICAgICAgICAgICAgIG1hcHBpbmcub3JpZ2luYWxDb2x1bW4gPT0gb3JpZ2luYWxDb2x1bW4pIHtcbiAgICAgICAgICBtYXBwaW5ncy5wdXNoKHtcbiAgICAgICAgICAgIGxpbmU6IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdnZW5lcmF0ZWRMaW5lJywgbnVsbCksXG4gICAgICAgICAgICBjb2x1bW46IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdnZW5lcmF0ZWRDb2x1bW4nLCBudWxsKSxcbiAgICAgICAgICAgIGxhc3RDb2x1bW46IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdsYXN0R2VuZXJhdGVkQ29sdW1uJywgbnVsbClcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIG1hcHBpbmcgPSB0aGlzLl9vcmlnaW5hbE1hcHBpbmdzWysraW5kZXhdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1hcHBpbmdzO1xuICB9O1xuXG5leHBvcnRzLlNvdXJjZU1hcENvbnN1bWVyID0gU291cmNlTWFwQ29uc3VtZXI7XG5cbi8qKlxuICogQSBCYXNpY1NvdXJjZU1hcENvbnN1bWVyIGluc3RhbmNlIHJlcHJlc2VudHMgYSBwYXJzZWQgc291cmNlIG1hcCB3aGljaCB3ZSBjYW5cbiAqIHF1ZXJ5IGZvciBpbmZvcm1hdGlvbiBhYm91dCB0aGUgb3JpZ2luYWwgZmlsZSBwb3NpdGlvbnMgYnkgZ2l2aW5nIGl0IGEgZmlsZVxuICogcG9zaXRpb24gaW4gdGhlIGdlbmVyYXRlZCBzb3VyY2UuXG4gKlxuICogVGhlIG9ubHkgcGFyYW1ldGVyIGlzIHRoZSByYXcgc291cmNlIG1hcCAoZWl0aGVyIGFzIGEgSlNPTiBzdHJpbmcsIG9yXG4gKiBhbHJlYWR5IHBhcnNlZCB0byBhbiBvYmplY3QpLiBBY2NvcmRpbmcgdG8gdGhlIHNwZWMsIHNvdXJjZSBtYXBzIGhhdmUgdGhlXG4gKiBmb2xsb3dpbmcgYXR0cmlidXRlczpcbiAqXG4gKiAgIC0gdmVyc2lvbjogV2hpY2ggdmVyc2lvbiBvZiB0aGUgc291cmNlIG1hcCBzcGVjIHRoaXMgbWFwIGlzIGZvbGxvd2luZy5cbiAqICAgLSBzb3VyY2VzOiBBbiBhcnJheSBvZiBVUkxzIHRvIHRoZSBvcmlnaW5hbCBzb3VyY2UgZmlsZXMuXG4gKiAgIC0gbmFtZXM6IEFuIGFycmF5IG9mIGlkZW50aWZpZXJzIHdoaWNoIGNhbiBiZSByZWZlcnJlbmNlZCBieSBpbmRpdmlkdWFsIG1hcHBpbmdzLlxuICogICAtIHNvdXJjZVJvb3Q6IE9wdGlvbmFsLiBUaGUgVVJMIHJvb3QgZnJvbSB3aGljaCBhbGwgc291cmNlcyBhcmUgcmVsYXRpdmUuXG4gKiAgIC0gc291cmNlc0NvbnRlbnQ6IE9wdGlvbmFsLiBBbiBhcnJheSBvZiBjb250ZW50cyBvZiB0aGUgb3JpZ2luYWwgc291cmNlIGZpbGVzLlxuICogICAtIG1hcHBpbmdzOiBBIHN0cmluZyBvZiBiYXNlNjQgVkxRcyB3aGljaCBjb250YWluIHRoZSBhY3R1YWwgbWFwcGluZ3MuXG4gKiAgIC0gZmlsZTogT3B0aW9uYWwuIFRoZSBnZW5lcmF0ZWQgZmlsZSB0aGlzIHNvdXJjZSBtYXAgaXMgYXNzb2NpYXRlZCB3aXRoLlxuICpcbiAqIEhlcmUgaXMgYW4gZXhhbXBsZSBzb3VyY2UgbWFwLCB0YWtlbiBmcm9tIHRoZSBzb3VyY2UgbWFwIHNwZWNbMF06XG4gKlxuICogICAgIHtcbiAqICAgICAgIHZlcnNpb24gOiAzLFxuICogICAgICAgZmlsZTogXCJvdXQuanNcIixcbiAqICAgICAgIHNvdXJjZVJvb3QgOiBcIlwiLFxuICogICAgICAgc291cmNlczogW1wiZm9vLmpzXCIsIFwiYmFyLmpzXCJdLFxuICogICAgICAgbmFtZXM6IFtcInNyY1wiLCBcIm1hcHNcIiwgXCJhcmVcIiwgXCJmdW5cIl0sXG4gKiAgICAgICBtYXBwaW5nczogXCJBQSxBQjs7QUJDREU7XCJcbiAqICAgICB9XG4gKlxuICogWzBdOiBodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9kb2N1bWVudC9kLzFVMVJHQWVoUXdSeXBVVG92RjFLUmxwaU9GemUwYi1fMmdjNmZBSDBLWTBrL2VkaXQ/cGxpPTEjXG4gKi9cbmZ1bmN0aW9uIEJhc2ljU291cmNlTWFwQ29uc3VtZXIoYVNvdXJjZU1hcCkge1xuICB2YXIgc291cmNlTWFwID0gYVNvdXJjZU1hcDtcbiAgaWYgKHR5cGVvZiBhU291cmNlTWFwID09PSAnc3RyaW5nJykge1xuICAgIHNvdXJjZU1hcCA9IEpTT04ucGFyc2UoYVNvdXJjZU1hcC5yZXBsYWNlKC9eXFwpXFxdXFx9Jy8sICcnKSk7XG4gIH1cblxuICB2YXIgdmVyc2lvbiA9IHV0aWwuZ2V0QXJnKHNvdXJjZU1hcCwgJ3ZlcnNpb24nKTtcbiAgdmFyIHNvdXJjZXMgPSB1dGlsLmdldEFyZyhzb3VyY2VNYXAsICdzb3VyY2VzJyk7XG4gIC8vIFNhc3MgMy4zIGxlYXZlcyBvdXQgdGhlICduYW1lcycgYXJyYXksIHNvIHdlIGRldmlhdGUgZnJvbSB0aGUgc3BlYyAod2hpY2hcbiAgLy8gcmVxdWlyZXMgdGhlIGFycmF5KSB0byBwbGF5IG5pY2UgaGVyZS5cbiAgdmFyIG5hbWVzID0gdXRpbC5nZXRBcmcoc291cmNlTWFwLCAnbmFtZXMnLCBbXSk7XG4gIHZhciBzb3VyY2VSb290ID0gdXRpbC5nZXRBcmcoc291cmNlTWFwLCAnc291cmNlUm9vdCcsIG51bGwpO1xuICB2YXIgc291cmNlc0NvbnRlbnQgPSB1dGlsLmdldEFyZyhzb3VyY2VNYXAsICdzb3VyY2VzQ29udGVudCcsIG51bGwpO1xuICB2YXIgbWFwcGluZ3MgPSB1dGlsLmdldEFyZyhzb3VyY2VNYXAsICdtYXBwaW5ncycpO1xuICB2YXIgZmlsZSA9IHV0aWwuZ2V0QXJnKHNvdXJjZU1hcCwgJ2ZpbGUnLCBudWxsKTtcblxuICAvLyBPbmNlIGFnYWluLCBTYXNzIGRldmlhdGVzIGZyb20gdGhlIHNwZWMgYW5kIHN1cHBsaWVzIHRoZSB2ZXJzaW9uIGFzIGFcbiAgLy8gc3RyaW5nIHJhdGhlciB0aGFuIGEgbnVtYmVyLCBzbyB3ZSB1c2UgbG9vc2UgZXF1YWxpdHkgY2hlY2tpbmcgaGVyZS5cbiAgaWYgKHZlcnNpb24gIT0gdGhpcy5fdmVyc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgdmVyc2lvbjogJyArIHZlcnNpb24pO1xuICB9XG5cbiAgc291cmNlcyA9IHNvdXJjZXNcbiAgICAubWFwKFN0cmluZylcbiAgICAvLyBTb21lIHNvdXJjZSBtYXBzIHByb2R1Y2UgcmVsYXRpdmUgc291cmNlIHBhdGhzIGxpa2UgXCIuL2Zvby5qc1wiIGluc3RlYWQgb2ZcbiAgICAvLyBcImZvby5qc1wiLiAgTm9ybWFsaXplIHRoZXNlIGZpcnN0IHNvIHRoYXQgZnV0dXJlIGNvbXBhcmlzb25zIHdpbGwgc3VjY2VlZC5cbiAgICAvLyBTZWUgYnVnemlsLmxhLzEwOTA3NjguXG4gICAgLm1hcCh1dGlsLm5vcm1hbGl6ZSlcbiAgICAvLyBBbHdheXMgZW5zdXJlIHRoYXQgYWJzb2x1dGUgc291cmNlcyBhcmUgaW50ZXJuYWxseSBzdG9yZWQgcmVsYXRpdmUgdG9cbiAgICAvLyB0aGUgc291cmNlIHJvb3QsIGlmIHRoZSBzb3VyY2Ugcm9vdCBpcyBhYnNvbHV0ZS4gTm90IGRvaW5nIHRoaXMgd291bGRcbiAgICAvLyBiZSBwYXJ0aWN1bGFybHkgcHJvYmxlbWF0aWMgd2hlbiB0aGUgc291cmNlIHJvb3QgaXMgYSBwcmVmaXggb2YgdGhlXG4gICAgLy8gc291cmNlICh2YWxpZCwgYnV0IHdoeT8/KS4gU2VlIGdpdGh1YiBpc3N1ZSAjMTk5IGFuZCBidWd6aWwubGEvMTE4ODk4Mi5cbiAgICAubWFwKGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgIHJldHVybiBzb3VyY2VSb290ICYmIHV0aWwuaXNBYnNvbHV0ZShzb3VyY2VSb290KSAmJiB1dGlsLmlzQWJzb2x1dGUoc291cmNlKVxuICAgICAgICA/IHV0aWwucmVsYXRpdmUoc291cmNlUm9vdCwgc291cmNlKVxuICAgICAgICA6IHNvdXJjZTtcbiAgICB9KTtcblxuICAvLyBQYXNzIGB0cnVlYCBiZWxvdyB0byBhbGxvdyBkdXBsaWNhdGUgbmFtZXMgYW5kIHNvdXJjZXMuIFdoaWxlIHNvdXJjZSBtYXBzXG4gIC8vIGFyZSBpbnRlbmRlZCB0byBiZSBjb21wcmVzc2VkIGFuZCBkZWR1cGxpY2F0ZWQsIHRoZSBUeXBlU2NyaXB0IGNvbXBpbGVyXG4gIC8vIHNvbWV0aW1lcyBnZW5lcmF0ZXMgc291cmNlIG1hcHMgd2l0aCBkdXBsaWNhdGVzIGluIHRoZW0uIFNlZSBHaXRodWIgaXNzdWVcbiAgLy8gIzcyIGFuZCBidWd6aWwubGEvODg5NDkyLlxuICB0aGlzLl9uYW1lcyA9IEFycmF5U2V0LmZyb21BcnJheShuYW1lcy5tYXAoU3RyaW5nKSwgdHJ1ZSk7XG4gIHRoaXMuX3NvdXJjZXMgPSBBcnJheVNldC5mcm9tQXJyYXkoc291cmNlcywgdHJ1ZSk7XG5cbiAgdGhpcy5zb3VyY2VSb290ID0gc291cmNlUm9vdDtcbiAgdGhpcy5zb3VyY2VzQ29udGVudCA9IHNvdXJjZXNDb250ZW50O1xuICB0aGlzLl9tYXBwaW5ncyA9IG1hcHBpbmdzO1xuICB0aGlzLmZpbGUgPSBmaWxlO1xufVxuXG5CYXNpY1NvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlKTtcbkJhc2ljU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlLmNvbnN1bWVyID0gU291cmNlTWFwQ29uc3VtZXI7XG5cbi8qKlxuICogQ3JlYXRlIGEgQmFzaWNTb3VyY2VNYXBDb25zdW1lciBmcm9tIGEgU291cmNlTWFwR2VuZXJhdG9yLlxuICpcbiAqIEBwYXJhbSBTb3VyY2VNYXBHZW5lcmF0b3IgYVNvdXJjZU1hcFxuICogICAgICAgIFRoZSBzb3VyY2UgbWFwIHRoYXQgd2lsbCBiZSBjb25zdW1lZC5cbiAqIEByZXR1cm5zIEJhc2ljU291cmNlTWFwQ29uc3VtZXJcbiAqL1xuQmFzaWNTb3VyY2VNYXBDb25zdW1lci5mcm9tU291cmNlTWFwID1cbiAgZnVuY3Rpb24gU291cmNlTWFwQ29uc3VtZXJfZnJvbVNvdXJjZU1hcChhU291cmNlTWFwKSB7XG4gICAgdmFyIHNtYyA9IE9iamVjdC5jcmVhdGUoQmFzaWNTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUpO1xuXG4gICAgdmFyIG5hbWVzID0gc21jLl9uYW1lcyA9IEFycmF5U2V0LmZyb21BcnJheShhU291cmNlTWFwLl9uYW1lcy50b0FycmF5KCksIHRydWUpO1xuICAgIHZhciBzb3VyY2VzID0gc21jLl9zb3VyY2VzID0gQXJyYXlTZXQuZnJvbUFycmF5KGFTb3VyY2VNYXAuX3NvdXJjZXMudG9BcnJheSgpLCB0cnVlKTtcbiAgICBzbWMuc291cmNlUm9vdCA9IGFTb3VyY2VNYXAuX3NvdXJjZVJvb3Q7XG4gICAgc21jLnNvdXJjZXNDb250ZW50ID0gYVNvdXJjZU1hcC5fZ2VuZXJhdGVTb3VyY2VzQ29udGVudChzbWMuX3NvdXJjZXMudG9BcnJheSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc21jLnNvdXJjZVJvb3QpO1xuICAgIHNtYy5maWxlID0gYVNvdXJjZU1hcC5fZmlsZTtcblxuICAgIC8vIEJlY2F1c2Ugd2UgYXJlIG1vZGlmeWluZyB0aGUgZW50cmllcyAoYnkgY29udmVydGluZyBzdHJpbmcgc291cmNlcyBhbmRcbiAgICAvLyBuYW1lcyB0byBpbmRpY2VzIGludG8gdGhlIHNvdXJjZXMgYW5kIG5hbWVzIEFycmF5U2V0cyksIHdlIGhhdmUgdG8gbWFrZVxuICAgIC8vIGEgY29weSBvZiB0aGUgZW50cnkgb3IgZWxzZSBiYWQgdGhpbmdzIGhhcHBlbi4gU2hhcmVkIG11dGFibGUgc3RhdGVcbiAgICAvLyBzdHJpa2VzIGFnYWluISBTZWUgZ2l0aHViIGlzc3VlICMxOTEuXG5cbiAgICB2YXIgZ2VuZXJhdGVkTWFwcGluZ3MgPSBhU291cmNlTWFwLl9tYXBwaW5ncy50b0FycmF5KCkuc2xpY2UoKTtcbiAgICB2YXIgZGVzdEdlbmVyYXRlZE1hcHBpbmdzID0gc21jLl9fZ2VuZXJhdGVkTWFwcGluZ3MgPSBbXTtcbiAgICB2YXIgZGVzdE9yaWdpbmFsTWFwcGluZ3MgPSBzbWMuX19vcmlnaW5hbE1hcHBpbmdzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gZ2VuZXJhdGVkTWFwcGluZ3MubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBzcmNNYXBwaW5nID0gZ2VuZXJhdGVkTWFwcGluZ3NbaV07XG4gICAgICB2YXIgZGVzdE1hcHBpbmcgPSBuZXcgTWFwcGluZztcbiAgICAgIGRlc3RNYXBwaW5nLmdlbmVyYXRlZExpbmUgPSBzcmNNYXBwaW5nLmdlbmVyYXRlZExpbmU7XG4gICAgICBkZXN0TWFwcGluZy5nZW5lcmF0ZWRDb2x1bW4gPSBzcmNNYXBwaW5nLmdlbmVyYXRlZENvbHVtbjtcblxuICAgICAgaWYgKHNyY01hcHBpbmcuc291cmNlKSB7XG4gICAgICAgIGRlc3RNYXBwaW5nLnNvdXJjZSA9IHNvdXJjZXMuaW5kZXhPZihzcmNNYXBwaW5nLnNvdXJjZSk7XG4gICAgICAgIGRlc3RNYXBwaW5nLm9yaWdpbmFsTGluZSA9IHNyY01hcHBpbmcub3JpZ2luYWxMaW5lO1xuICAgICAgICBkZXN0TWFwcGluZy5vcmlnaW5hbENvbHVtbiA9IHNyY01hcHBpbmcub3JpZ2luYWxDb2x1bW47XG5cbiAgICAgICAgaWYgKHNyY01hcHBpbmcubmFtZSkge1xuICAgICAgICAgIGRlc3RNYXBwaW5nLm5hbWUgPSBuYW1lcy5pbmRleE9mKHNyY01hcHBpbmcubmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICBkZXN0T3JpZ2luYWxNYXBwaW5ncy5wdXNoKGRlc3RNYXBwaW5nKTtcbiAgICAgIH1cblxuICAgICAgZGVzdEdlbmVyYXRlZE1hcHBpbmdzLnB1c2goZGVzdE1hcHBpbmcpO1xuICAgIH1cblxuICAgIHF1aWNrU29ydChzbWMuX19vcmlnaW5hbE1hcHBpbmdzLCB1dGlsLmNvbXBhcmVCeU9yaWdpbmFsUG9zaXRpb25zKTtcblxuICAgIHJldHVybiBzbWM7XG4gIH07XG5cbi8qKlxuICogVGhlIHZlcnNpb24gb2YgdGhlIHNvdXJjZSBtYXBwaW5nIHNwZWMgdGhhdCB3ZSBhcmUgY29uc3VtaW5nLlxuICovXG5CYXNpY1NvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5fdmVyc2lvbiA9IDM7XG5cbi8qKlxuICogVGhlIGxpc3Qgb2Ygb3JpZ2luYWwgc291cmNlcy5cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEJhc2ljU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlLCAnc291cmNlcycsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZXMudG9BcnJheSgpLm1hcChmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHRoaXMuc291cmNlUm9vdCAhPSBudWxsID8gdXRpbC5qb2luKHRoaXMuc291cmNlUm9vdCwgcykgOiBzO1xuICAgIH0sIHRoaXMpO1xuICB9XG59KTtcblxuLyoqXG4gKiBQcm92aWRlIHRoZSBKSVQgd2l0aCBhIG5pY2Ugc2hhcGUgLyBoaWRkZW4gY2xhc3MuXG4gKi9cbmZ1bmN0aW9uIE1hcHBpbmcoKSB7XG4gIHRoaXMuZ2VuZXJhdGVkTGluZSA9IDA7XG4gIHRoaXMuZ2VuZXJhdGVkQ29sdW1uID0gMDtcbiAgdGhpcy5zb3VyY2UgPSBudWxsO1xuICB0aGlzLm9yaWdpbmFsTGluZSA9IG51bGw7XG4gIHRoaXMub3JpZ2luYWxDb2x1bW4gPSBudWxsO1xuICB0aGlzLm5hbWUgPSBudWxsO1xufVxuXG4vKipcbiAqIFBhcnNlIHRoZSBtYXBwaW5ncyBpbiBhIHN0cmluZyBpbiB0byBhIGRhdGEgc3RydWN0dXJlIHdoaWNoIHdlIGNhbiBlYXNpbHlcbiAqIHF1ZXJ5ICh0aGUgb3JkZXJlZCBhcnJheXMgaW4gdGhlIGB0aGlzLl9fZ2VuZXJhdGVkTWFwcGluZ3NgIGFuZFxuICogYHRoaXMuX19vcmlnaW5hbE1hcHBpbmdzYCBwcm9wZXJ0aWVzKS5cbiAqL1xuQmFzaWNTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuX3BhcnNlTWFwcGluZ3MgPVxuICBmdW5jdGlvbiBTb3VyY2VNYXBDb25zdW1lcl9wYXJzZU1hcHBpbmdzKGFTdHIsIGFTb3VyY2VSb290KSB7XG4gICAgdmFyIGdlbmVyYXRlZExpbmUgPSAxO1xuICAgIHZhciBwcmV2aW91c0dlbmVyYXRlZENvbHVtbiA9IDA7XG4gICAgdmFyIHByZXZpb3VzT3JpZ2luYWxMaW5lID0gMDtcbiAgICB2YXIgcHJldmlvdXNPcmlnaW5hbENvbHVtbiA9IDA7XG4gICAgdmFyIHByZXZpb3VzU291cmNlID0gMDtcbiAgICB2YXIgcHJldmlvdXNOYW1lID0gMDtcbiAgICB2YXIgbGVuZ3RoID0gYVN0ci5sZW5ndGg7XG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICB2YXIgY2FjaGVkU2VnbWVudHMgPSB7fTtcbiAgICB2YXIgdGVtcCA9IHt9O1xuICAgIHZhciBvcmlnaW5hbE1hcHBpbmdzID0gW107XG4gICAgdmFyIGdlbmVyYXRlZE1hcHBpbmdzID0gW107XG4gICAgdmFyIG1hcHBpbmcsIHN0ciwgc2VnbWVudCwgZW5kLCB2YWx1ZTtcblxuICAgIHdoaWxlIChpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKGFTdHIuY2hhckF0KGluZGV4KSA9PT0gJzsnKSB7XG4gICAgICAgIGdlbmVyYXRlZExpbmUrKztcbiAgICAgICAgaW5kZXgrKztcbiAgICAgICAgcHJldmlvdXNHZW5lcmF0ZWRDb2x1bW4gPSAwO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoYVN0ci5jaGFyQXQoaW5kZXgpID09PSAnLCcpIHtcbiAgICAgICAgaW5kZXgrKztcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBtYXBwaW5nID0gbmV3IE1hcHBpbmcoKTtcbiAgICAgICAgbWFwcGluZy5nZW5lcmF0ZWRMaW5lID0gZ2VuZXJhdGVkTGluZTtcblxuICAgICAgICAvLyBCZWNhdXNlIGVhY2ggb2Zmc2V0IGlzIGVuY29kZWQgcmVsYXRpdmUgdG8gdGhlIHByZXZpb3VzIG9uZSxcbiAgICAgICAgLy8gbWFueSBzZWdtZW50cyBvZnRlbiBoYXZlIHRoZSBzYW1lIGVuY29kaW5nLiBXZSBjYW4gZXhwbG9pdCB0aGlzXG4gICAgICAgIC8vIGZhY3QgYnkgY2FjaGluZyB0aGUgcGFyc2VkIHZhcmlhYmxlIGxlbmd0aCBmaWVsZHMgb2YgZWFjaCBzZWdtZW50LFxuICAgICAgICAvLyBhbGxvd2luZyB1cyB0byBhdm9pZCBhIHNlY29uZCBwYXJzZSBpZiB3ZSBlbmNvdW50ZXIgdGhlIHNhbWVcbiAgICAgICAgLy8gc2VnbWVudCBhZ2Fpbi5cbiAgICAgICAgZm9yIChlbmQgPSBpbmRleDsgZW5kIDwgbGVuZ3RoOyBlbmQrKykge1xuICAgICAgICAgIGlmICh0aGlzLl9jaGFySXNNYXBwaW5nU2VwYXJhdG9yKGFTdHIsIGVuZCkpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdHIgPSBhU3RyLnNsaWNlKGluZGV4LCBlbmQpO1xuXG4gICAgICAgIHNlZ21lbnQgPSBjYWNoZWRTZWdtZW50c1tzdHJdO1xuICAgICAgICBpZiAoc2VnbWVudCkge1xuICAgICAgICAgIGluZGV4ICs9IHN0ci5sZW5ndGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2VnbWVudCA9IFtdO1xuICAgICAgICAgIHdoaWxlIChpbmRleCA8IGVuZCkge1xuICAgICAgICAgICAgYmFzZTY0VkxRLmRlY29kZShhU3RyLCBpbmRleCwgdGVtcCk7XG4gICAgICAgICAgICB2YWx1ZSA9IHRlbXAudmFsdWU7XG4gICAgICAgICAgICBpbmRleCA9IHRlbXAucmVzdDtcbiAgICAgICAgICAgIHNlZ21lbnQucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNlZ21lbnQubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvdW5kIGEgc291cmNlLCBidXQgbm8gbGluZSBhbmQgY29sdW1uJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNlZ21lbnQubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvdW5kIGEgc291cmNlIGFuZCBsaW5lLCBidXQgbm8gY29sdW1uJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2FjaGVkU2VnbWVudHNbc3RyXSA9IHNlZ21lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZW5lcmF0ZWQgY29sdW1uLlxuICAgICAgICBtYXBwaW5nLmdlbmVyYXRlZENvbHVtbiA9IHByZXZpb3VzR2VuZXJhdGVkQ29sdW1uICsgc2VnbWVudFswXTtcbiAgICAgICAgcHJldmlvdXNHZW5lcmF0ZWRDb2x1bW4gPSBtYXBwaW5nLmdlbmVyYXRlZENvbHVtbjtcblxuICAgICAgICBpZiAoc2VnbWVudC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgLy8gT3JpZ2luYWwgc291cmNlLlxuICAgICAgICAgIG1hcHBpbmcuc291cmNlID0gcHJldmlvdXNTb3VyY2UgKyBzZWdtZW50WzFdO1xuICAgICAgICAgIHByZXZpb3VzU291cmNlICs9IHNlZ21lbnRbMV07XG5cbiAgICAgICAgICAvLyBPcmlnaW5hbCBsaW5lLlxuICAgICAgICAgIG1hcHBpbmcub3JpZ2luYWxMaW5lID0gcHJldmlvdXNPcmlnaW5hbExpbmUgKyBzZWdtZW50WzJdO1xuICAgICAgICAgIHByZXZpb3VzT3JpZ2luYWxMaW5lID0gbWFwcGluZy5vcmlnaW5hbExpbmU7XG4gICAgICAgICAgLy8gTGluZXMgYXJlIHN0b3JlZCAwLWJhc2VkXG4gICAgICAgICAgbWFwcGluZy5vcmlnaW5hbExpbmUgKz0gMTtcblxuICAgICAgICAgIC8vIE9yaWdpbmFsIGNvbHVtbi5cbiAgICAgICAgICBtYXBwaW5nLm9yaWdpbmFsQ29sdW1uID0gcHJldmlvdXNPcmlnaW5hbENvbHVtbiArIHNlZ21lbnRbM107XG4gICAgICAgICAgcHJldmlvdXNPcmlnaW5hbENvbHVtbiA9IG1hcHBpbmcub3JpZ2luYWxDb2x1bW47XG5cbiAgICAgICAgICBpZiAoc2VnbWVudC5sZW5ndGggPiA0KSB7XG4gICAgICAgICAgICAvLyBPcmlnaW5hbCBuYW1lLlxuICAgICAgICAgICAgbWFwcGluZy5uYW1lID0gcHJldmlvdXNOYW1lICsgc2VnbWVudFs0XTtcbiAgICAgICAgICAgIHByZXZpb3VzTmFtZSArPSBzZWdtZW50WzRdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGdlbmVyYXRlZE1hcHBpbmdzLnB1c2gobWFwcGluZyk7XG4gICAgICAgIGlmICh0eXBlb2YgbWFwcGluZy5vcmlnaW5hbExpbmUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgb3JpZ2luYWxNYXBwaW5ncy5wdXNoKG1hcHBpbmcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcXVpY2tTb3J0KGdlbmVyYXRlZE1hcHBpbmdzLCB1dGlsLmNvbXBhcmVCeUdlbmVyYXRlZFBvc2l0aW9uc0RlZmxhdGVkKTtcbiAgICB0aGlzLl9fZ2VuZXJhdGVkTWFwcGluZ3MgPSBnZW5lcmF0ZWRNYXBwaW5ncztcblxuICAgIHF1aWNrU29ydChvcmlnaW5hbE1hcHBpbmdzLCB1dGlsLmNvbXBhcmVCeU9yaWdpbmFsUG9zaXRpb25zKTtcbiAgICB0aGlzLl9fb3JpZ2luYWxNYXBwaW5ncyA9IG9yaWdpbmFsTWFwcGluZ3M7XG4gIH07XG5cbi8qKlxuICogRmluZCB0aGUgbWFwcGluZyB0aGF0IGJlc3QgbWF0Y2hlcyB0aGUgaHlwb3RoZXRpY2FsIFwibmVlZGxlXCIgbWFwcGluZyB0aGF0XG4gKiB3ZSBhcmUgc2VhcmNoaW5nIGZvciBpbiB0aGUgZ2l2ZW4gXCJoYXlzdGFja1wiIG9mIG1hcHBpbmdzLlxuICovXG5CYXNpY1NvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5fZmluZE1hcHBpbmcgPVxuICBmdW5jdGlvbiBTb3VyY2VNYXBDb25zdW1lcl9maW5kTWFwcGluZyhhTmVlZGxlLCBhTWFwcGluZ3MsIGFMaW5lTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYUNvbHVtbk5hbWUsIGFDb21wYXJhdG9yLCBhQmlhcykge1xuICAgIC8vIFRvIHJldHVybiB0aGUgcG9zaXRpb24gd2UgYXJlIHNlYXJjaGluZyBmb3IsIHdlIG11c3QgZmlyc3QgZmluZCB0aGVcbiAgICAvLyBtYXBwaW5nIGZvciB0aGUgZ2l2ZW4gcG9zaXRpb24gYW5kIHRoZW4gcmV0dXJuIHRoZSBvcHBvc2l0ZSBwb3NpdGlvbiBpdFxuICAgIC8vIHBvaW50cyB0by4gQmVjYXVzZSB0aGUgbWFwcGluZ3MgYXJlIHNvcnRlZCwgd2UgY2FuIHVzZSBiaW5hcnkgc2VhcmNoIHRvXG4gICAgLy8gZmluZCB0aGUgYmVzdCBtYXBwaW5nLlxuXG4gICAgaWYgKGFOZWVkbGVbYUxpbmVOYW1lXSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdMaW5lIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEsIGdvdCAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICsgYU5lZWRsZVthTGluZU5hbWVdKTtcbiAgICB9XG4gICAgaWYgKGFOZWVkbGVbYUNvbHVtbk5hbWVdIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ29sdW1uIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDAsIGdvdCAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICsgYU5lZWRsZVthQ29sdW1uTmFtZV0pO1xuICAgIH1cblxuICAgIHJldHVybiBiaW5hcnlTZWFyY2guc2VhcmNoKGFOZWVkbGUsIGFNYXBwaW5ncywgYUNvbXBhcmF0b3IsIGFCaWFzKTtcbiAgfTtcblxuLyoqXG4gKiBDb21wdXRlIHRoZSBsYXN0IGNvbHVtbiBmb3IgZWFjaCBnZW5lcmF0ZWQgbWFwcGluZy4gVGhlIGxhc3QgY29sdW1uIGlzXG4gKiBpbmNsdXNpdmUuXG4gKi9cbkJhc2ljU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlLmNvbXB1dGVDb2x1bW5TcGFucyA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcENvbnN1bWVyX2NvbXB1dGVDb2x1bW5TcGFucygpIHtcbiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5fZ2VuZXJhdGVkTWFwcGluZ3MubGVuZ3RoOyArK2luZGV4KSB7XG4gICAgICB2YXIgbWFwcGluZyA9IHRoaXMuX2dlbmVyYXRlZE1hcHBpbmdzW2luZGV4XTtcblxuICAgICAgLy8gTWFwcGluZ3MgZG8gbm90IGNvbnRhaW4gYSBmaWVsZCBmb3IgdGhlIGxhc3QgZ2VuZXJhdGVkIGNvbHVtbnQuIFdlXG4gICAgICAvLyBjYW4gY29tZSB1cCB3aXRoIGFuIG9wdGltaXN0aWMgZXN0aW1hdGUsIGhvd2V2ZXIsIGJ5IGFzc3VtaW5nIHRoYXRcbiAgICAgIC8vIG1hcHBpbmdzIGFyZSBjb250aWd1b3VzIChpLmUuIGdpdmVuIHR3byBjb25zZWN1dGl2ZSBtYXBwaW5ncywgdGhlXG4gICAgICAvLyBmaXJzdCBtYXBwaW5nIGVuZHMgd2hlcmUgdGhlIHNlY29uZCBvbmUgc3RhcnRzKS5cbiAgICAgIGlmIChpbmRleCArIDEgPCB0aGlzLl9nZW5lcmF0ZWRNYXBwaW5ncy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIG5leHRNYXBwaW5nID0gdGhpcy5fZ2VuZXJhdGVkTWFwcGluZ3NbaW5kZXggKyAxXTtcblxuICAgICAgICBpZiAobWFwcGluZy5nZW5lcmF0ZWRMaW5lID09PSBuZXh0TWFwcGluZy5nZW5lcmF0ZWRMaW5lKSB7XG4gICAgICAgICAgbWFwcGluZy5sYXN0R2VuZXJhdGVkQ29sdW1uID0gbmV4dE1hcHBpbmcuZ2VuZXJhdGVkQ29sdW1uIC0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBUaGUgbGFzdCBtYXBwaW5nIGZvciBlYWNoIGxpbmUgc3BhbnMgdGhlIGVudGlyZSBsaW5lLlxuICAgICAgbWFwcGluZy5sYXN0R2VuZXJhdGVkQ29sdW1uID0gSW5maW5pdHk7XG4gICAgfVxuICB9O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG9yaWdpbmFsIHNvdXJjZSwgbGluZSwgYW5kIGNvbHVtbiBpbmZvcm1hdGlvbiBmb3IgdGhlIGdlbmVyYXRlZFxuICogc291cmNlJ3MgbGluZSBhbmQgY29sdW1uIHBvc2l0aW9ucyBwcm92aWRlZC4gVGhlIG9ubHkgYXJndW1lbnQgaXMgYW4gb2JqZWN0XG4gKiB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAqXG4gKiAgIC0gbGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBnZW5lcmF0ZWQgc291cmNlLlxuICogICAtIGNvbHVtbjogVGhlIGNvbHVtbiBudW1iZXIgaW4gdGhlIGdlbmVyYXRlZCBzb3VyY2UuXG4gKiAgIC0gYmlhczogRWl0aGVyICdTb3VyY2VNYXBDb25zdW1lci5HUkVBVEVTVF9MT1dFUl9CT1VORCcgb3JcbiAqICAgICAnU291cmNlTWFwQ29uc3VtZXIuTEVBU1RfVVBQRVJfQk9VTkQnLiBTcGVjaWZpZXMgd2hldGhlciB0byByZXR1cm4gdGhlXG4gKiAgICAgY2xvc2VzdCBlbGVtZW50IHRoYXQgaXMgc21hbGxlciB0aGFuIG9yIGdyZWF0ZXIgdGhhbiB0aGUgb25lIHdlIGFyZVxuICogICAgIHNlYXJjaGluZyBmb3IsIHJlc3BlY3RpdmVseSwgaWYgdGhlIGV4YWN0IGVsZW1lbnQgY2Fubm90IGJlIGZvdW5kLlxuICogICAgIERlZmF1bHRzIHRvICdTb3VyY2VNYXBDb25zdW1lci5HUkVBVEVTVF9MT1dFUl9CT1VORCcuXG4gKlxuICogYW5kIGFuIG9iamVjdCBpcyByZXR1cm5lZCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAqXG4gKiAgIC0gc291cmNlOiBUaGUgb3JpZ2luYWwgc291cmNlIGZpbGUsIG9yIG51bGwuXG4gKiAgIC0gbGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBvcmlnaW5hbCBzb3VyY2UsIG9yIG51bGwuXG4gKiAgIC0gY29sdW1uOiBUaGUgY29sdW1uIG51bWJlciBpbiB0aGUgb3JpZ2luYWwgc291cmNlLCBvciBudWxsLlxuICogICAtIG5hbWU6IFRoZSBvcmlnaW5hbCBpZGVudGlmaWVyLCBvciBudWxsLlxuICovXG5CYXNpY1NvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5vcmlnaW5hbFBvc2l0aW9uRm9yID1cbiAgZnVuY3Rpb24gU291cmNlTWFwQ29uc3VtZXJfb3JpZ2luYWxQb3NpdGlvbkZvcihhQXJncykge1xuICAgIHZhciBuZWVkbGUgPSB7XG4gICAgICBnZW5lcmF0ZWRMaW5lOiB1dGlsLmdldEFyZyhhQXJncywgJ2xpbmUnKSxcbiAgICAgIGdlbmVyYXRlZENvbHVtbjogdXRpbC5nZXRBcmcoYUFyZ3MsICdjb2x1bW4nKVxuICAgIH07XG5cbiAgICB2YXIgaW5kZXggPSB0aGlzLl9maW5kTWFwcGluZyhcbiAgICAgIG5lZWRsZSxcbiAgICAgIHRoaXMuX2dlbmVyYXRlZE1hcHBpbmdzLFxuICAgICAgXCJnZW5lcmF0ZWRMaW5lXCIsXG4gICAgICBcImdlbmVyYXRlZENvbHVtblwiLFxuICAgICAgdXRpbC5jb21wYXJlQnlHZW5lcmF0ZWRQb3NpdGlvbnNEZWZsYXRlZCxcbiAgICAgIHV0aWwuZ2V0QXJnKGFBcmdzLCAnYmlhcycsIFNvdXJjZU1hcENvbnN1bWVyLkdSRUFURVNUX0xPV0VSX0JPVU5EKVxuICAgICk7XG5cbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgdmFyIG1hcHBpbmcgPSB0aGlzLl9nZW5lcmF0ZWRNYXBwaW5nc1tpbmRleF07XG5cbiAgICAgIGlmIChtYXBwaW5nLmdlbmVyYXRlZExpbmUgPT09IG5lZWRsZS5nZW5lcmF0ZWRMaW5lKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSB1dGlsLmdldEFyZyhtYXBwaW5nLCAnc291cmNlJywgbnVsbCk7XG4gICAgICAgIGlmIChzb3VyY2UgIT09IG51bGwpIHtcbiAgICAgICAgICBzb3VyY2UgPSB0aGlzLl9zb3VyY2VzLmF0KHNvdXJjZSk7XG4gICAgICAgICAgaWYgKHRoaXMuc291cmNlUm9vdCAhPSBudWxsKSB7XG4gICAgICAgICAgICBzb3VyY2UgPSB1dGlsLmpvaW4odGhpcy5zb3VyY2VSb290LCBzb3VyY2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgbmFtZSA9IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICduYW1lJywgbnVsbCk7XG4gICAgICAgIGlmIChuYW1lICE9PSBudWxsKSB7XG4gICAgICAgICAgbmFtZSA9IHRoaXMuX25hbWVzLmF0KG5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICAgICAgbGluZTogdXRpbC5nZXRBcmcobWFwcGluZywgJ29yaWdpbmFsTGluZScsIG51bGwpLFxuICAgICAgICAgIGNvbHVtbjogdXRpbC5nZXRBcmcobWFwcGluZywgJ29yaWdpbmFsQ29sdW1uJywgbnVsbCksXG4gICAgICAgICAgbmFtZTogbmFtZVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2U6IG51bGwsXG4gICAgICBsaW5lOiBudWxsLFxuICAgICAgY29sdW1uOiBudWxsLFxuICAgICAgbmFtZTogbnVsbFxuICAgIH07XG4gIH07XG5cbi8qKlxuICogUmV0dXJuIHRydWUgaWYgd2UgaGF2ZSB0aGUgc291cmNlIGNvbnRlbnQgZm9yIGV2ZXJ5IHNvdXJjZSBpbiB0aGUgc291cmNlXG4gKiBtYXAsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuQmFzaWNTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuaGFzQ29udGVudHNPZkFsbFNvdXJjZXMgPVxuICBmdW5jdGlvbiBCYXNpY1NvdXJjZU1hcENvbnN1bWVyX2hhc0NvbnRlbnRzT2ZBbGxTb3VyY2VzKCkge1xuICAgIGlmICghdGhpcy5zb3VyY2VzQ29udGVudCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zb3VyY2VzQ29udGVudC5sZW5ndGggPj0gdGhpcy5fc291cmNlcy5zaXplKCkgJiZcbiAgICAgICF0aGlzLnNvdXJjZXNDb250ZW50LnNvbWUoZnVuY3Rpb24gKHNjKSB7IHJldHVybiBzYyA9PSBudWxsOyB9KTtcbiAgfTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBvcmlnaW5hbCBzb3VyY2UgY29udGVudC4gVGhlIG9ubHkgYXJndW1lbnQgaXMgdGhlIHVybCBvZiB0aGVcbiAqIG9yaWdpbmFsIHNvdXJjZSBmaWxlLiBSZXR1cm5zIG51bGwgaWYgbm8gb3JpZ2luYWwgc291cmNlIGNvbnRlbnQgaXNcbiAqIGF2YWlsYWJsZS5cbiAqL1xuQmFzaWNTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuc291cmNlQ29udGVudEZvciA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcENvbnN1bWVyX3NvdXJjZUNvbnRlbnRGb3IoYVNvdXJjZSwgbnVsbE9uTWlzc2luZykge1xuICAgIGlmICghdGhpcy5zb3VyY2VzQ29udGVudCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc291cmNlUm9vdCAhPSBudWxsKSB7XG4gICAgICBhU291cmNlID0gdXRpbC5yZWxhdGl2ZSh0aGlzLnNvdXJjZVJvb3QsIGFTb3VyY2UpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9zb3VyY2VzLmhhcyhhU291cmNlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuc291cmNlc0NvbnRlbnRbdGhpcy5fc291cmNlcy5pbmRleE9mKGFTb3VyY2UpXTtcbiAgICB9XG5cbiAgICB2YXIgdXJsO1xuICAgIGlmICh0aGlzLnNvdXJjZVJvb3QgIT0gbnVsbFxuICAgICAgICAmJiAodXJsID0gdXRpbC51cmxQYXJzZSh0aGlzLnNvdXJjZVJvb3QpKSkge1xuICAgICAgLy8gWFhYOiBmaWxlOi8vIFVSSXMgYW5kIGFic29sdXRlIHBhdGhzIGxlYWQgdG8gdW5leHBlY3RlZCBiZWhhdmlvciBmb3JcbiAgICAgIC8vIG1hbnkgdXNlcnMuIFdlIGNhbiBoZWxwIHRoZW0gb3V0IHdoZW4gdGhleSBleHBlY3QgZmlsZTovLyBVUklzIHRvXG4gICAgICAvLyBiZWhhdmUgbGlrZSBpdCB3b3VsZCBpZiB0aGV5IHdlcmUgcnVubmluZyBhIGxvY2FsIEhUVFAgc2VydmVyLiBTZWVcbiAgICAgIC8vIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTg4NTU5Ny5cbiAgICAgIHZhciBmaWxlVXJpQWJzUGF0aCA9IGFTb3VyY2UucmVwbGFjZSgvXmZpbGU6XFwvXFwvLywgXCJcIik7XG4gICAgICBpZiAodXJsLnNjaGVtZSA9PSBcImZpbGVcIlxuICAgICAgICAgICYmIHRoaXMuX3NvdXJjZXMuaGFzKGZpbGVVcmlBYnNQYXRoKSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2VzQ29udGVudFt0aGlzLl9zb3VyY2VzLmluZGV4T2YoZmlsZVVyaUFic1BhdGgpXVxuICAgICAgfVxuXG4gICAgICBpZiAoKCF1cmwucGF0aCB8fCB1cmwucGF0aCA9PSBcIi9cIilcbiAgICAgICAgICAmJiB0aGlzLl9zb3VyY2VzLmhhcyhcIi9cIiArIGFTb3VyY2UpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNvdXJjZXNDb250ZW50W3RoaXMuX3NvdXJjZXMuaW5kZXhPZihcIi9cIiArIGFTb3VyY2UpXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgcmVjdXJzaXZlbHkgZnJvbVxuICAgIC8vIEluZGV4ZWRTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuc291cmNlQ29udGVudEZvci4gSW4gdGhhdCBjYXNlLCB3ZVxuICAgIC8vIGRvbid0IHdhbnQgdG8gdGhyb3cgaWYgd2UgY2FuJ3QgZmluZCB0aGUgc291cmNlIC0gd2UganVzdCB3YW50IHRvXG4gICAgLy8gcmV0dXJuIG51bGwsIHNvIHdlIHByb3ZpZGUgYSBmbGFnIHRvIGV4aXQgZ3JhY2VmdWxseS5cbiAgICBpZiAobnVsbE9uTWlzc2luZykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIicgKyBhU291cmNlICsgJ1wiIGlzIG5vdCBpbiB0aGUgU291cmNlTWFwLicpO1xuICAgIH1cbiAgfTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBnZW5lcmF0ZWQgbGluZSBhbmQgY29sdW1uIGluZm9ybWF0aW9uIGZvciB0aGUgb3JpZ2luYWwgc291cmNlLFxuICogbGluZSwgYW5kIGNvbHVtbiBwb3NpdGlvbnMgcHJvdmlkZWQuIFRoZSBvbmx5IGFyZ3VtZW50IGlzIGFuIG9iamVjdCB3aXRoXG4gKiB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIHNvdXJjZTogVGhlIGZpbGVuYW1lIG9mIHRoZSBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIC0gbGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIC0gY29sdW1uOiBUaGUgY29sdW1uIG51bWJlciBpbiB0aGUgb3JpZ2luYWwgc291cmNlLlxuICogICAtIGJpYXM6IEVpdGhlciAnU291cmNlTWFwQ29uc3VtZXIuR1JFQVRFU1RfTE9XRVJfQk9VTkQnIG9yXG4gKiAgICAgJ1NvdXJjZU1hcENvbnN1bWVyLkxFQVNUX1VQUEVSX0JPVU5EJy4gU3BlY2lmaWVzIHdoZXRoZXIgdG8gcmV0dXJuIHRoZVxuICogICAgIGNsb3Nlc3QgZWxlbWVudCB0aGF0IGlzIHNtYWxsZXIgdGhhbiBvciBncmVhdGVyIHRoYW4gdGhlIG9uZSB3ZSBhcmVcbiAqICAgICBzZWFyY2hpbmcgZm9yLCByZXNwZWN0aXZlbHksIGlmIHRoZSBleGFjdCBlbGVtZW50IGNhbm5vdCBiZSBmb3VuZC5cbiAqICAgICBEZWZhdWx0cyB0byAnU291cmNlTWFwQ29uc3VtZXIuR1JFQVRFU1RfTE9XRVJfQk9VTkQnLlxuICpcbiAqIGFuZCBhbiBvYmplY3QgaXMgcmV0dXJuZWQgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIGxpbmU6IFRoZSBsaW5lIG51bWJlciBpbiB0aGUgZ2VuZXJhdGVkIHNvdXJjZSwgb3IgbnVsbC5cbiAqICAgLSBjb2x1bW46IFRoZSBjb2x1bW4gbnVtYmVyIGluIHRoZSBnZW5lcmF0ZWQgc291cmNlLCBvciBudWxsLlxuICovXG5CYXNpY1NvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5nZW5lcmF0ZWRQb3NpdGlvbkZvciA9XG4gIGZ1bmN0aW9uIFNvdXJjZU1hcENvbnN1bWVyX2dlbmVyYXRlZFBvc2l0aW9uRm9yKGFBcmdzKSB7XG4gICAgdmFyIHNvdXJjZSA9IHV0aWwuZ2V0QXJnKGFBcmdzLCAnc291cmNlJyk7XG4gICAgaWYgKHRoaXMuc291cmNlUm9vdCAhPSBudWxsKSB7XG4gICAgICBzb3VyY2UgPSB1dGlsLnJlbGF0aXZlKHRoaXMuc291cmNlUm9vdCwgc291cmNlKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLl9zb3VyY2VzLmhhcyhzb3VyY2UpKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBsaW5lOiBudWxsLFxuICAgICAgICBjb2x1bW46IG51bGwsXG4gICAgICAgIGxhc3RDb2x1bW46IG51bGxcbiAgICAgIH07XG4gICAgfVxuICAgIHNvdXJjZSA9IHRoaXMuX3NvdXJjZXMuaW5kZXhPZihzb3VyY2UpO1xuXG4gICAgdmFyIG5lZWRsZSA9IHtcbiAgICAgIHNvdXJjZTogc291cmNlLFxuICAgICAgb3JpZ2luYWxMaW5lOiB1dGlsLmdldEFyZyhhQXJncywgJ2xpbmUnKSxcbiAgICAgIG9yaWdpbmFsQ29sdW1uOiB1dGlsLmdldEFyZyhhQXJncywgJ2NvbHVtbicpXG4gICAgfTtcblxuICAgIHZhciBpbmRleCA9IHRoaXMuX2ZpbmRNYXBwaW5nKFxuICAgICAgbmVlZGxlLFxuICAgICAgdGhpcy5fb3JpZ2luYWxNYXBwaW5ncyxcbiAgICAgIFwib3JpZ2luYWxMaW5lXCIsXG4gICAgICBcIm9yaWdpbmFsQ29sdW1uXCIsXG4gICAgICB1dGlsLmNvbXBhcmVCeU9yaWdpbmFsUG9zaXRpb25zLFxuICAgICAgdXRpbC5nZXRBcmcoYUFyZ3MsICdiaWFzJywgU291cmNlTWFwQ29uc3VtZXIuR1JFQVRFU1RfTE9XRVJfQk9VTkQpXG4gICAgKTtcblxuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB2YXIgbWFwcGluZyA9IHRoaXMuX29yaWdpbmFsTWFwcGluZ3NbaW5kZXhdO1xuXG4gICAgICBpZiAobWFwcGluZy5zb3VyY2UgPT09IG5lZWRsZS5zb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBsaW5lOiB1dGlsLmdldEFyZyhtYXBwaW5nLCAnZ2VuZXJhdGVkTGluZScsIG51bGwpLFxuICAgICAgICAgIGNvbHVtbjogdXRpbC5nZXRBcmcobWFwcGluZywgJ2dlbmVyYXRlZENvbHVtbicsIG51bGwpLFxuICAgICAgICAgIGxhc3RDb2x1bW46IHV0aWwuZ2V0QXJnKG1hcHBpbmcsICdsYXN0R2VuZXJhdGVkQ29sdW1uJywgbnVsbClcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGluZTogbnVsbCxcbiAgICAgIGNvbHVtbjogbnVsbCxcbiAgICAgIGxhc3RDb2x1bW46IG51bGxcbiAgICB9O1xuICB9O1xuXG5leHBvcnRzLkJhc2ljU291cmNlTWFwQ29uc3VtZXIgPSBCYXNpY1NvdXJjZU1hcENvbnN1bWVyO1xuXG4vKipcbiAqIEFuIEluZGV4ZWRTb3VyY2VNYXBDb25zdW1lciBpbnN0YW5jZSByZXByZXNlbnRzIGEgcGFyc2VkIHNvdXJjZSBtYXAgd2hpY2hcbiAqIHdlIGNhbiBxdWVyeSBmb3IgaW5mb3JtYXRpb24uIEl0IGRpZmZlcnMgZnJvbSBCYXNpY1NvdXJjZU1hcENvbnN1bWVyIGluXG4gKiB0aGF0IGl0IHRha2VzIFwiaW5kZXhlZFwiIHNvdXJjZSBtYXBzIChpLmUuIG9uZXMgd2l0aCBhIFwic2VjdGlvbnNcIiBmaWVsZCkgYXNcbiAqIGlucHV0LlxuICpcbiAqIFRoZSBvbmx5IHBhcmFtZXRlciBpcyBhIHJhdyBzb3VyY2UgbWFwIChlaXRoZXIgYXMgYSBKU09OIHN0cmluZywgb3IgYWxyZWFkeVxuICogcGFyc2VkIHRvIGFuIG9iamVjdCkuIEFjY29yZGluZyB0byB0aGUgc3BlYyBmb3IgaW5kZXhlZCBzb3VyY2UgbWFwcywgdGhleVxuICogaGF2ZSB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXM6XG4gKlxuICogICAtIHZlcnNpb246IFdoaWNoIHZlcnNpb24gb2YgdGhlIHNvdXJjZSBtYXAgc3BlYyB0aGlzIG1hcCBpcyBmb2xsb3dpbmcuXG4gKiAgIC0gZmlsZTogT3B0aW9uYWwuIFRoZSBnZW5lcmF0ZWQgZmlsZSB0aGlzIHNvdXJjZSBtYXAgaXMgYXNzb2NpYXRlZCB3aXRoLlxuICogICAtIHNlY3Rpb25zOiBBIGxpc3Qgb2Ygc2VjdGlvbiBkZWZpbml0aW9ucy5cbiAqXG4gKiBFYWNoIHZhbHVlIHVuZGVyIHRoZSBcInNlY3Rpb25zXCIgZmllbGQgaGFzIHR3byBmaWVsZHM6XG4gKiAgIC0gb2Zmc2V0OiBUaGUgb2Zmc2V0IGludG8gdGhlIG9yaWdpbmFsIHNwZWNpZmllZCBhdCB3aGljaCB0aGlzIHNlY3Rpb25cbiAqICAgICAgIGJlZ2lucyB0byBhcHBseSwgZGVmaW5lZCBhcyBhbiBvYmplY3Qgd2l0aCBhIFwibGluZVwiIGFuZCBcImNvbHVtblwiXG4gKiAgICAgICBmaWVsZC5cbiAqICAgLSBtYXA6IEEgc291cmNlIG1hcCBkZWZpbml0aW9uLiBUaGlzIHNvdXJjZSBtYXAgY291bGQgYWxzbyBiZSBpbmRleGVkLFxuICogICAgICAgYnV0IGRvZXNuJ3QgaGF2ZSB0byBiZS5cbiAqXG4gKiBJbnN0ZWFkIG9mIHRoZSBcIm1hcFwiIGZpZWxkLCBpdCdzIGFsc28gcG9zc2libGUgdG8gaGF2ZSBhIFwidXJsXCIgZmllbGRcbiAqIHNwZWNpZnlpbmcgYSBVUkwgdG8gcmV0cmlldmUgYSBzb3VyY2UgbWFwIGZyb20sIGJ1dCB0aGF0J3MgY3VycmVudGx5XG4gKiB1bnN1cHBvcnRlZC5cbiAqXG4gKiBIZXJlJ3MgYW4gZXhhbXBsZSBzb3VyY2UgbWFwLCB0YWtlbiBmcm9tIHRoZSBzb3VyY2UgbWFwIHNwZWNbMF0sIGJ1dFxuICogbW9kaWZpZWQgdG8gb21pdCBhIHNlY3Rpb24gd2hpY2ggdXNlcyB0aGUgXCJ1cmxcIiBmaWVsZC5cbiAqXG4gKiAge1xuICogICAgdmVyc2lvbiA6IDMsXG4gKiAgICBmaWxlOiBcImFwcC5qc1wiLFxuICogICAgc2VjdGlvbnM6IFt7XG4gKiAgICAgIG9mZnNldDoge2xpbmU6MTAwLCBjb2x1bW46MTB9LFxuICogICAgICBtYXA6IHtcbiAqICAgICAgICB2ZXJzaW9uIDogMyxcbiAqICAgICAgICBmaWxlOiBcInNlY3Rpb24uanNcIixcbiAqICAgICAgICBzb3VyY2VzOiBbXCJmb28uanNcIiwgXCJiYXIuanNcIl0sXG4gKiAgICAgICAgbmFtZXM6IFtcInNyY1wiLCBcIm1hcHNcIiwgXCJhcmVcIiwgXCJmdW5cIl0sXG4gKiAgICAgICAgbWFwcGluZ3M6IFwiQUFBQSxFOztBQkNERTtcIlxuICogICAgICB9XG4gKiAgICB9XSxcbiAqICB9XG4gKlxuICogWzBdOiBodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9kb2N1bWVudC9kLzFVMVJHQWVoUXdSeXBVVG92RjFLUmxwaU9GemUwYi1fMmdjNmZBSDBLWTBrL2VkaXQjaGVhZGluZz1oLjUzNWVzM3hlcHJndFxuICovXG5mdW5jdGlvbiBJbmRleGVkU291cmNlTWFwQ29uc3VtZXIoYVNvdXJjZU1hcCkge1xuICB2YXIgc291cmNlTWFwID0gYVNvdXJjZU1hcDtcbiAgaWYgKHR5cGVvZiBhU291cmNlTWFwID09PSAnc3RyaW5nJykge1xuICAgIHNvdXJjZU1hcCA9IEpTT04ucGFyc2UoYVNvdXJjZU1hcC5yZXBsYWNlKC9eXFwpXFxdXFx9Jy8sICcnKSk7XG4gIH1cblxuICB2YXIgdmVyc2lvbiA9IHV0aWwuZ2V0QXJnKHNvdXJjZU1hcCwgJ3ZlcnNpb24nKTtcbiAgdmFyIHNlY3Rpb25zID0gdXRpbC5nZXRBcmcoc291cmNlTWFwLCAnc2VjdGlvbnMnKTtcblxuICBpZiAodmVyc2lvbiAhPSB0aGlzLl92ZXJzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCB2ZXJzaW9uOiAnICsgdmVyc2lvbik7XG4gIH1cblxuICB0aGlzLl9zb3VyY2VzID0gbmV3IEFycmF5U2V0KCk7XG4gIHRoaXMuX25hbWVzID0gbmV3IEFycmF5U2V0KCk7XG5cbiAgdmFyIGxhc3RPZmZzZXQgPSB7XG4gICAgbGluZTogLTEsXG4gICAgY29sdW1uOiAwXG4gIH07XG4gIHRoaXMuX3NlY3Rpb25zID0gc2VjdGlvbnMubWFwKGZ1bmN0aW9uIChzKSB7XG4gICAgaWYgKHMudXJsKSB7XG4gICAgICAvLyBUaGUgdXJsIGZpZWxkIHdpbGwgcmVxdWlyZSBzdXBwb3J0IGZvciBhc3luY2hyb25pY2l0eS5cbiAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbW96aWxsYS9zb3VyY2UtbWFwL2lzc3Vlcy8xNlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTdXBwb3J0IGZvciB1cmwgZmllbGQgaW4gc2VjdGlvbnMgbm90IGltcGxlbWVudGVkLicpO1xuICAgIH1cbiAgICB2YXIgb2Zmc2V0ID0gdXRpbC5nZXRBcmcocywgJ29mZnNldCcpO1xuICAgIHZhciBvZmZzZXRMaW5lID0gdXRpbC5nZXRBcmcob2Zmc2V0LCAnbGluZScpO1xuICAgIHZhciBvZmZzZXRDb2x1bW4gPSB1dGlsLmdldEFyZyhvZmZzZXQsICdjb2x1bW4nKTtcblxuICAgIGlmIChvZmZzZXRMaW5lIDwgbGFzdE9mZnNldC5saW5lIHx8XG4gICAgICAgIChvZmZzZXRMaW5lID09PSBsYXN0T2Zmc2V0LmxpbmUgJiYgb2Zmc2V0Q29sdW1uIDwgbGFzdE9mZnNldC5jb2x1bW4pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NlY3Rpb24gb2Zmc2V0cyBtdXN0IGJlIG9yZGVyZWQgYW5kIG5vbi1vdmVybGFwcGluZy4nKTtcbiAgICB9XG4gICAgbGFzdE9mZnNldCA9IG9mZnNldDtcblxuICAgIHJldHVybiB7XG4gICAgICBnZW5lcmF0ZWRPZmZzZXQ6IHtcbiAgICAgICAgLy8gVGhlIG9mZnNldCBmaWVsZHMgYXJlIDAtYmFzZWQsIGJ1dCB3ZSB1c2UgMS1iYXNlZCBpbmRpY2VzIHdoZW5cbiAgICAgICAgLy8gZW5jb2RpbmcvZGVjb2RpbmcgZnJvbSBWTFEuXG4gICAgICAgIGdlbmVyYXRlZExpbmU6IG9mZnNldExpbmUgKyAxLFxuICAgICAgICBnZW5lcmF0ZWRDb2x1bW46IG9mZnNldENvbHVtbiArIDFcbiAgICAgIH0sXG4gICAgICBjb25zdW1lcjogbmV3IFNvdXJjZU1hcENvbnN1bWVyKHV0aWwuZ2V0QXJnKHMsICdtYXAnKSlcbiAgICB9XG4gIH0pO1xufVxuXG5JbmRleGVkU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUpO1xuSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFNvdXJjZU1hcENvbnN1bWVyO1xuXG4vKipcbiAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBzb3VyY2UgbWFwcGluZyBzcGVjIHRoYXQgd2UgYXJlIGNvbnN1bWluZy5cbiAqL1xuSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5fdmVyc2lvbiA9IDM7XG5cbi8qKlxuICogVGhlIGxpc3Qgb2Ygb3JpZ2luYWwgc291cmNlcy5cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEluZGV4ZWRTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUsICdzb3VyY2VzJywge1xuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc291cmNlcyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fc2VjdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdGhpcy5fc2VjdGlvbnNbaV0uY29uc3VtZXIuc291cmNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBzb3VyY2VzLnB1c2godGhpcy5fc2VjdGlvbnNbaV0uY29uc3VtZXIuc291cmNlc1tqXSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzb3VyY2VzO1xuICB9XG59KTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBvcmlnaW5hbCBzb3VyY2UsIGxpbmUsIGFuZCBjb2x1bW4gaW5mb3JtYXRpb24gZm9yIHRoZSBnZW5lcmF0ZWRcbiAqIHNvdXJjZSdzIGxpbmUgYW5kIGNvbHVtbiBwb3NpdGlvbnMgcHJvdmlkZWQuIFRoZSBvbmx5IGFyZ3VtZW50IGlzIGFuIG9iamVjdFxuICogd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIGxpbmU6IFRoZSBsaW5lIG51bWJlciBpbiB0aGUgZ2VuZXJhdGVkIHNvdXJjZS5cbiAqICAgLSBjb2x1bW46IFRoZSBjb2x1bW4gbnVtYmVyIGluIHRoZSBnZW5lcmF0ZWQgc291cmNlLlxuICpcbiAqIGFuZCBhbiBvYmplY3QgaXMgcmV0dXJuZWQgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIHNvdXJjZTogVGhlIG9yaWdpbmFsIHNvdXJjZSBmaWxlLCBvciBudWxsLlxuICogICAtIGxpbmU6IFRoZSBsaW5lIG51bWJlciBpbiB0aGUgb3JpZ2luYWwgc291cmNlLCBvciBudWxsLlxuICogICAtIGNvbHVtbjogVGhlIGNvbHVtbiBudW1iZXIgaW4gdGhlIG9yaWdpbmFsIHNvdXJjZSwgb3IgbnVsbC5cbiAqICAgLSBuYW1lOiBUaGUgb3JpZ2luYWwgaWRlbnRpZmllciwgb3IgbnVsbC5cbiAqL1xuSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5vcmlnaW5hbFBvc2l0aW9uRm9yID1cbiAgZnVuY3Rpb24gSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyX29yaWdpbmFsUG9zaXRpb25Gb3IoYUFyZ3MpIHtcbiAgICB2YXIgbmVlZGxlID0ge1xuICAgICAgZ2VuZXJhdGVkTGluZTogdXRpbC5nZXRBcmcoYUFyZ3MsICdsaW5lJyksXG4gICAgICBnZW5lcmF0ZWRDb2x1bW46IHV0aWwuZ2V0QXJnKGFBcmdzLCAnY29sdW1uJylcbiAgICB9O1xuXG4gICAgLy8gRmluZCB0aGUgc2VjdGlvbiBjb250YWluaW5nIHRoZSBnZW5lcmF0ZWQgcG9zaXRpb24gd2UncmUgdHJ5aW5nIHRvIG1hcFxuICAgIC8vIHRvIGFuIG9yaWdpbmFsIHBvc2l0aW9uLlxuICAgIHZhciBzZWN0aW9uSW5kZXggPSBiaW5hcnlTZWFyY2guc2VhcmNoKG5lZWRsZSwgdGhpcy5fc2VjdGlvbnMsXG4gICAgICBmdW5jdGlvbihuZWVkbGUsIHNlY3Rpb24pIHtcbiAgICAgICAgdmFyIGNtcCA9IG5lZWRsZS5nZW5lcmF0ZWRMaW5lIC0gc2VjdGlvbi5nZW5lcmF0ZWRPZmZzZXQuZ2VuZXJhdGVkTGluZTtcbiAgICAgICAgaWYgKGNtcCkge1xuICAgICAgICAgIHJldHVybiBjbXA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKG5lZWRsZS5nZW5lcmF0ZWRDb2x1bW4gLVxuICAgICAgICAgICAgICAgIHNlY3Rpb24uZ2VuZXJhdGVkT2Zmc2V0LmdlbmVyYXRlZENvbHVtbik7XG4gICAgICB9KTtcbiAgICB2YXIgc2VjdGlvbiA9IHRoaXMuX3NlY3Rpb25zW3NlY3Rpb25JbmRleF07XG5cbiAgICBpZiAoIXNlY3Rpb24pIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNvdXJjZTogbnVsbCxcbiAgICAgICAgbGluZTogbnVsbCxcbiAgICAgICAgY29sdW1uOiBudWxsLFxuICAgICAgICBuYW1lOiBudWxsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBzZWN0aW9uLmNvbnN1bWVyLm9yaWdpbmFsUG9zaXRpb25Gb3Ioe1xuICAgICAgbGluZTogbmVlZGxlLmdlbmVyYXRlZExpbmUgLVxuICAgICAgICAoc2VjdGlvbi5nZW5lcmF0ZWRPZmZzZXQuZ2VuZXJhdGVkTGluZSAtIDEpLFxuICAgICAgY29sdW1uOiBuZWVkbGUuZ2VuZXJhdGVkQ29sdW1uIC1cbiAgICAgICAgKHNlY3Rpb24uZ2VuZXJhdGVkT2Zmc2V0LmdlbmVyYXRlZExpbmUgPT09IG5lZWRsZS5nZW5lcmF0ZWRMaW5lXG4gICAgICAgICA/IHNlY3Rpb24uZ2VuZXJhdGVkT2Zmc2V0LmdlbmVyYXRlZENvbHVtbiAtIDFcbiAgICAgICAgIDogMCksXG4gICAgICBiaWFzOiBhQXJncy5iaWFzXG4gICAgfSk7XG4gIH07XG5cbi8qKlxuICogUmV0dXJuIHRydWUgaWYgd2UgaGF2ZSB0aGUgc291cmNlIGNvbnRlbnQgZm9yIGV2ZXJ5IHNvdXJjZSBpbiB0aGUgc291cmNlXG4gKiBtYXAsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyLnByb3RvdHlwZS5oYXNDb250ZW50c09mQWxsU291cmNlcyA9XG4gIGZ1bmN0aW9uIEluZGV4ZWRTb3VyY2VNYXBDb25zdW1lcl9oYXNDb250ZW50c09mQWxsU291cmNlcygpIHtcbiAgICByZXR1cm4gdGhpcy5fc2VjdGlvbnMuZXZlcnkoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzLmNvbnN1bWVyLmhhc0NvbnRlbnRzT2ZBbGxTb3VyY2VzKCk7XG4gICAgfSk7XG4gIH07XG5cbi8qKlxuICogUmV0dXJucyB0aGUgb3JpZ2luYWwgc291cmNlIGNvbnRlbnQuIFRoZSBvbmx5IGFyZ3VtZW50IGlzIHRoZSB1cmwgb2YgdGhlXG4gKiBvcmlnaW5hbCBzb3VyY2UgZmlsZS4gUmV0dXJucyBudWxsIGlmIG5vIG9yaWdpbmFsIHNvdXJjZSBjb250ZW50IGlzXG4gKiBhdmFpbGFibGUuXG4gKi9cbkluZGV4ZWRTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuc291cmNlQ29udGVudEZvciA9XG4gIGZ1bmN0aW9uIEluZGV4ZWRTb3VyY2VNYXBDb25zdW1lcl9zb3VyY2VDb250ZW50Rm9yKGFTb3VyY2UsIG51bGxPbk1pc3NpbmcpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3NlY3Rpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgc2VjdGlvbiA9IHRoaXMuX3NlY3Rpb25zW2ldO1xuXG4gICAgICB2YXIgY29udGVudCA9IHNlY3Rpb24uY29uc3VtZXIuc291cmNlQ29udGVudEZvcihhU291cmNlLCB0cnVlKTtcbiAgICAgIGlmIChjb250ZW50KSB7XG4gICAgICAgIHJldHVybiBjb250ZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobnVsbE9uTWlzc2luZykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIicgKyBhU291cmNlICsgJ1wiIGlzIG5vdCBpbiB0aGUgU291cmNlTWFwLicpO1xuICAgIH1cbiAgfTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBnZW5lcmF0ZWQgbGluZSBhbmQgY29sdW1uIGluZm9ybWF0aW9uIGZvciB0aGUgb3JpZ2luYWwgc291cmNlLFxuICogbGluZSwgYW5kIGNvbHVtbiBwb3NpdGlvbnMgcHJvdmlkZWQuIFRoZSBvbmx5IGFyZ3VtZW50IGlzIGFuIG9iamVjdCB3aXRoXG4gKiB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIHNvdXJjZTogVGhlIGZpbGVuYW1lIG9mIHRoZSBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIC0gbGluZTogVGhlIGxpbmUgbnVtYmVyIGluIHRoZSBvcmlnaW5hbCBzb3VyY2UuXG4gKiAgIC0gY29sdW1uOiBUaGUgY29sdW1uIG51bWJlciBpbiB0aGUgb3JpZ2luYWwgc291cmNlLlxuICpcbiAqIGFuZCBhbiBvYmplY3QgaXMgcmV0dXJuZWQgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogICAtIGxpbmU6IFRoZSBsaW5lIG51bWJlciBpbiB0aGUgZ2VuZXJhdGVkIHNvdXJjZSwgb3IgbnVsbC5cbiAqICAgLSBjb2x1bW46IFRoZSBjb2x1bW4gbnVtYmVyIGluIHRoZSBnZW5lcmF0ZWQgc291cmNlLCBvciBudWxsLlxuICovXG5JbmRleGVkU291cmNlTWFwQ29uc3VtZXIucHJvdG90eXBlLmdlbmVyYXRlZFBvc2l0aW9uRm9yID1cbiAgZnVuY3Rpb24gSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyX2dlbmVyYXRlZFBvc2l0aW9uRm9yKGFBcmdzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9zZWN0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNlY3Rpb24gPSB0aGlzLl9zZWN0aW9uc1tpXTtcblxuICAgICAgLy8gT25seSBjb25zaWRlciB0aGlzIHNlY3Rpb24gaWYgdGhlIHJlcXVlc3RlZCBzb3VyY2UgaXMgaW4gdGhlIGxpc3Qgb2ZcbiAgICAgIC8vIHNvdXJjZXMgb2YgdGhlIGNvbnN1bWVyLlxuICAgICAgaWYgKHNlY3Rpb24uY29uc3VtZXIuc291cmNlcy5pbmRleE9mKHV0aWwuZ2V0QXJnKGFBcmdzLCAnc291cmNlJykpID09PSAtMSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHZhciBnZW5lcmF0ZWRQb3NpdGlvbiA9IHNlY3Rpb24uY29uc3VtZXIuZ2VuZXJhdGVkUG9zaXRpb25Gb3IoYUFyZ3MpO1xuICAgICAgaWYgKGdlbmVyYXRlZFBvc2l0aW9uKSB7XG4gICAgICAgIHZhciByZXQgPSB7XG4gICAgICAgICAgbGluZTogZ2VuZXJhdGVkUG9zaXRpb24ubGluZSArXG4gICAgICAgICAgICAoc2VjdGlvbi5nZW5lcmF0ZWRPZmZzZXQuZ2VuZXJhdGVkTGluZSAtIDEpLFxuICAgICAgICAgIGNvbHVtbjogZ2VuZXJhdGVkUG9zaXRpb24uY29sdW1uICtcbiAgICAgICAgICAgIChzZWN0aW9uLmdlbmVyYXRlZE9mZnNldC5nZW5lcmF0ZWRMaW5lID09PSBnZW5lcmF0ZWRQb3NpdGlvbi5saW5lXG4gICAgICAgICAgICAgPyBzZWN0aW9uLmdlbmVyYXRlZE9mZnNldC5nZW5lcmF0ZWRDb2x1bW4gLSAxXG4gICAgICAgICAgICAgOiAwKVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBsaW5lOiBudWxsLFxuICAgICAgY29sdW1uOiBudWxsXG4gICAgfTtcbiAgfTtcblxuLyoqXG4gKiBQYXJzZSB0aGUgbWFwcGluZ3MgaW4gYSBzdHJpbmcgaW4gdG8gYSBkYXRhIHN0cnVjdHVyZSB3aGljaCB3ZSBjYW4gZWFzaWx5XG4gKiBxdWVyeSAodGhlIG9yZGVyZWQgYXJyYXlzIGluIHRoZSBgdGhpcy5fX2dlbmVyYXRlZE1hcHBpbmdzYCBhbmRcbiAqIGB0aGlzLl9fb3JpZ2luYWxNYXBwaW5nc2AgcHJvcGVydGllcykuXG4gKi9cbkluZGV4ZWRTb3VyY2VNYXBDb25zdW1lci5wcm90b3R5cGUuX3BhcnNlTWFwcGluZ3MgPVxuICBmdW5jdGlvbiBJbmRleGVkU291cmNlTWFwQ29uc3VtZXJfcGFyc2VNYXBwaW5ncyhhU3RyLCBhU291cmNlUm9vdCkge1xuICAgIHRoaXMuX19nZW5lcmF0ZWRNYXBwaW5ncyA9IFtdO1xuICAgIHRoaXMuX19vcmlnaW5hbE1hcHBpbmdzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9zZWN0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNlY3Rpb24gPSB0aGlzLl9zZWN0aW9uc1tpXTtcbiAgICAgIHZhciBzZWN0aW9uTWFwcGluZ3MgPSBzZWN0aW9uLmNvbnN1bWVyLl9nZW5lcmF0ZWRNYXBwaW5ncztcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgc2VjdGlvbk1hcHBpbmdzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBtYXBwaW5nID0gc2VjdGlvbk1hcHBpbmdzW2pdO1xuXG4gICAgICAgIHZhciBzb3VyY2UgPSBzZWN0aW9uLmNvbnN1bWVyLl9zb3VyY2VzLmF0KG1hcHBpbmcuc291cmNlKTtcbiAgICAgICAgaWYgKHNlY3Rpb24uY29uc3VtZXIuc291cmNlUm9vdCAhPT0gbnVsbCkge1xuICAgICAgICAgIHNvdXJjZSA9IHV0aWwuam9pbihzZWN0aW9uLmNvbnN1bWVyLnNvdXJjZVJvb3QsIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc291cmNlcy5hZGQoc291cmNlKTtcbiAgICAgICAgc291cmNlID0gdGhpcy5fc291cmNlcy5pbmRleE9mKHNvdXJjZSk7XG5cbiAgICAgICAgdmFyIG5hbWUgPSBzZWN0aW9uLmNvbnN1bWVyLl9uYW1lcy5hdChtYXBwaW5nLm5hbWUpO1xuICAgICAgICB0aGlzLl9uYW1lcy5hZGQobmFtZSk7XG4gICAgICAgIG5hbWUgPSB0aGlzLl9uYW1lcy5pbmRleE9mKG5hbWUpO1xuXG4gICAgICAgIC8vIFRoZSBtYXBwaW5ncyBjb21pbmcgZnJvbSB0aGUgY29uc3VtZXIgZm9yIHRoZSBzZWN0aW9uIGhhdmVcbiAgICAgICAgLy8gZ2VuZXJhdGVkIHBvc2l0aW9ucyByZWxhdGl2ZSB0byB0aGUgc3RhcnQgb2YgdGhlIHNlY3Rpb24sIHNvIHdlXG4gICAgICAgIC8vIG5lZWQgdG8gb2Zmc2V0IHRoZW0gdG8gYmUgcmVsYXRpdmUgdG8gdGhlIHN0YXJ0IG9mIHRoZSBjb25jYXRlbmF0ZWRcbiAgICAgICAgLy8gZ2VuZXJhdGVkIGZpbGUuXG4gICAgICAgIHZhciBhZGp1c3RlZE1hcHBpbmcgPSB7XG4gICAgICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICAgICAgZ2VuZXJhdGVkTGluZTogbWFwcGluZy5nZW5lcmF0ZWRMaW5lICtcbiAgICAgICAgICAgIChzZWN0aW9uLmdlbmVyYXRlZE9mZnNldC5nZW5lcmF0ZWRMaW5lIC0gMSksXG4gICAgICAgICAgZ2VuZXJhdGVkQ29sdW1uOiBtYXBwaW5nLmdlbmVyYXRlZENvbHVtbiArXG4gICAgICAgICAgICAoc2VjdGlvbi5nZW5lcmF0ZWRPZmZzZXQuZ2VuZXJhdGVkTGluZSA9PT0gbWFwcGluZy5nZW5lcmF0ZWRMaW5lXG4gICAgICAgICAgICA/IHNlY3Rpb24uZ2VuZXJhdGVkT2Zmc2V0LmdlbmVyYXRlZENvbHVtbiAtIDFcbiAgICAgICAgICAgIDogMCksXG4gICAgICAgICAgb3JpZ2luYWxMaW5lOiBtYXBwaW5nLm9yaWdpbmFsTGluZSxcbiAgICAgICAgICBvcmlnaW5hbENvbHVtbjogbWFwcGluZy5vcmlnaW5hbENvbHVtbixcbiAgICAgICAgICBuYW1lOiBuYW1lXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5fX2dlbmVyYXRlZE1hcHBpbmdzLnB1c2goYWRqdXN0ZWRNYXBwaW5nKTtcbiAgICAgICAgaWYgKHR5cGVvZiBhZGp1c3RlZE1hcHBpbmcub3JpZ2luYWxMaW5lID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIHRoaXMuX19vcmlnaW5hbE1hcHBpbmdzLnB1c2goYWRqdXN0ZWRNYXBwaW5nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHF1aWNrU29ydCh0aGlzLl9fZ2VuZXJhdGVkTWFwcGluZ3MsIHV0aWwuY29tcGFyZUJ5R2VuZXJhdGVkUG9zaXRpb25zRGVmbGF0ZWQpO1xuICAgIHF1aWNrU29ydCh0aGlzLl9fb3JpZ2luYWxNYXBwaW5ncywgdXRpbC5jb21wYXJlQnlPcmlnaW5hbFBvc2l0aW9ucyk7XG4gIH07XG5cbmV4cG9ydHMuSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyID0gSW5kZXhlZFNvdXJjZU1hcENvbnN1bWVyO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvc291cmNlLW1hcC1jb25zdW1lci5qc1xuLy8gbW9kdWxlIGlkID0gN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiAtKi0gTW9kZToganM7IGpzLWluZGVudC1sZXZlbDogMjsgLSotICovXG4vKlxuICogQ29weXJpZ2h0IDIwMTEgTW96aWxsYSBGb3VuZGF0aW9uIGFuZCBjb250cmlidXRvcnNcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBOZXcgQlNEIGxpY2Vuc2UuIFNlZSBMSUNFTlNFIG9yOlxuICogaHR0cDovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL0JTRC0zLUNsYXVzZVxuICovXG5cbmV4cG9ydHMuR1JFQVRFU1RfTE9XRVJfQk9VTkQgPSAxO1xuZXhwb3J0cy5MRUFTVF9VUFBFUl9CT1VORCA9IDI7XG5cbi8qKlxuICogUmVjdXJzaXZlIGltcGxlbWVudGF0aW9uIG9mIGJpbmFyeSBzZWFyY2guXG4gKlxuICogQHBhcmFtIGFMb3cgSW5kaWNlcyBoZXJlIGFuZCBsb3dlciBkbyBub3QgY29udGFpbiB0aGUgbmVlZGxlLlxuICogQHBhcmFtIGFIaWdoIEluZGljZXMgaGVyZSBhbmQgaGlnaGVyIGRvIG5vdCBjb250YWluIHRoZSBuZWVkbGUuXG4gKiBAcGFyYW0gYU5lZWRsZSBUaGUgZWxlbWVudCBiZWluZyBzZWFyY2hlZCBmb3IuXG4gKiBAcGFyYW0gYUhheXN0YWNrIFRoZSBub24tZW1wdHkgYXJyYXkgYmVpbmcgc2VhcmNoZWQuXG4gKiBAcGFyYW0gYUNvbXBhcmUgRnVuY3Rpb24gd2hpY2ggdGFrZXMgdHdvIGVsZW1lbnRzIGFuZCByZXR1cm5zIC0xLCAwLCBvciAxLlxuICogQHBhcmFtIGFCaWFzIEVpdGhlciAnYmluYXJ5U2VhcmNoLkdSRUFURVNUX0xPV0VSX0JPVU5EJyBvclxuICogICAgICdiaW5hcnlTZWFyY2guTEVBU1RfVVBQRVJfQk9VTkQnLiBTcGVjaWZpZXMgd2hldGhlciB0byByZXR1cm4gdGhlXG4gKiAgICAgY2xvc2VzdCBlbGVtZW50IHRoYXQgaXMgc21hbGxlciB0aGFuIG9yIGdyZWF0ZXIgdGhhbiB0aGUgb25lIHdlIGFyZVxuICogICAgIHNlYXJjaGluZyBmb3IsIHJlc3BlY3RpdmVseSwgaWYgdGhlIGV4YWN0IGVsZW1lbnQgY2Fubm90IGJlIGZvdW5kLlxuICovXG5mdW5jdGlvbiByZWN1cnNpdmVTZWFyY2goYUxvdywgYUhpZ2gsIGFOZWVkbGUsIGFIYXlzdGFjaywgYUNvbXBhcmUsIGFCaWFzKSB7XG4gIC8vIFRoaXMgZnVuY3Rpb24gdGVybWluYXRlcyB3aGVuIG9uZSBvZiB0aGUgZm9sbG93aW5nIGlzIHRydWU6XG4gIC8vXG4gIC8vICAgMS4gV2UgZmluZCB0aGUgZXhhY3QgZWxlbWVudCB3ZSBhcmUgbG9va2luZyBmb3IuXG4gIC8vXG4gIC8vICAgMi4gV2UgZGlkIG5vdCBmaW5kIHRoZSBleGFjdCBlbGVtZW50LCBidXQgd2UgY2FuIHJldHVybiB0aGUgaW5kZXggb2ZcbiAgLy8gICAgICB0aGUgbmV4dC1jbG9zZXN0IGVsZW1lbnQuXG4gIC8vXG4gIC8vICAgMy4gV2UgZGlkIG5vdCBmaW5kIHRoZSBleGFjdCBlbGVtZW50LCBhbmQgdGhlcmUgaXMgbm8gbmV4dC1jbG9zZXN0XG4gIC8vICAgICAgZWxlbWVudCB0aGFuIHRoZSBvbmUgd2UgYXJlIHNlYXJjaGluZyBmb3IsIHNvIHdlIHJldHVybiAtMS5cbiAgdmFyIG1pZCA9IE1hdGguZmxvb3IoKGFIaWdoIC0gYUxvdykgLyAyKSArIGFMb3c7XG4gIHZhciBjbXAgPSBhQ29tcGFyZShhTmVlZGxlLCBhSGF5c3RhY2tbbWlkXSwgdHJ1ZSk7XG4gIGlmIChjbXAgPT09IDApIHtcbiAgICAvLyBGb3VuZCB0aGUgZWxlbWVudCB3ZSBhcmUgbG9va2luZyBmb3IuXG4gICAgcmV0dXJuIG1pZDtcbiAgfVxuICBlbHNlIGlmIChjbXAgPiAwKSB7XG4gICAgLy8gT3VyIG5lZWRsZSBpcyBncmVhdGVyIHRoYW4gYUhheXN0YWNrW21pZF0uXG4gICAgaWYgKGFIaWdoIC0gbWlkID4gMSkge1xuICAgICAgLy8gVGhlIGVsZW1lbnQgaXMgaW4gdGhlIHVwcGVyIGhhbGYuXG4gICAgICByZXR1cm4gcmVjdXJzaXZlU2VhcmNoKG1pZCwgYUhpZ2gsIGFOZWVkbGUsIGFIYXlzdGFjaywgYUNvbXBhcmUsIGFCaWFzKTtcbiAgICB9XG5cbiAgICAvLyBUaGUgZXhhY3QgbmVlZGxlIGVsZW1lbnQgd2FzIG5vdCBmb3VuZCBpbiB0aGlzIGhheXN0YWNrLiBEZXRlcm1pbmUgaWZcbiAgICAvLyB3ZSBhcmUgaW4gdGVybWluYXRpb24gY2FzZSAoMykgb3IgKDIpIGFuZCByZXR1cm4gdGhlIGFwcHJvcHJpYXRlIHRoaW5nLlxuICAgIGlmIChhQmlhcyA9PSBleHBvcnRzLkxFQVNUX1VQUEVSX0JPVU5EKSB7XG4gICAgICByZXR1cm4gYUhpZ2ggPCBhSGF5c3RhY2subGVuZ3RoID8gYUhpZ2ggOiAtMTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG1pZDtcbiAgICB9XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gT3VyIG5lZWRsZSBpcyBsZXNzIHRoYW4gYUhheXN0YWNrW21pZF0uXG4gICAgaWYgKG1pZCAtIGFMb3cgPiAxKSB7XG4gICAgICAvLyBUaGUgZWxlbWVudCBpcyBpbiB0aGUgbG93ZXIgaGFsZi5cbiAgICAgIHJldHVybiByZWN1cnNpdmVTZWFyY2goYUxvdywgbWlkLCBhTmVlZGxlLCBhSGF5c3RhY2ssIGFDb21wYXJlLCBhQmlhcyk7XG4gICAgfVxuXG4gICAgLy8gd2UgYXJlIGluIHRlcm1pbmF0aW9uIGNhc2UgKDMpIG9yICgyKSBhbmQgcmV0dXJuIHRoZSBhcHByb3ByaWF0ZSB0aGluZy5cbiAgICBpZiAoYUJpYXMgPT0gZXhwb3J0cy5MRUFTVF9VUFBFUl9CT1VORCkge1xuICAgICAgcmV0dXJuIG1pZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGFMb3cgPCAwID8gLTEgOiBhTG93O1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFRoaXMgaXMgYW4gaW1wbGVtZW50YXRpb24gb2YgYmluYXJ5IHNlYXJjaCB3aGljaCB3aWxsIGFsd2F5cyB0cnkgYW5kIHJldHVyblxuICogdGhlIGluZGV4IG9mIHRoZSBjbG9zZXN0IGVsZW1lbnQgaWYgdGhlcmUgaXMgbm8gZXhhY3QgaGl0LiBUaGlzIGlzIGJlY2F1c2VcbiAqIG1hcHBpbmdzIGJldHdlZW4gb3JpZ2luYWwgYW5kIGdlbmVyYXRlZCBsaW5lL2NvbCBwYWlycyBhcmUgc2luZ2xlIHBvaW50cyxcbiAqIGFuZCB0aGVyZSBpcyBhbiBpbXBsaWNpdCByZWdpb24gYmV0d2VlbiBlYWNoIG9mIHRoZW0sIHNvIGEgbWlzcyBqdXN0IG1lYW5zXG4gKiB0aGF0IHlvdSBhcmVuJ3Qgb24gdGhlIHZlcnkgc3RhcnQgb2YgYSByZWdpb24uXG4gKlxuICogQHBhcmFtIGFOZWVkbGUgVGhlIGVsZW1lbnQgeW91IGFyZSBsb29raW5nIGZvci5cbiAqIEBwYXJhbSBhSGF5c3RhY2sgVGhlIGFycmF5IHRoYXQgaXMgYmVpbmcgc2VhcmNoZWQuXG4gKiBAcGFyYW0gYUNvbXBhcmUgQSBmdW5jdGlvbiB3aGljaCB0YWtlcyB0aGUgbmVlZGxlIGFuZCBhbiBlbGVtZW50IGluIHRoZVxuICogICAgIGFycmF5IGFuZCByZXR1cm5zIC0xLCAwLCBvciAxIGRlcGVuZGluZyBvbiB3aGV0aGVyIHRoZSBuZWVkbGUgaXMgbGVzc1xuICogICAgIHRoYW4sIGVxdWFsIHRvLCBvciBncmVhdGVyIHRoYW4gdGhlIGVsZW1lbnQsIHJlc3BlY3RpdmVseS5cbiAqIEBwYXJhbSBhQmlhcyBFaXRoZXIgJ2JpbmFyeVNlYXJjaC5HUkVBVEVTVF9MT1dFUl9CT1VORCcgb3JcbiAqICAgICAnYmluYXJ5U2VhcmNoLkxFQVNUX1VQUEVSX0JPVU5EJy4gU3BlY2lmaWVzIHdoZXRoZXIgdG8gcmV0dXJuIHRoZVxuICogICAgIGNsb3Nlc3QgZWxlbWVudCB0aGF0IGlzIHNtYWxsZXIgdGhhbiBvciBncmVhdGVyIHRoYW4gdGhlIG9uZSB3ZSBhcmVcbiAqICAgICBzZWFyY2hpbmcgZm9yLCByZXNwZWN0aXZlbHksIGlmIHRoZSBleGFjdCBlbGVtZW50IGNhbm5vdCBiZSBmb3VuZC5cbiAqICAgICBEZWZhdWx0cyB0byAnYmluYXJ5U2VhcmNoLkdSRUFURVNUX0xPV0VSX0JPVU5EJy5cbiAqL1xuZXhwb3J0cy5zZWFyY2ggPSBmdW5jdGlvbiBzZWFyY2goYU5lZWRsZSwgYUhheXN0YWNrLCBhQ29tcGFyZSwgYUJpYXMpIHtcbiAgaWYgKGFIYXlzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICB2YXIgaW5kZXggPSByZWN1cnNpdmVTZWFyY2goLTEsIGFIYXlzdGFjay5sZW5ndGgsIGFOZWVkbGUsIGFIYXlzdGFjayxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFDb21wYXJlLCBhQmlhcyB8fCBleHBvcnRzLkdSRUFURVNUX0xPV0VSX0JPVU5EKTtcbiAgaWYgKGluZGV4IDwgMCkge1xuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8vIFdlIGhhdmUgZm91bmQgZWl0aGVyIHRoZSBleGFjdCBlbGVtZW50LCBvciB0aGUgbmV4dC1jbG9zZXN0IGVsZW1lbnQgdGhhblxuICAvLyB0aGUgb25lIHdlIGFyZSBzZWFyY2hpbmcgZm9yLiBIb3dldmVyLCB0aGVyZSBtYXkgYmUgbW9yZSB0aGFuIG9uZSBzdWNoXG4gIC8vIGVsZW1lbnQuIE1ha2Ugc3VyZSB3ZSBhbHdheXMgcmV0dXJuIHRoZSBzbWFsbGVzdCBvZiB0aGVzZS5cbiAgd2hpbGUgKGluZGV4IC0gMSA+PSAwKSB7XG4gICAgaWYgKGFDb21wYXJlKGFIYXlzdGFja1tpbmRleF0sIGFIYXlzdGFja1tpbmRleCAtIDFdLCB0cnVlKSAhPT0gMCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIC0taW5kZXg7XG4gIH1cblxuICByZXR1cm4gaW5kZXg7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvYmluYXJ5LXNlYXJjaC5qc1xuLy8gbW9kdWxlIGlkID0gOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiAtKi0gTW9kZToganM7IGpzLWluZGVudC1sZXZlbDogMjsgLSotICovXG4vKlxuICogQ29weXJpZ2h0IDIwMTEgTW96aWxsYSBGb3VuZGF0aW9uIGFuZCBjb250cmlidXRvcnNcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBOZXcgQlNEIGxpY2Vuc2UuIFNlZSBMSUNFTlNFIG9yOlxuICogaHR0cDovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL0JTRC0zLUNsYXVzZVxuICovXG5cbi8vIEl0IHR1cm5zIG91dCB0aGF0IHNvbWUgKG1vc3Q/KSBKYXZhU2NyaXB0IGVuZ2luZXMgZG9uJ3Qgc2VsZi1ob3N0XG4vLyBgQXJyYXkucHJvdG90eXBlLnNvcnRgLiBUaGlzIG1ha2VzIHNlbnNlIGJlY2F1c2UgQysrIHdpbGwgbGlrZWx5IHJlbWFpblxuLy8gZmFzdGVyIHRoYW4gSlMgd2hlbiBkb2luZyByYXcgQ1BVLWludGVuc2l2ZSBzb3J0aW5nLiBIb3dldmVyLCB3aGVuIHVzaW5nIGFcbi8vIGN1c3RvbSBjb21wYXJhdG9yIGZ1bmN0aW9uLCBjYWxsaW5nIGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gdGhlIFZNJ3MgQysrIGFuZFxuLy8gSklUJ2QgSlMgaXMgcmF0aGVyIHNsb3cgKmFuZCogbG9zZXMgSklUIHR5cGUgaW5mb3JtYXRpb24sIHJlc3VsdGluZyBpblxuLy8gd29yc2UgZ2VuZXJhdGVkIGNvZGUgZm9yIHRoZSBjb21wYXJhdG9yIGZ1bmN0aW9uIHRoYW4gd291bGQgYmUgb3B0aW1hbC4gSW5cbi8vIGZhY3QsIHdoZW4gc29ydGluZyB3aXRoIGEgY29tcGFyYXRvciwgdGhlc2UgY29zdHMgb3V0d2VpZ2ggdGhlIGJlbmVmaXRzIG9mXG4vLyBzb3J0aW5nIGluIEMrKy4gQnkgdXNpbmcgb3VyIG93biBKUy1pbXBsZW1lbnRlZCBRdWljayBTb3J0IChiZWxvdyksIHdlIGdldFxuLy8gYSB+MzUwMG1zIG1lYW4gc3BlZWQtdXAgaW4gYGJlbmNoL2JlbmNoLmh0bWxgLlxuXG4vKipcbiAqIFN3YXAgdGhlIGVsZW1lbnRzIGluZGV4ZWQgYnkgYHhgIGFuZCBgeWAgaW4gdGhlIGFycmF5IGBhcnlgLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGFyeVxuICogICAgICAgIFRoZSBhcnJheS5cbiAqIEBwYXJhbSB7TnVtYmVyfSB4XG4gKiAgICAgICAgVGhlIGluZGV4IG9mIHRoZSBmaXJzdCBpdGVtLlxuICogQHBhcmFtIHtOdW1iZXJ9IHlcbiAqICAgICAgICBUaGUgaW5kZXggb2YgdGhlIHNlY29uZCBpdGVtLlxuICovXG5mdW5jdGlvbiBzd2FwKGFyeSwgeCwgeSkge1xuICB2YXIgdGVtcCA9IGFyeVt4XTtcbiAgYXJ5W3hdID0gYXJ5W3ldO1xuICBhcnlbeV0gPSB0ZW1wO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSByYW5kb20gaW50ZWdlciB3aXRoaW4gdGhlIHJhbmdlIGBsb3cgLi4gaGlnaGAgaW5jbHVzaXZlLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBsb3dcbiAqICAgICAgICBUaGUgbG93ZXIgYm91bmQgb24gdGhlIHJhbmdlLlxuICogQHBhcmFtIHtOdW1iZXJ9IGhpZ2hcbiAqICAgICAgICBUaGUgdXBwZXIgYm91bmQgb24gdGhlIHJhbmdlLlxuICovXG5mdW5jdGlvbiByYW5kb21JbnRJblJhbmdlKGxvdywgaGlnaCkge1xuICByZXR1cm4gTWF0aC5yb3VuZChsb3cgKyAoTWF0aC5yYW5kb20oKSAqIChoaWdoIC0gbG93KSkpO1xufVxuXG4vKipcbiAqIFRoZSBRdWljayBTb3J0IGFsZ29yaXRobS5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhcnlcbiAqICAgICAgICBBbiBhcnJheSB0byBzb3J0LlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY29tcGFyYXRvclxuICogICAgICAgIEZ1bmN0aW9uIHRvIHVzZSB0byBjb21wYXJlIHR3byBpdGVtcy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBwXG4gKiAgICAgICAgU3RhcnQgaW5kZXggb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gclxuICogICAgICAgIEVuZCBpbmRleCBvZiB0aGUgYXJyYXlcbiAqL1xuZnVuY3Rpb24gZG9RdWlja1NvcnQoYXJ5LCBjb21wYXJhdG9yLCBwLCByKSB7XG4gIC8vIElmIG91ciBsb3dlciBib3VuZCBpcyBsZXNzIHRoYW4gb3VyIHVwcGVyIGJvdW5kLCB3ZSAoMSkgcGFydGl0aW9uIHRoZVxuICAvLyBhcnJheSBpbnRvIHR3byBwaWVjZXMgYW5kICgyKSByZWN1cnNlIG9uIGVhY2ggaGFsZi4gSWYgaXQgaXMgbm90LCB0aGlzIGlzXG4gIC8vIHRoZSBlbXB0eSBhcnJheSBhbmQgb3VyIGJhc2UgY2FzZS5cblxuICBpZiAocCA8IHIpIHtcbiAgICAvLyAoMSkgUGFydGl0aW9uaW5nLlxuICAgIC8vXG4gICAgLy8gVGhlIHBhcnRpdGlvbmluZyBjaG9vc2VzIGEgcGl2b3QgYmV0d2VlbiBgcGAgYW5kIGByYCBhbmQgbW92ZXMgYWxsXG4gICAgLy8gZWxlbWVudHMgdGhhdCBhcmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBwaXZvdCB0byB0aGUgYmVmb3JlIGl0LCBhbmRcbiAgICAvLyBhbGwgdGhlIGVsZW1lbnRzIHRoYXQgYXJlIGdyZWF0ZXIgdGhhbiBpdCBhZnRlciBpdC4gVGhlIGVmZmVjdCBpcyB0aGF0XG4gICAgLy8gb25jZSBwYXJ0aXRpb24gaXMgZG9uZSwgdGhlIHBpdm90IGlzIGluIHRoZSBleGFjdCBwbGFjZSBpdCB3aWxsIGJlIHdoZW5cbiAgICAvLyB0aGUgYXJyYXkgaXMgcHV0IGluIHNvcnRlZCBvcmRlciwgYW5kIGl0IHdpbGwgbm90IG5lZWQgdG8gYmUgbW92ZWRcbiAgICAvLyBhZ2Fpbi4gVGhpcyBydW5zIGluIE8obikgdGltZS5cblxuICAgIC8vIEFsd2F5cyBjaG9vc2UgYSByYW5kb20gcGl2b3Qgc28gdGhhdCBhbiBpbnB1dCBhcnJheSB3aGljaCBpcyByZXZlcnNlXG4gICAgLy8gc29ydGVkIGRvZXMgbm90IGNhdXNlIE8obl4yKSBydW5uaW5nIHRpbWUuXG4gICAgdmFyIHBpdm90SW5kZXggPSByYW5kb21JbnRJblJhbmdlKHAsIHIpO1xuICAgIHZhciBpID0gcCAtIDE7XG5cbiAgICBzd2FwKGFyeSwgcGl2b3RJbmRleCwgcik7XG4gICAgdmFyIHBpdm90ID0gYXJ5W3JdO1xuXG4gICAgLy8gSW1tZWRpYXRlbHkgYWZ0ZXIgYGpgIGlzIGluY3JlbWVudGVkIGluIHRoaXMgbG9vcCwgdGhlIGZvbGxvd2luZyBob2xkXG4gICAgLy8gdHJ1ZTpcbiAgICAvL1xuICAgIC8vICAgKiBFdmVyeSBlbGVtZW50IGluIGBhcnlbcCAuLiBpXWAgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBwaXZvdC5cbiAgICAvL1xuICAgIC8vICAgKiBFdmVyeSBlbGVtZW50IGluIGBhcnlbaSsxIC4uIGotMV1gIGlzIGdyZWF0ZXIgdGhhbiB0aGUgcGl2b3QuXG4gICAgZm9yICh2YXIgaiA9IHA7IGogPCByOyBqKyspIHtcbiAgICAgIGlmIChjb21wYXJhdG9yKGFyeVtqXSwgcGl2b3QpIDw9IDApIHtcbiAgICAgICAgaSArPSAxO1xuICAgICAgICBzd2FwKGFyeSwgaSwgaik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc3dhcChhcnksIGkgKyAxLCBqKTtcbiAgICB2YXIgcSA9IGkgKyAxO1xuXG4gICAgLy8gKDIpIFJlY3Vyc2Ugb24gZWFjaCBoYWxmLlxuXG4gICAgZG9RdWlja1NvcnQoYXJ5LCBjb21wYXJhdG9yLCBwLCBxIC0gMSk7XG4gICAgZG9RdWlja1NvcnQoYXJ5LCBjb21wYXJhdG9yLCBxICsgMSwgcik7XG4gIH1cbn1cblxuLyoqXG4gKiBTb3J0IHRoZSBnaXZlbiBhcnJheSBpbi1wbGFjZSB3aXRoIHRoZSBnaXZlbiBjb21wYXJhdG9yIGZ1bmN0aW9uLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGFyeVxuICogICAgICAgIEFuIGFycmF5IHRvIHNvcnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjb21wYXJhdG9yXG4gKiAgICAgICAgRnVuY3Rpb24gdG8gdXNlIHRvIGNvbXBhcmUgdHdvIGl0ZW1zLlxuICovXG5leHBvcnRzLnF1aWNrU29ydCA9IGZ1bmN0aW9uIChhcnksIGNvbXBhcmF0b3IpIHtcbiAgZG9RdWlja1NvcnQoYXJ5LCBjb21wYXJhdG9yLCAwLCBhcnkubGVuZ3RoIC0gMSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvcXVpY2stc29ydC5qc1xuLy8gbW9kdWxlIGlkID0gOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiAtKi0gTW9kZToganM7IGpzLWluZGVudC1sZXZlbDogMjsgLSotICovXG4vKlxuICogQ29weXJpZ2h0IDIwMTEgTW96aWxsYSBGb3VuZGF0aW9uIGFuZCBjb250cmlidXRvcnNcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBOZXcgQlNEIGxpY2Vuc2UuIFNlZSBMSUNFTlNFIG9yOlxuICogaHR0cDovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL0JTRC0zLUNsYXVzZVxuICovXG5cbnZhciBTb3VyY2VNYXBHZW5lcmF0b3IgPSByZXF1aXJlKCcuL3NvdXJjZS1tYXAtZ2VuZXJhdG9yJykuU291cmNlTWFwR2VuZXJhdG9yO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuLy8gTWF0Y2hlcyBhIFdpbmRvd3Mtc3R5bGUgYFxcclxcbmAgbmV3bGluZSBvciBhIGBcXG5gIG5ld2xpbmUgdXNlZCBieSBhbGwgb3RoZXJcbi8vIG9wZXJhdGluZyBzeXN0ZW1zIHRoZXNlIGRheXMgKGNhcHR1cmluZyB0aGUgcmVzdWx0KS5cbnZhciBSRUdFWF9ORVdMSU5FID0gLyhcXHI/XFxuKS87XG5cbi8vIE5ld2xpbmUgY2hhcmFjdGVyIGNvZGUgZm9yIGNoYXJDb2RlQXQoKSBjb21wYXJpc29uc1xudmFyIE5FV0xJTkVfQ09ERSA9IDEwO1xuXG4vLyBQcml2YXRlIHN5bWJvbCBmb3IgaWRlbnRpZnlpbmcgYFNvdXJjZU5vZGVgcyB3aGVuIG11bHRpcGxlIHZlcnNpb25zIG9mXG4vLyB0aGUgc291cmNlLW1hcCBsaWJyYXJ5IGFyZSBsb2FkZWQuIFRoaXMgTVVTVCBOT1QgQ0hBTkdFIGFjcm9zc1xuLy8gdmVyc2lvbnMhXG52YXIgaXNTb3VyY2VOb2RlID0gXCIkJCRpc1NvdXJjZU5vZGUkJCRcIjtcblxuLyoqXG4gKiBTb3VyY2VOb2RlcyBwcm92aWRlIGEgd2F5IHRvIGFic3RyYWN0IG92ZXIgaW50ZXJwb2xhdGluZy9jb25jYXRlbmF0aW5nXG4gKiBzbmlwcGV0cyBvZiBnZW5lcmF0ZWQgSmF2YVNjcmlwdCBzb3VyY2UgY29kZSB3aGlsZSBtYWludGFpbmluZyB0aGUgbGluZSBhbmRcbiAqIGNvbHVtbiBpbmZvcm1hdGlvbiBhc3NvY2lhdGVkIHdpdGggdGhlIG9yaWdpbmFsIHNvdXJjZSBjb2RlLlxuICpcbiAqIEBwYXJhbSBhTGluZSBUaGUgb3JpZ2luYWwgbGluZSBudW1iZXIuXG4gKiBAcGFyYW0gYUNvbHVtbiBUaGUgb3JpZ2luYWwgY29sdW1uIG51bWJlci5cbiAqIEBwYXJhbSBhU291cmNlIFRoZSBvcmlnaW5hbCBzb3VyY2UncyBmaWxlbmFtZS5cbiAqIEBwYXJhbSBhQ2h1bmtzIE9wdGlvbmFsLiBBbiBhcnJheSBvZiBzdHJpbmdzIHdoaWNoIGFyZSBzbmlwcGV0cyBvZlxuICogICAgICAgIGdlbmVyYXRlZCBKUywgb3Igb3RoZXIgU291cmNlTm9kZXMuXG4gKiBAcGFyYW0gYU5hbWUgVGhlIG9yaWdpbmFsIGlkZW50aWZpZXIuXG4gKi9cbmZ1bmN0aW9uIFNvdXJjZU5vZGUoYUxpbmUsIGFDb2x1bW4sIGFTb3VyY2UsIGFDaHVua3MsIGFOYW1lKSB7XG4gIHRoaXMuY2hpbGRyZW4gPSBbXTtcbiAgdGhpcy5zb3VyY2VDb250ZW50cyA9IHt9O1xuICB0aGlzLmxpbmUgPSBhTGluZSA9PSBudWxsID8gbnVsbCA6IGFMaW5lO1xuICB0aGlzLmNvbHVtbiA9IGFDb2x1bW4gPT0gbnVsbCA/IG51bGwgOiBhQ29sdW1uO1xuICB0aGlzLnNvdXJjZSA9IGFTb3VyY2UgPT0gbnVsbCA/IG51bGwgOiBhU291cmNlO1xuICB0aGlzLm5hbWUgPSBhTmFtZSA9PSBudWxsID8gbnVsbCA6IGFOYW1lO1xuICB0aGlzW2lzU291cmNlTm9kZV0gPSB0cnVlO1xuICBpZiAoYUNodW5rcyAhPSBudWxsKSB0aGlzLmFkZChhQ2h1bmtzKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgU291cmNlTm9kZSBmcm9tIGdlbmVyYXRlZCBjb2RlIGFuZCBhIFNvdXJjZU1hcENvbnN1bWVyLlxuICpcbiAqIEBwYXJhbSBhR2VuZXJhdGVkQ29kZSBUaGUgZ2VuZXJhdGVkIGNvZGVcbiAqIEBwYXJhbSBhU291cmNlTWFwQ29uc3VtZXIgVGhlIFNvdXJjZU1hcCBmb3IgdGhlIGdlbmVyYXRlZCBjb2RlXG4gKiBAcGFyYW0gYVJlbGF0aXZlUGF0aCBPcHRpb25hbC4gVGhlIHBhdGggdGhhdCByZWxhdGl2ZSBzb3VyY2VzIGluIHRoZVxuICogICAgICAgIFNvdXJjZU1hcENvbnN1bWVyIHNob3VsZCBiZSByZWxhdGl2ZSB0by5cbiAqL1xuU291cmNlTm9kZS5mcm9tU3RyaW5nV2l0aFNvdXJjZU1hcCA9XG4gIGZ1bmN0aW9uIFNvdXJjZU5vZGVfZnJvbVN0cmluZ1dpdGhTb3VyY2VNYXAoYUdlbmVyYXRlZENvZGUsIGFTb3VyY2VNYXBDb25zdW1lciwgYVJlbGF0aXZlUGF0aCkge1xuICAgIC8vIFRoZSBTb3VyY2VOb2RlIHdlIHdhbnQgdG8gZmlsbCB3aXRoIHRoZSBnZW5lcmF0ZWQgY29kZVxuICAgIC8vIGFuZCB0aGUgU291cmNlTWFwXG4gICAgdmFyIG5vZGUgPSBuZXcgU291cmNlTm9kZSgpO1xuXG4gICAgLy8gQWxsIGV2ZW4gaW5kaWNlcyBvZiB0aGlzIGFycmF5IGFyZSBvbmUgbGluZSBvZiB0aGUgZ2VuZXJhdGVkIGNvZGUsXG4gICAgLy8gd2hpbGUgYWxsIG9kZCBpbmRpY2VzIGFyZSB0aGUgbmV3bGluZXMgYmV0d2VlbiB0d28gYWRqYWNlbnQgbGluZXNcbiAgICAvLyAoc2luY2UgYFJFR0VYX05FV0xJTkVgIGNhcHR1cmVzIGl0cyBtYXRjaCkuXG4gICAgLy8gUHJvY2Vzc2VkIGZyYWdtZW50cyBhcmUgYWNjZXNzZWQgYnkgY2FsbGluZyBgc2hpZnROZXh0TGluZWAuXG4gICAgdmFyIHJlbWFpbmluZ0xpbmVzID0gYUdlbmVyYXRlZENvZGUuc3BsaXQoUkVHRVhfTkVXTElORSk7XG4gICAgdmFyIHJlbWFpbmluZ0xpbmVzSW5kZXggPSAwO1xuICAgIHZhciBzaGlmdE5leHRMaW5lID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbGluZUNvbnRlbnRzID0gZ2V0TmV4dExpbmUoKTtcbiAgICAgIC8vIFRoZSBsYXN0IGxpbmUgb2YgYSBmaWxlIG1pZ2h0IG5vdCBoYXZlIGEgbmV3bGluZS5cbiAgICAgIHZhciBuZXdMaW5lID0gZ2V0TmV4dExpbmUoKSB8fCBcIlwiO1xuICAgICAgcmV0dXJuIGxpbmVDb250ZW50cyArIG5ld0xpbmU7XG5cbiAgICAgIGZ1bmN0aW9uIGdldE5leHRMaW5lKCkge1xuICAgICAgICByZXR1cm4gcmVtYWluaW5nTGluZXNJbmRleCA8IHJlbWFpbmluZ0xpbmVzLmxlbmd0aCA/XG4gICAgICAgICAgICByZW1haW5pbmdMaW5lc1tyZW1haW5pbmdMaW5lc0luZGV4KytdIDogdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBXZSBuZWVkIHRvIHJlbWVtYmVyIHRoZSBwb3NpdGlvbiBvZiBcInJlbWFpbmluZ0xpbmVzXCJcbiAgICB2YXIgbGFzdEdlbmVyYXRlZExpbmUgPSAxLCBsYXN0R2VuZXJhdGVkQ29sdW1uID0gMDtcblxuICAgIC8vIFRoZSBnZW5lcmF0ZSBTb3VyY2VOb2RlcyB3ZSBuZWVkIGEgY29kZSByYW5nZS5cbiAgICAvLyBUbyBleHRyYWN0IGl0IGN1cnJlbnQgYW5kIGxhc3QgbWFwcGluZyBpcyB1c2VkLlxuICAgIC8vIEhlcmUgd2Ugc3RvcmUgdGhlIGxhc3QgbWFwcGluZy5cbiAgICB2YXIgbGFzdE1hcHBpbmcgPSBudWxsO1xuXG4gICAgYVNvdXJjZU1hcENvbnN1bWVyLmVhY2hNYXBwaW5nKGZ1bmN0aW9uIChtYXBwaW5nKSB7XG4gICAgICBpZiAobGFzdE1hcHBpbmcgIT09IG51bGwpIHtcbiAgICAgICAgLy8gV2UgYWRkIHRoZSBjb2RlIGZyb20gXCJsYXN0TWFwcGluZ1wiIHRvIFwibWFwcGluZ1wiOlxuICAgICAgICAvLyBGaXJzdCBjaGVjayBpZiB0aGVyZSBpcyBhIG5ldyBsaW5lIGluIGJldHdlZW4uXG4gICAgICAgIGlmIChsYXN0R2VuZXJhdGVkTGluZSA8IG1hcHBpbmcuZ2VuZXJhdGVkTGluZSkge1xuICAgICAgICAgIC8vIEFzc29jaWF0ZSBmaXJzdCBsaW5lIHdpdGggXCJsYXN0TWFwcGluZ1wiXG4gICAgICAgICAgYWRkTWFwcGluZ1dpdGhDb2RlKGxhc3RNYXBwaW5nLCBzaGlmdE5leHRMaW5lKCkpO1xuICAgICAgICAgIGxhc3RHZW5lcmF0ZWRMaW5lKys7XG4gICAgICAgICAgbGFzdEdlbmVyYXRlZENvbHVtbiA9IDA7XG4gICAgICAgICAgLy8gVGhlIHJlbWFpbmluZyBjb2RlIGlzIGFkZGVkIHdpdGhvdXQgbWFwcGluZ1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIG5ldyBsaW5lIGluIGJldHdlZW4uXG4gICAgICAgICAgLy8gQXNzb2NpYXRlIHRoZSBjb2RlIGJldHdlZW4gXCJsYXN0R2VuZXJhdGVkQ29sdW1uXCIgYW5kXG4gICAgICAgICAgLy8gXCJtYXBwaW5nLmdlbmVyYXRlZENvbHVtblwiIHdpdGggXCJsYXN0TWFwcGluZ1wiXG4gICAgICAgICAgdmFyIG5leHRMaW5lID0gcmVtYWluaW5nTGluZXNbcmVtYWluaW5nTGluZXNJbmRleF07XG4gICAgICAgICAgdmFyIGNvZGUgPSBuZXh0TGluZS5zdWJzdHIoMCwgbWFwcGluZy5nZW5lcmF0ZWRDb2x1bW4gLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RHZW5lcmF0ZWRDb2x1bW4pO1xuICAgICAgICAgIHJlbWFpbmluZ0xpbmVzW3JlbWFpbmluZ0xpbmVzSW5kZXhdID0gbmV4dExpbmUuc3Vic3RyKG1hcHBpbmcuZ2VuZXJhdGVkQ29sdW1uIC1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0R2VuZXJhdGVkQ29sdW1uKTtcbiAgICAgICAgICBsYXN0R2VuZXJhdGVkQ29sdW1uID0gbWFwcGluZy5nZW5lcmF0ZWRDb2x1bW47XG4gICAgICAgICAgYWRkTWFwcGluZ1dpdGhDb2RlKGxhc3RNYXBwaW5nLCBjb2RlKTtcbiAgICAgICAgICAvLyBObyBtb3JlIHJlbWFpbmluZyBjb2RlLCBjb250aW51ZVxuICAgICAgICAgIGxhc3RNYXBwaW5nID0gbWFwcGluZztcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIFdlIGFkZCB0aGUgZ2VuZXJhdGVkIGNvZGUgdW50aWwgdGhlIGZpcnN0IG1hcHBpbmdcbiAgICAgIC8vIHRvIHRoZSBTb3VyY2VOb2RlIHdpdGhvdXQgYW55IG1hcHBpbmcuXG4gICAgICAvLyBFYWNoIGxpbmUgaXMgYWRkZWQgYXMgc2VwYXJhdGUgc3RyaW5nLlxuICAgICAgd2hpbGUgKGxhc3RHZW5lcmF0ZWRMaW5lIDwgbWFwcGluZy5nZW5lcmF0ZWRMaW5lKSB7XG4gICAgICAgIG5vZGUuYWRkKHNoaWZ0TmV4dExpbmUoKSk7XG4gICAgICAgIGxhc3RHZW5lcmF0ZWRMaW5lKys7XG4gICAgICB9XG4gICAgICBpZiAobGFzdEdlbmVyYXRlZENvbHVtbiA8IG1hcHBpbmcuZ2VuZXJhdGVkQ29sdW1uKSB7XG4gICAgICAgIHZhciBuZXh0TGluZSA9IHJlbWFpbmluZ0xpbmVzW3JlbWFpbmluZ0xpbmVzSW5kZXhdO1xuICAgICAgICBub2RlLmFkZChuZXh0TGluZS5zdWJzdHIoMCwgbWFwcGluZy5nZW5lcmF0ZWRDb2x1bW4pKTtcbiAgICAgICAgcmVtYWluaW5nTGluZXNbcmVtYWluaW5nTGluZXNJbmRleF0gPSBuZXh0TGluZS5zdWJzdHIobWFwcGluZy5nZW5lcmF0ZWRDb2x1bW4pO1xuICAgICAgICBsYXN0R2VuZXJhdGVkQ29sdW1uID0gbWFwcGluZy5nZW5lcmF0ZWRDb2x1bW47XG4gICAgICB9XG4gICAgICBsYXN0TWFwcGluZyA9IG1hcHBpbmc7XG4gICAgfSwgdGhpcyk7XG4gICAgLy8gV2UgaGF2ZSBwcm9jZXNzZWQgYWxsIG1hcHBpbmdzLlxuICAgIGlmIChyZW1haW5pbmdMaW5lc0luZGV4IDwgcmVtYWluaW5nTGluZXMubGVuZ3RoKSB7XG4gICAgICBpZiAobGFzdE1hcHBpbmcpIHtcbiAgICAgICAgLy8gQXNzb2NpYXRlIHRoZSByZW1haW5pbmcgY29kZSBpbiB0aGUgY3VycmVudCBsaW5lIHdpdGggXCJsYXN0TWFwcGluZ1wiXG4gICAgICAgIGFkZE1hcHBpbmdXaXRoQ29kZShsYXN0TWFwcGluZywgc2hpZnROZXh0TGluZSgpKTtcbiAgICAgIH1cbiAgICAgIC8vIGFuZCBhZGQgdGhlIHJlbWFpbmluZyBsaW5lcyB3aXRob3V0IGFueSBtYXBwaW5nXG4gICAgICBub2RlLmFkZChyZW1haW5pbmdMaW5lcy5zcGxpY2UocmVtYWluaW5nTGluZXNJbmRleCkuam9pbihcIlwiKSk7XG4gICAgfVxuXG4gICAgLy8gQ29weSBzb3VyY2VzQ29udGVudCBpbnRvIFNvdXJjZU5vZGVcbiAgICBhU291cmNlTWFwQ29uc3VtZXIuc291cmNlcy5mb3JFYWNoKGZ1bmN0aW9uIChzb3VyY2VGaWxlKSB7XG4gICAgICB2YXIgY29udGVudCA9IGFTb3VyY2VNYXBDb25zdW1lci5zb3VyY2VDb250ZW50Rm9yKHNvdXJjZUZpbGUpO1xuICAgICAgaWYgKGNvbnRlbnQgIT0gbnVsbCkge1xuICAgICAgICBpZiAoYVJlbGF0aXZlUGF0aCAhPSBudWxsKSB7XG4gICAgICAgICAgc291cmNlRmlsZSA9IHV0aWwuam9pbihhUmVsYXRpdmVQYXRoLCBzb3VyY2VGaWxlKTtcbiAgICAgICAgfVxuICAgICAgICBub2RlLnNldFNvdXJjZUNvbnRlbnQoc291cmNlRmlsZSwgY29udGVudCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gbm9kZTtcblxuICAgIGZ1bmN0aW9uIGFkZE1hcHBpbmdXaXRoQ29kZShtYXBwaW5nLCBjb2RlKSB7XG4gICAgICBpZiAobWFwcGluZyA9PT0gbnVsbCB8fCBtYXBwaW5nLnNvdXJjZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG5vZGUuYWRkKGNvZGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGFSZWxhdGl2ZVBhdGhcbiAgICAgICAgICA/IHV0aWwuam9pbihhUmVsYXRpdmVQYXRoLCBtYXBwaW5nLnNvdXJjZSlcbiAgICAgICAgICA6IG1hcHBpbmcuc291cmNlO1xuICAgICAgICBub2RlLmFkZChuZXcgU291cmNlTm9kZShtYXBwaW5nLm9yaWdpbmFsTGluZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwcGluZy5vcmlnaW5hbENvbHVtbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXBwaW5nLm5hbWUpKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbi8qKlxuICogQWRkIGEgY2h1bmsgb2YgZ2VuZXJhdGVkIEpTIHRvIHRoaXMgc291cmNlIG5vZGUuXG4gKlxuICogQHBhcmFtIGFDaHVuayBBIHN0cmluZyBzbmlwcGV0IG9mIGdlbmVyYXRlZCBKUyBjb2RlLCBhbm90aGVyIGluc3RhbmNlIG9mXG4gKiAgICAgICAgU291cmNlTm9kZSwgb3IgYW4gYXJyYXkgd2hlcmUgZWFjaCBtZW1iZXIgaXMgb25lIG9mIHRob3NlIHRoaW5ncy5cbiAqL1xuU291cmNlTm9kZS5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gU291cmNlTm9kZV9hZGQoYUNodW5rKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGFDaHVuaykpIHtcbiAgICBhQ2h1bmsuZm9yRWFjaChmdW5jdGlvbiAoY2h1bmspIHtcbiAgICAgIHRoaXMuYWRkKGNodW5rKTtcbiAgICB9LCB0aGlzKTtcbiAgfVxuICBlbHNlIGlmIChhQ2h1bmtbaXNTb3VyY2VOb2RlXSB8fCB0eXBlb2YgYUNodW5rID09PSBcInN0cmluZ1wiKSB7XG4gICAgaWYgKGFDaHVuaykge1xuICAgICAgdGhpcy5jaGlsZHJlbi5wdXNoKGFDaHVuayk7XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICBcIkV4cGVjdGVkIGEgU291cmNlTm9kZSwgc3RyaW5nLCBvciBhbiBhcnJheSBvZiBTb3VyY2VOb2RlcyBhbmQgc3RyaW5ncy4gR290IFwiICsgYUNodW5rXG4gICAgKTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogQWRkIGEgY2h1bmsgb2YgZ2VuZXJhdGVkIEpTIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhpcyBzb3VyY2Ugbm9kZS5cbiAqXG4gKiBAcGFyYW0gYUNodW5rIEEgc3RyaW5nIHNuaXBwZXQgb2YgZ2VuZXJhdGVkIEpTIGNvZGUsIGFub3RoZXIgaW5zdGFuY2Ugb2ZcbiAqICAgICAgICBTb3VyY2VOb2RlLCBvciBhbiBhcnJheSB3aGVyZSBlYWNoIG1lbWJlciBpcyBvbmUgb2YgdGhvc2UgdGhpbmdzLlxuICovXG5Tb3VyY2VOb2RlLnByb3RvdHlwZS5wcmVwZW5kID0gZnVuY3Rpb24gU291cmNlTm9kZV9wcmVwZW5kKGFDaHVuaykge1xuICBpZiAoQXJyYXkuaXNBcnJheShhQ2h1bmspKSB7XG4gICAgZm9yICh2YXIgaSA9IGFDaHVuay5sZW5ndGgtMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHRoaXMucHJlcGVuZChhQ2h1bmtbaV0pO1xuICAgIH1cbiAgfVxuICBlbHNlIGlmIChhQ2h1bmtbaXNTb3VyY2VOb2RlXSB8fCB0eXBlb2YgYUNodW5rID09PSBcInN0cmluZ1wiKSB7XG4gICAgdGhpcy5jaGlsZHJlbi51bnNoaWZ0KGFDaHVuayk7XG4gIH1cbiAgZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgIFwiRXhwZWN0ZWQgYSBTb3VyY2VOb2RlLCBzdHJpbmcsIG9yIGFuIGFycmF5IG9mIFNvdXJjZU5vZGVzIGFuZCBzdHJpbmdzLiBHb3QgXCIgKyBhQ2h1bmtcbiAgICApO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBXYWxrIG92ZXIgdGhlIHRyZWUgb2YgSlMgc25pcHBldHMgaW4gdGhpcyBub2RlIGFuZCBpdHMgY2hpbGRyZW4uIFRoZVxuICogd2Fsa2luZyBmdW5jdGlvbiBpcyBjYWxsZWQgb25jZSBmb3IgZWFjaCBzbmlwcGV0IG9mIEpTIGFuZCBpcyBwYXNzZWQgdGhhdFxuICogc25pcHBldCBhbmQgdGhlIGl0cyBvcmlnaW5hbCBhc3NvY2lhdGVkIHNvdXJjZSdzIGxpbmUvY29sdW1uIGxvY2F0aW9uLlxuICpcbiAqIEBwYXJhbSBhRm4gVGhlIHRyYXZlcnNhbCBmdW5jdGlvbi5cbiAqL1xuU291cmNlTm9kZS5wcm90b3R5cGUud2FsayA9IGZ1bmN0aW9uIFNvdXJjZU5vZGVfd2FsayhhRm4pIHtcbiAgdmFyIGNodW5rO1xuICBmb3IgKHZhciBpID0gMCwgbGVuID0gdGhpcy5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGNodW5rID0gdGhpcy5jaGlsZHJlbltpXTtcbiAgICBpZiAoY2h1bmtbaXNTb3VyY2VOb2RlXSkge1xuICAgICAgY2h1bmsud2FsayhhRm4pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGlmIChjaHVuayAhPT0gJycpIHtcbiAgICAgICAgYUZuKGNodW5rLCB7IHNvdXJjZTogdGhpcy5zb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgICBsaW5lOiB0aGlzLmxpbmUsXG4gICAgICAgICAgICAgICAgICAgICBjb2x1bW46IHRoaXMuY29sdW1uLFxuICAgICAgICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBMaWtlIGBTdHJpbmcucHJvdG90eXBlLmpvaW5gIGV4Y2VwdCBmb3IgU291cmNlTm9kZXMuIEluc2VydHMgYGFTdHJgIGJldHdlZW5cbiAqIGVhY2ggb2YgYHRoaXMuY2hpbGRyZW5gLlxuICpcbiAqIEBwYXJhbSBhU2VwIFRoZSBzZXBhcmF0b3IuXG4gKi9cblNvdXJjZU5vZGUucHJvdG90eXBlLmpvaW4gPSBmdW5jdGlvbiBTb3VyY2VOb2RlX2pvaW4oYVNlcCkge1xuICB2YXIgbmV3Q2hpbGRyZW47XG4gIHZhciBpO1xuICB2YXIgbGVuID0gdGhpcy5jaGlsZHJlbi5sZW5ndGg7XG4gIGlmIChsZW4gPiAwKSB7XG4gICAgbmV3Q2hpbGRyZW4gPSBbXTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuLTE7IGkrKykge1xuICAgICAgbmV3Q2hpbGRyZW4ucHVzaCh0aGlzLmNoaWxkcmVuW2ldKTtcbiAgICAgIG5ld0NoaWxkcmVuLnB1c2goYVNlcCk7XG4gICAgfVxuICAgIG5ld0NoaWxkcmVuLnB1c2godGhpcy5jaGlsZHJlbltpXSk7XG4gICAgdGhpcy5jaGlsZHJlbiA9IG5ld0NoaWxkcmVuO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBDYWxsIFN0cmluZy5wcm90b3R5cGUucmVwbGFjZSBvbiB0aGUgdmVyeSByaWdodC1tb3N0IHNvdXJjZSBzbmlwcGV0LiBVc2VmdWxcbiAqIGZvciB0cmltbWluZyB3aGl0ZXNwYWNlIGZyb20gdGhlIGVuZCBvZiBhIHNvdXJjZSBub2RlLCBldGMuXG4gKlxuICogQHBhcmFtIGFQYXR0ZXJuIFRoZSBwYXR0ZXJuIHRvIHJlcGxhY2UuXG4gKiBAcGFyYW0gYVJlcGxhY2VtZW50IFRoZSB0aGluZyB0byByZXBsYWNlIHRoZSBwYXR0ZXJuIHdpdGguXG4gKi9cblNvdXJjZU5vZGUucHJvdG90eXBlLnJlcGxhY2VSaWdodCA9IGZ1bmN0aW9uIFNvdXJjZU5vZGVfcmVwbGFjZVJpZ2h0KGFQYXR0ZXJuLCBhUmVwbGFjZW1lbnQpIHtcbiAgdmFyIGxhc3RDaGlsZCA9IHRoaXMuY2hpbGRyZW5bdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxXTtcbiAgaWYgKGxhc3RDaGlsZFtpc1NvdXJjZU5vZGVdKSB7XG4gICAgbGFzdENoaWxkLnJlcGxhY2VSaWdodChhUGF0dGVybiwgYVJlcGxhY2VtZW50KTtcbiAgfVxuICBlbHNlIGlmICh0eXBlb2YgbGFzdENoaWxkID09PSAnc3RyaW5nJykge1xuICAgIHRoaXMuY2hpbGRyZW5bdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxXSA9IGxhc3RDaGlsZC5yZXBsYWNlKGFQYXR0ZXJuLCBhUmVwbGFjZW1lbnQpO1xuICB9XG4gIGVsc2Uge1xuICAgIHRoaXMuY2hpbGRyZW4ucHVzaCgnJy5yZXBsYWNlKGFQYXR0ZXJuLCBhUmVwbGFjZW1lbnQpKTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IHRoZSBzb3VyY2UgY29udGVudCBmb3IgYSBzb3VyY2UgZmlsZS4gVGhpcyB3aWxsIGJlIGFkZGVkIHRvIHRoZSBTb3VyY2VNYXBHZW5lcmF0b3JcbiAqIGluIHRoZSBzb3VyY2VzQ29udGVudCBmaWVsZC5cbiAqXG4gKiBAcGFyYW0gYVNvdXJjZUZpbGUgVGhlIGZpbGVuYW1lIG9mIHRoZSBzb3VyY2UgZmlsZVxuICogQHBhcmFtIGFTb3VyY2VDb250ZW50IFRoZSBjb250ZW50IG9mIHRoZSBzb3VyY2UgZmlsZVxuICovXG5Tb3VyY2VOb2RlLnByb3RvdHlwZS5zZXRTb3VyY2VDb250ZW50ID1cbiAgZnVuY3Rpb24gU291cmNlTm9kZV9zZXRTb3VyY2VDb250ZW50KGFTb3VyY2VGaWxlLCBhU291cmNlQ29udGVudCkge1xuICAgIHRoaXMuc291cmNlQ29udGVudHNbdXRpbC50b1NldFN0cmluZyhhU291cmNlRmlsZSldID0gYVNvdXJjZUNvbnRlbnQ7XG4gIH07XG5cbi8qKlxuICogV2FsayBvdmVyIHRoZSB0cmVlIG9mIFNvdXJjZU5vZGVzLiBUaGUgd2Fsa2luZyBmdW5jdGlvbiBpcyBjYWxsZWQgZm9yIGVhY2hcbiAqIHNvdXJjZSBmaWxlIGNvbnRlbnQgYW5kIGlzIHBhc3NlZCB0aGUgZmlsZW5hbWUgYW5kIHNvdXJjZSBjb250ZW50LlxuICpcbiAqIEBwYXJhbSBhRm4gVGhlIHRyYXZlcnNhbCBmdW5jdGlvbi5cbiAqL1xuU291cmNlTm9kZS5wcm90b3R5cGUud2Fsa1NvdXJjZUNvbnRlbnRzID1cbiAgZnVuY3Rpb24gU291cmNlTm9kZV93YWxrU291cmNlQ29udGVudHMoYUZuKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IHRoaXMuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGlmICh0aGlzLmNoaWxkcmVuW2ldW2lzU291cmNlTm9kZV0pIHtcbiAgICAgICAgdGhpcy5jaGlsZHJlbltpXS53YWxrU291cmNlQ29udGVudHMoYUZuKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc291cmNlcyA9IE9iamVjdC5rZXlzKHRoaXMuc291cmNlQ29udGVudHMpO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzb3VyY2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBhRm4odXRpbC5mcm9tU2V0U3RyaW5nKHNvdXJjZXNbaV0pLCB0aGlzLnNvdXJjZUNvbnRlbnRzW3NvdXJjZXNbaV1dKTtcbiAgICB9XG4gIH07XG5cbi8qKlxuICogUmV0dXJuIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBzb3VyY2Ugbm9kZS4gV2Fsa3Mgb3ZlciB0aGUgdHJlZVxuICogYW5kIGNvbmNhdGVuYXRlcyBhbGwgdGhlIHZhcmlvdXMgc25pcHBldHMgdG9nZXRoZXIgdG8gb25lIHN0cmluZy5cbiAqL1xuU291cmNlTm9kZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiBTb3VyY2VOb2RlX3RvU3RyaW5nKCkge1xuICB2YXIgc3RyID0gXCJcIjtcbiAgdGhpcy53YWxrKGZ1bmN0aW9uIChjaHVuaykge1xuICAgIHN0ciArPSBjaHVuaztcbiAgfSk7XG4gIHJldHVybiBzdHI7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHNvdXJjZSBub2RlIGFsb25nIHdpdGggYSBzb3VyY2VcbiAqIG1hcC5cbiAqL1xuU291cmNlTm9kZS5wcm90b3R5cGUudG9TdHJpbmdXaXRoU291cmNlTWFwID0gZnVuY3Rpb24gU291cmNlTm9kZV90b1N0cmluZ1dpdGhTb3VyY2VNYXAoYUFyZ3MpIHtcbiAgdmFyIGdlbmVyYXRlZCA9IHtcbiAgICBjb2RlOiBcIlwiLFxuICAgIGxpbmU6IDEsXG4gICAgY29sdW1uOiAwXG4gIH07XG4gIHZhciBtYXAgPSBuZXcgU291cmNlTWFwR2VuZXJhdG9yKGFBcmdzKTtcbiAgdmFyIHNvdXJjZU1hcHBpbmdBY3RpdmUgPSBmYWxzZTtcbiAgdmFyIGxhc3RPcmlnaW5hbFNvdXJjZSA9IG51bGw7XG4gIHZhciBsYXN0T3JpZ2luYWxMaW5lID0gbnVsbDtcbiAgdmFyIGxhc3RPcmlnaW5hbENvbHVtbiA9IG51bGw7XG4gIHZhciBsYXN0T3JpZ2luYWxOYW1lID0gbnVsbDtcbiAgdGhpcy53YWxrKGZ1bmN0aW9uIChjaHVuaywgb3JpZ2luYWwpIHtcbiAgICBnZW5lcmF0ZWQuY29kZSArPSBjaHVuaztcbiAgICBpZiAob3JpZ2luYWwuc291cmNlICE9PSBudWxsXG4gICAgICAgICYmIG9yaWdpbmFsLmxpbmUgIT09IG51bGxcbiAgICAgICAgJiYgb3JpZ2luYWwuY29sdW1uICE9PSBudWxsKSB7XG4gICAgICBpZihsYXN0T3JpZ2luYWxTb3VyY2UgIT09IG9yaWdpbmFsLnNvdXJjZVxuICAgICAgICAgfHwgbGFzdE9yaWdpbmFsTGluZSAhPT0gb3JpZ2luYWwubGluZVxuICAgICAgICAgfHwgbGFzdE9yaWdpbmFsQ29sdW1uICE9PSBvcmlnaW5hbC5jb2x1bW5cbiAgICAgICAgIHx8IGxhc3RPcmlnaW5hbE5hbWUgIT09IG9yaWdpbmFsLm5hbWUpIHtcbiAgICAgICAgbWFwLmFkZE1hcHBpbmcoe1xuICAgICAgICAgIHNvdXJjZTogb3JpZ2luYWwuc291cmNlLFxuICAgICAgICAgIG9yaWdpbmFsOiB7XG4gICAgICAgICAgICBsaW5lOiBvcmlnaW5hbC5saW5lLFxuICAgICAgICAgICAgY29sdW1uOiBvcmlnaW5hbC5jb2x1bW5cbiAgICAgICAgICB9LFxuICAgICAgICAgIGdlbmVyYXRlZDoge1xuICAgICAgICAgICAgbGluZTogZ2VuZXJhdGVkLmxpbmUsXG4gICAgICAgICAgICBjb2x1bW46IGdlbmVyYXRlZC5jb2x1bW5cbiAgICAgICAgICB9LFxuICAgICAgICAgIG5hbWU6IG9yaWdpbmFsLm5hbWVcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBsYXN0T3JpZ2luYWxTb3VyY2UgPSBvcmlnaW5hbC5zb3VyY2U7XG4gICAgICBsYXN0T3JpZ2luYWxMaW5lID0gb3JpZ2luYWwubGluZTtcbiAgICAgIGxhc3RPcmlnaW5hbENvbHVtbiA9IG9yaWdpbmFsLmNvbHVtbjtcbiAgICAgIGxhc3RPcmlnaW5hbE5hbWUgPSBvcmlnaW5hbC5uYW1lO1xuICAgICAgc291cmNlTWFwcGluZ0FjdGl2ZSA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChzb3VyY2VNYXBwaW5nQWN0aXZlKSB7XG4gICAgICBtYXAuYWRkTWFwcGluZyh7XG4gICAgICAgIGdlbmVyYXRlZDoge1xuICAgICAgICAgIGxpbmU6IGdlbmVyYXRlZC5saW5lLFxuICAgICAgICAgIGNvbHVtbjogZ2VuZXJhdGVkLmNvbHVtblxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGxhc3RPcmlnaW5hbFNvdXJjZSA9IG51bGw7XG4gICAgICBzb3VyY2VNYXBwaW5nQWN0aXZlID0gZmFsc2U7XG4gICAgfVxuICAgIGZvciAodmFyIGlkeCA9IDAsIGxlbmd0aCA9IGNodW5rLmxlbmd0aDsgaWR4IDwgbGVuZ3RoOyBpZHgrKykge1xuICAgICAgaWYgKGNodW5rLmNoYXJDb2RlQXQoaWR4KSA9PT0gTkVXTElORV9DT0RFKSB7XG4gICAgICAgIGdlbmVyYXRlZC5saW5lKys7XG4gICAgICAgIGdlbmVyYXRlZC5jb2x1bW4gPSAwO1xuICAgICAgICAvLyBNYXBwaW5ncyBlbmQgYXQgZW9sXG4gICAgICAgIGlmIChpZHggKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICBsYXN0T3JpZ2luYWxTb3VyY2UgPSBudWxsO1xuICAgICAgICAgIHNvdXJjZU1hcHBpbmdBY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIGlmIChzb3VyY2VNYXBwaW5nQWN0aXZlKSB7XG4gICAgICAgICAgbWFwLmFkZE1hcHBpbmcoe1xuICAgICAgICAgICAgc291cmNlOiBvcmlnaW5hbC5zb3VyY2UsXG4gICAgICAgICAgICBvcmlnaW5hbDoge1xuICAgICAgICAgICAgICBsaW5lOiBvcmlnaW5hbC5saW5lLFxuICAgICAgICAgICAgICBjb2x1bW46IG9yaWdpbmFsLmNvbHVtblxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdlbmVyYXRlZDoge1xuICAgICAgICAgICAgICBsaW5lOiBnZW5lcmF0ZWQubGluZSxcbiAgICAgICAgICAgICAgY29sdW1uOiBnZW5lcmF0ZWQuY29sdW1uXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmFtZTogb3JpZ2luYWwubmFtZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnZW5lcmF0ZWQuY29sdW1uKys7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgdGhpcy53YWxrU291cmNlQ29udGVudHMoZnVuY3Rpb24gKHNvdXJjZUZpbGUsIHNvdXJjZUNvbnRlbnQpIHtcbiAgICBtYXAuc2V0U291cmNlQ29udGVudChzb3VyY2VGaWxlLCBzb3VyY2VDb250ZW50KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHsgY29kZTogZ2VuZXJhdGVkLmNvZGUsIG1hcDogbWFwIH07XG59O1xuXG5leHBvcnRzLlNvdXJjZU5vZGUgPSBTb3VyY2VOb2RlO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvc291cmNlLW5vZGUuanNcbi8vIG1vZHVsZSBpZCA9IDEwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/js/node_modules/source-map/dist/source-map.js b/js/node_modules/source-map/dist/source-map.js new file mode 100644 index 0000000..4e630e2 --- /dev/null +++ b/js/node_modules/source-map/dist/source-map.js @@ -0,0 +1,3090 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["sourceMap"] = factory(); + else + root["sourceMap"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + /* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ + exports.SourceMapGenerator = __webpack_require__(1).SourceMapGenerator; + exports.SourceMapConsumer = __webpack_require__(7).SourceMapConsumer; + exports.SourceNode = __webpack_require__(10).SourceNode; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var base64VLQ = __webpack_require__(2); + var util = __webpack_require__(4); + var ArraySet = __webpack_require__(5).ArraySet; + var MappingList = __webpack_require__(6).MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null) { + source = String(source); + if (!this._sources.has(source)) { + this._sources.add(source); + } + } + + if (name != null) { + name = String(name); + if (!this._names.has(name)) { + this._names.add(name); + } + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = Object.create(null); + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + // When aOriginal is truthy but has empty values for .line and .column, + // it is most likely a programmer error. In this case we throw a very + // specific error message to try to guide them the right way. + // For example: https://github.com/Polymer/polymer-bundler/pull/519 + if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { + throw new Error( + 'original.line and original.column are not numbers -- you probably meant to omit ' + + 'the original mapping entirely and only map the generated position. If so, pass ' + + 'null for the original mapping instead of an object with empty or null values.' + ); + } + + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var next; + var mapping; + var nameIdx; + var sourceIdx; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + next = '' + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + next += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; + } + next += ','; + } + } + + next += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + next += base64VLQ.encode(sourceIdx - previousSource); + previousSource = sourceIdx; + + // lines are stored 0-based in SourceMap spec version 3 + next += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + next += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + next += base64VLQ.encode(nameIdx - previousName); + previousName = nameIdx; + } + } + + result += next; + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + var base64 = __webpack_require__(3); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; + }; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); + }; + + /** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ + exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consecutive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); + }; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; + } + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; + } + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); + } + exports.relative = relative; + + var supportsNullProto = (function () { + var obj = Object.create(null); + return !('__proto__' in obj); + }()); + + function identity (s) { + return s; + } + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + if (isProtoString(aStr)) { + return '$' + aStr; + } + + return aStr; + } + exports.toSetString = supportsNullProto ? identity : toSetString; + + function fromSetString(aStr) { + if (isProtoString(aStr)) { + return aStr.slice(1); + } + + return aStr; + } + exports.fromSetString = supportsNullProto ? identity : fromSetString; + + function isProtoString(s) { + if (!s) { + return false; + } + + var length = s.length; + + if (length < 9 /* "__proto__".length */) { + return false; + } + + if (s.charCodeAt(length - 1) !== 95 /* '_' */ || + s.charCodeAt(length - 2) !== 95 /* '_' */ || + s.charCodeAt(length - 3) !== 111 /* 'o' */ || + s.charCodeAt(length - 4) !== 116 /* 't' */ || + s.charCodeAt(length - 5) !== 111 /* 'o' */ || + s.charCodeAt(length - 6) !== 114 /* 'r' */ || + s.charCodeAt(length - 7) !== 112 /* 'p' */ || + s.charCodeAt(length - 8) !== 95 /* '_' */ || + s.charCodeAt(length - 9) !== 95 /* '_' */) { + return false; + } + + for (var i = length - 10; i >= 0; i--) { + if (s.charCodeAt(i) !== 36 /* '$' */) { + return false; + } + } + + return true; + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + } + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + } + exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + + function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; + } + + /** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ + function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(4); + var has = Object.prototype.hasOwnProperty; + var hasNativeMap = typeof Map !== "undefined"; + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = hasNativeMap ? new Map() : Object.create(null); + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ + ArraySet.prototype.size = function ArraySet_size() { + return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = hasNativeMap ? aStr : util.toSetString(aStr); + var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + if (hasNativeMap) { + this._set.set(aStr, idx); + } else { + this._set[sStr] = idx; + } + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + if (hasNativeMap) { + return this._set.has(aStr); + } else { + var sStr = util.toSetString(aStr); + return has.call(this._set, sStr); + } + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (hasNativeMap) { + var idx = this._set.get(aStr); + if (idx >= 0) { + return idx; + } + } else { + var sStr = util.toSetString(aStr); + if (has.call(this._set, sStr)) { + return this._set[sStr]; + } + } + + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(4); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(4); + var binarySearch = __webpack_require__(8); + var ArraySet = __webpack_require__(5).ArraySet; + var base64VLQ = __webpack_require__(2); + var quickSort = __webpack_require__(9).quickSort; + + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); + } + + SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + SourceMapConsumer.GREATEST_LOWER_BOUND = 1; + SourceMapConsumer.LEAST_UPPER_BOUND = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; + + /** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; + } + needle.source = this._sources.indexOf(needle.source); + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } + } + + return mappings; + }; + + exports.SourceMapConsumer = SourceMapConsumer; + + /** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + sources = sources + .map(String) + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) + ? util.relative(sourceRoot, source) + : source; + }); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names.map(String), true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; + + /** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer + */ + BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); + } + + destGeneratedMappings.push(destMapping); + } + + quickSort(smc.__originalMappings, util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + BasicSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Provide the JIT with a nice shape / hidden class. + */ + function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; + } + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; + } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + str = aStr.slice(index, end); + + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + cachedSegments[str] = segment; + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } + } + } + + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; + + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); + } + if (!this._sources.has(source)) { + return { + line: null, + column: null, + lastColumn: null + }; + } + source = this._sources.indexOf(source); + + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + + /** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ + function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); + + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); + } + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); + + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) + } + }); + } + + IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; + + /** + * The version of the source mapping spec that we are consuming. + */ + IndexedSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); + } + } + return sources; + } + }); + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[j]; + + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); + } + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.generatedColumn + + (section.generatedOffset.generatedLine === mapping.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; + + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } + } + } + + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; + + exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + exports.GREATEST_LOWER_BOUND = 1; + exports.LEAST_UPPER_BOUND = 2; + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } + + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } + + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ + exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } + + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } + + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } + + return index; + }; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + // It turns out that some (most?) JavaScript engines don't self-host + // `Array.prototype.sort`. This makes sense because C++ will likely remain + // faster than JS when doing raw CPU-intensive sorting. However, when using a + // custom comparator function, calling back and forth between the VM's C++ and + // JIT'd JS is rather slow *and* loses JIT type information, resulting in + // worse generated code for the comparator function than would be optimal. In + // fact, when sorting with a comparator, these costs outweigh the benefits of + // sorting in C++. By using our own JS-implemented Quick Sort (below), we get + // a ~3500ms mean speed-up in `bench/bench.html`. + + /** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ + function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; + } + + /** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ + function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); + } + + /** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ + function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. + + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. + + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; + + swap(ary, pivotIndex, r); + var pivot = ary[r]; + + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); + } + } + + swap(ary, i + 1, j); + var q = i + 1; + + // (2) Recurse on each half. + + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } + } + + /** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ + exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); + }; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var SourceMapGenerator = __webpack_require__(1).SourceMapGenerator; + var util = __webpack_require__(4); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are accessed by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var remainingLinesIndex = 0; + var shiftNextLine = function() { + var lineContents = getNextLine(); + // The last line of a file might not have a newline. + var newLine = getNextLine() || ""; + return lineContents + newLine; + + function getNextLine() { + return remainingLinesIndex < remainingLines.length ? + remainingLines[remainingLinesIndex++] : undefined; + } + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[remainingLinesIndex]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[remainingLinesIndex]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLinesIndex < remainingLines.length) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.splice(remainingLinesIndex).join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + + +/***/ }) +/******/ ]) +}); +; \ No newline at end of file diff --git a/js/node_modules/source-map/dist/source-map.min.js b/js/node_modules/source-map/dist/source-map.min.js new file mode 100644 index 0000000..f2a46bd --- /dev/null +++ b/js/node_modules/source-map/dist/source-map.min.js @@ -0,0 +1,2 @@ +!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.sourceMap=n():e.sourceMap=n()}(this,function(){return function(e){function n(t){if(r[t])return r[t].exports;var o=r[t]={exports:{},id:t,loaded:!1};return e[t].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}var r={};return n.m=e,n.c=r,n.p="",n(0)}([function(e,n,r){n.SourceMapGenerator=r(1).SourceMapGenerator,n.SourceMapConsumer=r(7).SourceMapConsumer,n.SourceNode=r(10).SourceNode},function(e,n,r){function t(e){e||(e={}),this._file=i.getArg(e,"file",null),this._sourceRoot=i.getArg(e,"sourceRoot",null),this._skipValidation=i.getArg(e,"skipValidation",!1),this._sources=new s,this._names=new s,this._mappings=new a,this._sourcesContents=null}var o=r(2),i=r(4),s=r(5).ArraySet,a=r(6).MappingList;t.prototype._version=3,t.fromSourceMap=function(e){var n=e.sourceRoot,r=new t({file:e.file,sourceRoot:n});return e.eachMapping(function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};null!=e.source&&(t.source=e.source,null!=n&&(t.source=i.relative(n,t.source)),t.original={line:e.originalLine,column:e.originalColumn},null!=e.name&&(t.name=e.name)),r.addMapping(t)}),e.sources.forEach(function(n){var t=e.sourceContentFor(n);null!=t&&r.setSourceContent(n,t)}),r},t.prototype.addMapping=function(e){var n=i.getArg(e,"generated"),r=i.getArg(e,"original",null),t=i.getArg(e,"source",null),o=i.getArg(e,"name",null);this._skipValidation||this._validateMapping(n,r,t,o),null!=t&&(t=String(t),this._sources.has(t)||this._sources.add(t)),null!=o&&(o=String(o),this._names.has(o)||this._names.add(o)),this._mappings.add({generatedLine:n.line,generatedColumn:n.column,originalLine:null!=r&&r.line,originalColumn:null!=r&&r.column,source:t,name:o})},t.prototype.setSourceContent=function(e,n){var r=e;null!=this._sourceRoot&&(r=i.relative(this._sourceRoot,r)),null!=n?(this._sourcesContents||(this._sourcesContents=Object.create(null)),this._sourcesContents[i.toSetString(r)]=n):this._sourcesContents&&(delete this._sourcesContents[i.toSetString(r)],0===Object.keys(this._sourcesContents).length&&(this._sourcesContents=null))},t.prototype.applySourceMap=function(e,n,r){var t=n;if(null==n){if(null==e.file)throw new Error('SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, or the source map\'s "file" property. Both were omitted.');t=e.file}var o=this._sourceRoot;null!=o&&(t=i.relative(o,t));var a=new s,u=new s;this._mappings.unsortedForEach(function(n){if(n.source===t&&null!=n.originalLine){var s=e.originalPositionFor({line:n.originalLine,column:n.originalColumn});null!=s.source&&(n.source=s.source,null!=r&&(n.source=i.join(r,n.source)),null!=o&&(n.source=i.relative(o,n.source)),n.originalLine=s.line,n.originalColumn=s.column,null!=s.name&&(n.name=s.name))}var l=n.source;null==l||a.has(l)||a.add(l);var c=n.name;null==c||u.has(c)||u.add(c)},this),this._sources=a,this._names=u,e.sources.forEach(function(n){var t=e.sourceContentFor(n);null!=t&&(null!=r&&(n=i.join(r,n)),null!=o&&(n=i.relative(o,n)),this.setSourceContent(n,t))},this)},t.prototype._validateMapping=function(e,n,r,t){if(n&&"number"!=typeof n.line&&"number"!=typeof n.column)throw new Error("original.line and original.column are not numbers -- you probably meant to omit the original mapping entirely and only map the generated position. If so, pass null for the original mapping instead of an object with empty or null values.");if((!(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0)||n||r||t)&&!(e&&"line"in e&&"column"in e&&n&&"line"in n&&"column"in n&&e.line>0&&e.column>=0&&n.line>0&&n.column>=0&&r))throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:r,original:n,name:t}))},t.prototype._serializeMappings=function(){for(var e,n,r,t,s=0,a=1,u=0,l=0,c=0,g=0,p="",h=this._mappings.toArray(),f=0,d=h.length;f0){if(!i.compareByGeneratedPositionsInflated(n,h[f-1]))continue;e+=","}e+=o.encode(n.generatedColumn-s),s=n.generatedColumn,null!=n.source&&(t=this._sources.indexOf(n.source),e+=o.encode(t-g),g=t,e+=o.encode(n.originalLine-1-l),l=n.originalLine-1,e+=o.encode(n.originalColumn-u),u=n.originalColumn,null!=n.name&&(r=this._names.indexOf(n.name),e+=o.encode(r-c),c=r)),p+=e}return p},t.prototype._generateSourcesContent=function(e,n){return e.map(function(e){if(!this._sourcesContents)return null;null!=n&&(e=i.relative(n,e));var r=i.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,r)?this._sourcesContents[r]:null},this)},t.prototype.toJSON=function(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};return null!=this._file&&(e.file=this._file),null!=this._sourceRoot&&(e.sourceRoot=this._sourceRoot),this._sourcesContents&&(e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)),e},t.prototype.toString=function(){return JSON.stringify(this.toJSON())},n.SourceMapGenerator=t},function(e,n,r){function t(e){return e<0?(-e<<1)+1:(e<<1)+0}function o(e){var n=1===(1&e),r=e>>1;return n?-r:r}var i=r(3),s=5,a=1<>>=s,o>0&&(n|=l),r+=i.encode(n);while(o>0);return r},n.decode=function(e,n,r){var t,a,c=e.length,g=0,p=0;do{if(n>=c)throw new Error("Expected more digits in base 64 VLQ value.");if(a=i.decode(e.charCodeAt(n++)),a===-1)throw new Error("Invalid base64 digit: "+e.charAt(n-1));t=!!(a&l),a&=u,g+=a<=0;c--)s=u[c],"."===s?u.splice(c,1):".."===s?l++:l>0&&(""===s?(u.splice(c+1,l),l=0):(u.splice(c,2),l--));return r=u.join("/"),""===r&&(r=a?"/":"."),i?(i.path=r,o(i)):r}function s(e,n){""===e&&(e="."),""===n&&(n=".");var r=t(n),s=t(e);if(s&&(e=s.path||"/"),r&&!r.scheme)return s&&(r.scheme=s.scheme),o(r);if(r||n.match(_))return n;if(s&&!s.host&&!s.path)return s.host=n,o(s);var a="/"===n.charAt(0)?n:i(e.replace(/\/+$/,"")+"/"+n);return s?(s.path=a,o(s)):a}function a(e,n){""===e&&(e="."),e=e.replace(/\/$/,"");for(var r=0;0!==n.indexOf(e+"/");){var t=e.lastIndexOf("/");if(t<0)return n;if(e=e.slice(0,t),e.match(/^([^\/]+:\/)?\/*$/))return n;++r}return Array(r+1).join("../")+n.substr(e.length+1)}function u(e){return e}function l(e){return g(e)?"$"+e:e}function c(e){return g(e)?e.slice(1):e}function g(e){if(!e)return!1;var n=e.length;if(n<9)return!1;if(95!==e.charCodeAt(n-1)||95!==e.charCodeAt(n-2)||111!==e.charCodeAt(n-3)||116!==e.charCodeAt(n-4)||111!==e.charCodeAt(n-5)||114!==e.charCodeAt(n-6)||112!==e.charCodeAt(n-7)||95!==e.charCodeAt(n-8)||95!==e.charCodeAt(n-9))return!1;for(var r=n-10;r>=0;r--)if(36!==e.charCodeAt(r))return!1;return!0}function p(e,n,r){var t=e.source-n.source;return 0!==t?t:(t=e.originalLine-n.originalLine,0!==t?t:(t=e.originalColumn-n.originalColumn,0!==t||r?t:(t=e.generatedColumn-n.generatedColumn,0!==t?t:(t=e.generatedLine-n.generatedLine,0!==t?t:e.name-n.name))))}function h(e,n,r){var t=e.generatedLine-n.generatedLine;return 0!==t?t:(t=e.generatedColumn-n.generatedColumn,0!==t||r?t:(t=e.source-n.source,0!==t?t:(t=e.originalLine-n.originalLine,0!==t?t:(t=e.originalColumn-n.originalColumn,0!==t?t:e.name-n.name))))}function f(e,n){return e===n?0:e>n?1:-1}function d(e,n){var r=e.generatedLine-n.generatedLine;return 0!==r?r:(r=e.generatedColumn-n.generatedColumn,0!==r?r:(r=f(e.source,n.source),0!==r?r:(r=e.originalLine-n.originalLine,0!==r?r:(r=e.originalColumn-n.originalColumn,0!==r?r:f(e.name,n.name)))))}n.getArg=r;var m=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/,_=/^data:.+\,.+$/;n.urlParse=t,n.urlGenerate=o,n.normalize=i,n.join=s,n.isAbsolute=function(e){return"/"===e.charAt(0)||!!e.match(m)},n.relative=a;var v=function(){var e=Object.create(null);return!("__proto__"in e)}();n.toSetString=v?u:l,n.fromSetString=v?u:c,n.compareByOriginalPositions=p,n.compareByGeneratedPositionsDeflated=h,n.compareByGeneratedPositionsInflated=d},function(e,n,r){function t(){this._array=[],this._set=s?new Map:Object.create(null)}var o=r(4),i=Object.prototype.hasOwnProperty,s="undefined"!=typeof Map;t.fromArray=function(e,n){for(var r=new t,o=0,i=e.length;o=0)return n}else{var r=o.toSetString(e);if(i.call(this._set,r))return this._set[r]}throw new Error('"'+e+'" is not in the set.')},t.prototype.at=function(e){if(e>=0&&er||t==r&&s>=o||i.compareByGeneratedPositionsInflated(e,n)<=0}function o(){this._array=[],this._sorted=!0,this._last={generatedLine:-1,generatedColumn:0}}var i=r(4);o.prototype.unsortedForEach=function(e,n){this._array.forEach(e,n)},o.prototype.add=function(e){t(this._last,e)?(this._last=e,this._array.push(e)):(this._sorted=!1,this._array.push(e))},o.prototype.toArray=function(){return this._sorted||(this._array.sort(i.compareByGeneratedPositionsInflated),this._sorted=!0),this._array},n.MappingList=o},function(e,n,r){function t(e){var n=e;return"string"==typeof e&&(n=JSON.parse(e.replace(/^\)\]\}'/,""))),null!=n.sections?new s(n):new o(n)}function o(e){var n=e;"string"==typeof e&&(n=JSON.parse(e.replace(/^\)\]\}'/,"")));var r=a.getArg(n,"version"),t=a.getArg(n,"sources"),o=a.getArg(n,"names",[]),i=a.getArg(n,"sourceRoot",null),s=a.getArg(n,"sourcesContent",null),u=a.getArg(n,"mappings"),c=a.getArg(n,"file",null);if(r!=this._version)throw new Error("Unsupported version: "+r);t=t.map(String).map(a.normalize).map(function(e){return i&&a.isAbsolute(i)&&a.isAbsolute(e)?a.relative(i,e):e}),this._names=l.fromArray(o.map(String),!0),this._sources=l.fromArray(t,!0),this.sourceRoot=i,this.sourcesContent=s,this._mappings=u,this.file=c}function i(){this.generatedLine=0,this.generatedColumn=0,this.source=null,this.originalLine=null,this.originalColumn=null,this.name=null}function s(e){var n=e;"string"==typeof e&&(n=JSON.parse(e.replace(/^\)\]\}'/,"")));var r=a.getArg(n,"version"),o=a.getArg(n,"sections");if(r!=this._version)throw new Error("Unsupported version: "+r);this._sources=new l,this._names=new l;var i={line:-1,column:0};this._sections=o.map(function(e){if(e.url)throw new Error("Support for url field in sections not implemented.");var n=a.getArg(e,"offset"),r=a.getArg(n,"line"),o=a.getArg(n,"column");if(r=0){var i=this._originalMappings[o];if(void 0===e.column)for(var s=i.originalLine;i&&i.originalLine===s;)t.push({line:a.getArg(i,"generatedLine",null),column:a.getArg(i,"generatedColumn",null),lastColumn:a.getArg(i,"lastGeneratedColumn",null)}),i=this._originalMappings[++o];else for(var l=i.originalColumn;i&&i.originalLine===n&&i.originalColumn==l;)t.push({line:a.getArg(i,"generatedLine",null),column:a.getArg(i,"generatedColumn",null),lastColumn:a.getArg(i,"lastGeneratedColumn",null)}),i=this._originalMappings[++o]}return t},n.SourceMapConsumer=t,o.prototype=Object.create(t.prototype),o.prototype.consumer=t,o.fromSourceMap=function(e){var n=Object.create(o.prototype),r=n._names=l.fromArray(e._names.toArray(),!0),t=n._sources=l.fromArray(e._sources.toArray(),!0);n.sourceRoot=e._sourceRoot,n.sourcesContent=e._generateSourcesContent(n._sources.toArray(),n.sourceRoot),n.file=e._file;for(var s=e._mappings.toArray().slice(),u=n.__generatedMappings=[],c=n.__originalMappings=[],p=0,h=s.length;p1&&(r.source=d+o[1],d+=o[1],r.originalLine=h+o[2],h=r.originalLine,r.originalLine+=1,r.originalColumn=f+o[3],f=r.originalColumn,o.length>4&&(r.name=m+o[4],m+=o[4])),S.push(r),"number"==typeof r.originalLine&&A.push(r)}g(S,a.compareByGeneratedPositionsDeflated),this.__generatedMappings=S,g(A,a.compareByOriginalPositions),this.__originalMappings=A},o.prototype._findMapping=function(e,n,r,t,o,i){if(e[r]<=0)throw new TypeError("Line must be greater than or equal to 1, got "+e[r]);if(e[t]<0)throw new TypeError("Column must be greater than or equal to 0, got "+e[t]);return u.search(e,n,o,i)},o.prototype.computeColumnSpans=function(){for(var e=0;e=0){var o=this._generatedMappings[r];if(o.generatedLine===n.generatedLine){var i=a.getArg(o,"source",null);null!==i&&(i=this._sources.at(i),null!=this.sourceRoot&&(i=a.join(this.sourceRoot,i)));var s=a.getArg(o,"name",null);return null!==s&&(s=this._names.at(s)),{source:i,line:a.getArg(o,"originalLine",null),column:a.getArg(o,"originalColumn",null),name:s}}}return{source:null,line:null,column:null,name:null}},o.prototype.hasContentsOfAllSources=function(){return!!this.sourcesContent&&(this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some(function(e){return null==e}))},o.prototype.sourceContentFor=function(e,n){if(!this.sourcesContent)return null;if(null!=this.sourceRoot&&(e=a.relative(this.sourceRoot,e)),this._sources.has(e))return this.sourcesContent[this._sources.indexOf(e)];var r;if(null!=this.sourceRoot&&(r=a.urlParse(this.sourceRoot))){var t=e.replace(/^file:\/\//,"");if("file"==r.scheme&&this._sources.has(t))return this.sourcesContent[this._sources.indexOf(t)];if((!r.path||"/"==r.path)&&this._sources.has("/"+e))return this.sourcesContent[this._sources.indexOf("/"+e)]}if(n)return null;throw new Error('"'+e+'" is not in the SourceMap.')},o.prototype.generatedPositionFor=function(e){var n=a.getArg(e,"source");if(null!=this.sourceRoot&&(n=a.relative(this.sourceRoot,n)),!this._sources.has(n))return{line:null,column:null,lastColumn:null};n=this._sources.indexOf(n);var r={source:n,originalLine:a.getArg(e,"line"),originalColumn:a.getArg(e,"column")},o=this._findMapping(r,this._originalMappings,"originalLine","originalColumn",a.compareByOriginalPositions,a.getArg(e,"bias",t.GREATEST_LOWER_BOUND));if(o>=0){var i=this._originalMappings[o];if(i.source===r.source)return{line:a.getArg(i,"generatedLine",null),column:a.getArg(i,"generatedColumn",null),lastColumn:a.getArg(i,"lastGeneratedColumn",null)}}return{line:null,column:null,lastColumn:null}},n.BasicSourceMapConsumer=o,s.prototype=Object.create(t.prototype),s.prototype.constructor=t,s.prototype._version=3,Object.defineProperty(s.prototype,"sources",{get:function(){for(var e=[],n=0;n0?t-u>1?r(u,t,o,i,s,a):a==n.LEAST_UPPER_BOUND?t1?r(e,u,o,i,s,a):a==n.LEAST_UPPER_BOUND?u:e<0?-1:e}n.GREATEST_LOWER_BOUND=1,n.LEAST_UPPER_BOUND=2,n.search=function(e,t,o,i){if(0===t.length)return-1;var s=r(-1,t.length,e,t,o,i||n.GREATEST_LOWER_BOUND);if(s<0)return-1;for(;s-1>=0&&0===o(t[s],t[s-1],!0);)--s;return s}},function(e,n){function r(e,n,r){var t=e[n];e[n]=e[r],e[r]=t}function t(e,n){return Math.round(e+Math.random()*(n-e))}function o(e,n,i,s){if(i=0;n--)this.prepend(e[n]);else{if(!e[u]&&"string"!=typeof e)throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e);this.children.unshift(e)}return this},t.prototype.walk=function(e){for(var n,r=0,t=this.children.length;r0){for(n=[],r=0;r 0 && aGenerated.column >= 0\n\t && !aOriginal && !aSource && !aName) {\n\t // Case 1.\n\t return;\n\t }\n\t else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated\n\t && aOriginal && 'line' in aOriginal && 'column' in aOriginal\n\t && aGenerated.line > 0 && aGenerated.column >= 0\n\t && aOriginal.line > 0 && aOriginal.column >= 0\n\t && aSource) {\n\t // Cases 2 and 3.\n\t return;\n\t }\n\t else {\n\t throw new Error('Invalid mapping: ' + JSON.stringify({\n\t generated: aGenerated,\n\t source: aSource,\n\t original: aOriginal,\n\t name: aName\n\t }));\n\t }\n\t };\n\t\n\t/**\n\t * Serialize the accumulated mappings in to the stream of base 64 VLQs\n\t * specified by the source map format.\n\t */\n\tSourceMapGenerator.prototype._serializeMappings =\n\t function SourceMapGenerator_serializeMappings() {\n\t var previousGeneratedColumn = 0;\n\t var previousGeneratedLine = 1;\n\t var previousOriginalColumn = 0;\n\t var previousOriginalLine = 0;\n\t var previousName = 0;\n\t var previousSource = 0;\n\t var result = '';\n\t var next;\n\t var mapping;\n\t var nameIdx;\n\t var sourceIdx;\n\t\n\t var mappings = this._mappings.toArray();\n\t for (var i = 0, len = mappings.length; i < len; i++) {\n\t mapping = mappings[i];\n\t next = ''\n\t\n\t if (mapping.generatedLine !== previousGeneratedLine) {\n\t previousGeneratedColumn = 0;\n\t while (mapping.generatedLine !== previousGeneratedLine) {\n\t next += ';';\n\t previousGeneratedLine++;\n\t }\n\t }\n\t else {\n\t if (i > 0) {\n\t if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {\n\t continue;\n\t }\n\t next += ',';\n\t }\n\t }\n\t\n\t next += base64VLQ.encode(mapping.generatedColumn\n\t - previousGeneratedColumn);\n\t previousGeneratedColumn = mapping.generatedColumn;\n\t\n\t if (mapping.source != null) {\n\t sourceIdx = this._sources.indexOf(mapping.source);\n\t next += base64VLQ.encode(sourceIdx - previousSource);\n\t previousSource = sourceIdx;\n\t\n\t // lines are stored 0-based in SourceMap spec version 3\n\t next += base64VLQ.encode(mapping.originalLine - 1\n\t - previousOriginalLine);\n\t previousOriginalLine = mapping.originalLine - 1;\n\t\n\t next += base64VLQ.encode(mapping.originalColumn\n\t - previousOriginalColumn);\n\t previousOriginalColumn = mapping.originalColumn;\n\t\n\t if (mapping.name != null) {\n\t nameIdx = this._names.indexOf(mapping.name);\n\t next += base64VLQ.encode(nameIdx - previousName);\n\t previousName = nameIdx;\n\t }\n\t }\n\t\n\t result += next;\n\t }\n\t\n\t return result;\n\t };\n\t\n\tSourceMapGenerator.prototype._generateSourcesContent =\n\t function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {\n\t return aSources.map(function (source) {\n\t if (!this._sourcesContents) {\n\t return null;\n\t }\n\t if (aSourceRoot != null) {\n\t source = util.relative(aSourceRoot, source);\n\t }\n\t var key = util.toSetString(source);\n\t return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)\n\t ? this._sourcesContents[key]\n\t : null;\n\t }, this);\n\t };\n\t\n\t/**\n\t * Externalize the source map.\n\t */\n\tSourceMapGenerator.prototype.toJSON =\n\t function SourceMapGenerator_toJSON() {\n\t var map = {\n\t version: this._version,\n\t sources: this._sources.toArray(),\n\t names: this._names.toArray(),\n\t mappings: this._serializeMappings()\n\t };\n\t if (this._file != null) {\n\t map.file = this._file;\n\t }\n\t if (this._sourceRoot != null) {\n\t map.sourceRoot = this._sourceRoot;\n\t }\n\t if (this._sourcesContents) {\n\t map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);\n\t }\n\t\n\t return map;\n\t };\n\t\n\t/**\n\t * Render the source map being generated to a string.\n\t */\n\tSourceMapGenerator.prototype.toString =\n\t function SourceMapGenerator_toString() {\n\t return JSON.stringify(this.toJSON());\n\t };\n\t\n\texports.SourceMapGenerator = SourceMapGenerator;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t *\n\t * Based on the Base 64 VLQ implementation in Closure Compiler:\n\t * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java\n\t *\n\t * Copyright 2011 The Closure Compiler Authors. All rights reserved.\n\t * Redistribution and use in source and binary forms, with or without\n\t * modification, are permitted provided that the following conditions are\n\t * met:\n\t *\n\t * * Redistributions of source code must retain the above copyright\n\t * notice, this list of conditions and the following disclaimer.\n\t * * Redistributions in binary form must reproduce the above\n\t * copyright notice, this list of conditions and the following\n\t * disclaimer in the documentation and/or other materials provided\n\t * with the distribution.\n\t * * Neither the name of Google Inc. nor the names of its\n\t * contributors may be used to endorse or promote products derived\n\t * from this software without specific prior written permission.\n\t *\n\t * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\t * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n\t * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\t * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n\t * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n\t * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n\t * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n\t * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n\t * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n\t * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n\t * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\t */\n\t\n\tvar base64 = __webpack_require__(3);\n\t\n\t// A single base 64 digit can contain 6 bits of data. For the base 64 variable\n\t// length quantities we use in the source map spec, the first bit is the sign,\n\t// the next four bits are the actual value, and the 6th bit is the\n\t// continuation bit. The continuation bit tells us whether there are more\n\t// digits in this value following this digit.\n\t//\n\t// Continuation\n\t// | Sign\n\t// | |\n\t// V V\n\t// 101011\n\t\n\tvar VLQ_BASE_SHIFT = 5;\n\t\n\t// binary: 100000\n\tvar VLQ_BASE = 1 << VLQ_BASE_SHIFT;\n\t\n\t// binary: 011111\n\tvar VLQ_BASE_MASK = VLQ_BASE - 1;\n\t\n\t// binary: 100000\n\tvar VLQ_CONTINUATION_BIT = VLQ_BASE;\n\t\n\t/**\n\t * Converts from a two-complement value to a value where the sign bit is\n\t * placed in the least significant bit. For example, as decimals:\n\t * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)\n\t * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)\n\t */\n\tfunction toVLQSigned(aValue) {\n\t return aValue < 0\n\t ? ((-aValue) << 1) + 1\n\t : (aValue << 1) + 0;\n\t}\n\t\n\t/**\n\t * Converts to a two-complement value from a value where the sign bit is\n\t * placed in the least significant bit. For example, as decimals:\n\t * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1\n\t * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2\n\t */\n\tfunction fromVLQSigned(aValue) {\n\t var isNegative = (aValue & 1) === 1;\n\t var shifted = aValue >> 1;\n\t return isNegative\n\t ? -shifted\n\t : shifted;\n\t}\n\t\n\t/**\n\t * Returns the base 64 VLQ encoded value.\n\t */\n\texports.encode = function base64VLQ_encode(aValue) {\n\t var encoded = \"\";\n\t var digit;\n\t\n\t var vlq = toVLQSigned(aValue);\n\t\n\t do {\n\t digit = vlq & VLQ_BASE_MASK;\n\t vlq >>>= VLQ_BASE_SHIFT;\n\t if (vlq > 0) {\n\t // There are still more digits in this value, so we must make sure the\n\t // continuation bit is marked.\n\t digit |= VLQ_CONTINUATION_BIT;\n\t }\n\t encoded += base64.encode(digit);\n\t } while (vlq > 0);\n\t\n\t return encoded;\n\t};\n\t\n\t/**\n\t * Decodes the next base 64 VLQ value from the given string and returns the\n\t * value and the rest of the string via the out parameter.\n\t */\n\texports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {\n\t var strLen = aStr.length;\n\t var result = 0;\n\t var shift = 0;\n\t var continuation, digit;\n\t\n\t do {\n\t if (aIndex >= strLen) {\n\t throw new Error(\"Expected more digits in base 64 VLQ value.\");\n\t }\n\t\n\t digit = base64.decode(aStr.charCodeAt(aIndex++));\n\t if (digit === -1) {\n\t throw new Error(\"Invalid base64 digit: \" + aStr.charAt(aIndex - 1));\n\t }\n\t\n\t continuation = !!(digit & VLQ_CONTINUATION_BIT);\n\t digit &= VLQ_BASE_MASK;\n\t result = result + (digit << shift);\n\t shift += VLQ_BASE_SHIFT;\n\t } while (continuation);\n\t\n\t aOutParam.value = fromVLQSigned(result);\n\t aOutParam.rest = aIndex;\n\t};\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\tvar intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');\n\t\n\t/**\n\t * Encode an integer in the range of 0 to 63 to a single base 64 digit.\n\t */\n\texports.encode = function (number) {\n\t if (0 <= number && number < intToCharMap.length) {\n\t return intToCharMap[number];\n\t }\n\t throw new TypeError(\"Must be between 0 and 63: \" + number);\n\t};\n\t\n\t/**\n\t * Decode a single base 64 character code digit to an integer. Returns -1 on\n\t * failure.\n\t */\n\texports.decode = function (charCode) {\n\t var bigA = 65; // 'A'\n\t var bigZ = 90; // 'Z'\n\t\n\t var littleA = 97; // 'a'\n\t var littleZ = 122; // 'z'\n\t\n\t var zero = 48; // '0'\n\t var nine = 57; // '9'\n\t\n\t var plus = 43; // '+'\n\t var slash = 47; // '/'\n\t\n\t var littleOffset = 26;\n\t var numberOffset = 52;\n\t\n\t // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ\n\t if (bigA <= charCode && charCode <= bigZ) {\n\t return (charCode - bigA);\n\t }\n\t\n\t // 26 - 51: abcdefghijklmnopqrstuvwxyz\n\t if (littleA <= charCode && charCode <= littleZ) {\n\t return (charCode - littleA + littleOffset);\n\t }\n\t\n\t // 52 - 61: 0123456789\n\t if (zero <= charCode && charCode <= nine) {\n\t return (charCode - zero + numberOffset);\n\t }\n\t\n\t // 62: +\n\t if (charCode == plus) {\n\t return 62;\n\t }\n\t\n\t // 63: /\n\t if (charCode == slash) {\n\t return 63;\n\t }\n\t\n\t // Invalid base64 digit.\n\t return -1;\n\t};\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\t/**\n\t * This is a helper function for getting values from parameter/options\n\t * objects.\n\t *\n\t * @param args The object we are extracting values from\n\t * @param name The name of the property we are getting.\n\t * @param defaultValue An optional value to return if the property is missing\n\t * from the object. If this is not specified and the property is missing, an\n\t * error will be thrown.\n\t */\n\tfunction getArg(aArgs, aName, aDefaultValue) {\n\t if (aName in aArgs) {\n\t return aArgs[aName];\n\t } else if (arguments.length === 3) {\n\t return aDefaultValue;\n\t } else {\n\t throw new Error('\"' + aName + '\" is a required argument.');\n\t }\n\t}\n\texports.getArg = getArg;\n\t\n\tvar urlRegexp = /^(?:([\\w+\\-.]+):)?\\/\\/(?:(\\w+:\\w+)@)?([\\w.]*)(?::(\\d+))?(\\S*)$/;\n\tvar dataUrlRegexp = /^data:.+\\,.+$/;\n\t\n\tfunction urlParse(aUrl) {\n\t var match = aUrl.match(urlRegexp);\n\t if (!match) {\n\t return null;\n\t }\n\t return {\n\t scheme: match[1],\n\t auth: match[2],\n\t host: match[3],\n\t port: match[4],\n\t path: match[5]\n\t };\n\t}\n\texports.urlParse = urlParse;\n\t\n\tfunction urlGenerate(aParsedUrl) {\n\t var url = '';\n\t if (aParsedUrl.scheme) {\n\t url += aParsedUrl.scheme + ':';\n\t }\n\t url += '//';\n\t if (aParsedUrl.auth) {\n\t url += aParsedUrl.auth + '@';\n\t }\n\t if (aParsedUrl.host) {\n\t url += aParsedUrl.host;\n\t }\n\t if (aParsedUrl.port) {\n\t url += \":\" + aParsedUrl.port\n\t }\n\t if (aParsedUrl.path) {\n\t url += aParsedUrl.path;\n\t }\n\t return url;\n\t}\n\texports.urlGenerate = urlGenerate;\n\t\n\t/**\n\t * Normalizes a path, or the path portion of a URL:\n\t *\n\t * - Replaces consecutive slashes with one slash.\n\t * - Removes unnecessary '.' parts.\n\t * - Removes unnecessary '/..' parts.\n\t *\n\t * Based on code in the Node.js 'path' core module.\n\t *\n\t * @param aPath The path or url to normalize.\n\t */\n\tfunction normalize(aPath) {\n\t var path = aPath;\n\t var url = urlParse(aPath);\n\t if (url) {\n\t if (!url.path) {\n\t return aPath;\n\t }\n\t path = url.path;\n\t }\n\t var isAbsolute = exports.isAbsolute(path);\n\t\n\t var parts = path.split(/\\/+/);\n\t for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {\n\t part = parts[i];\n\t if (part === '.') {\n\t parts.splice(i, 1);\n\t } else if (part === '..') {\n\t up++;\n\t } else if (up > 0) {\n\t if (part === '') {\n\t // The first part is blank if the path is absolute. Trying to go\n\t // above the root is a no-op. Therefore we can remove all '..' parts\n\t // directly after the root.\n\t parts.splice(i + 1, up);\n\t up = 0;\n\t } else {\n\t parts.splice(i, 2);\n\t up--;\n\t }\n\t }\n\t }\n\t path = parts.join('/');\n\t\n\t if (path === '') {\n\t path = isAbsolute ? '/' : '.';\n\t }\n\t\n\t if (url) {\n\t url.path = path;\n\t return urlGenerate(url);\n\t }\n\t return path;\n\t}\n\texports.normalize = normalize;\n\t\n\t/**\n\t * Joins two paths/URLs.\n\t *\n\t * @param aRoot The root path or URL.\n\t * @param aPath The path or URL to be joined with the root.\n\t *\n\t * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a\n\t * scheme-relative URL: Then the scheme of aRoot, if any, is prepended\n\t * first.\n\t * - Otherwise aPath is a path. If aRoot is a URL, then its path portion\n\t * is updated with the result and aRoot is returned. Otherwise the result\n\t * is returned.\n\t * - If aPath is absolute, the result is aPath.\n\t * - Otherwise the two paths are joined with a slash.\n\t * - Joining for example 'http://' and 'www.example.com' is also supported.\n\t */\n\tfunction join(aRoot, aPath) {\n\t if (aRoot === \"\") {\n\t aRoot = \".\";\n\t }\n\t if (aPath === \"\") {\n\t aPath = \".\";\n\t }\n\t var aPathUrl = urlParse(aPath);\n\t var aRootUrl = urlParse(aRoot);\n\t if (aRootUrl) {\n\t aRoot = aRootUrl.path || '/';\n\t }\n\t\n\t // `join(foo, '//www.example.org')`\n\t if (aPathUrl && !aPathUrl.scheme) {\n\t if (aRootUrl) {\n\t aPathUrl.scheme = aRootUrl.scheme;\n\t }\n\t return urlGenerate(aPathUrl);\n\t }\n\t\n\t if (aPathUrl || aPath.match(dataUrlRegexp)) {\n\t return aPath;\n\t }\n\t\n\t // `join('http://', 'www.example.com')`\n\t if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {\n\t aRootUrl.host = aPath;\n\t return urlGenerate(aRootUrl);\n\t }\n\t\n\t var joined = aPath.charAt(0) === '/'\n\t ? aPath\n\t : normalize(aRoot.replace(/\\/+$/, '') + '/' + aPath);\n\t\n\t if (aRootUrl) {\n\t aRootUrl.path = joined;\n\t return urlGenerate(aRootUrl);\n\t }\n\t return joined;\n\t}\n\texports.join = join;\n\t\n\texports.isAbsolute = function (aPath) {\n\t return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp);\n\t};\n\t\n\t/**\n\t * Make a path relative to a URL or another path.\n\t *\n\t * @param aRoot The root path or URL.\n\t * @param aPath The path or URL to be made relative to aRoot.\n\t */\n\tfunction relative(aRoot, aPath) {\n\t if (aRoot === \"\") {\n\t aRoot = \".\";\n\t }\n\t\n\t aRoot = aRoot.replace(/\\/$/, '');\n\t\n\t // It is possible for the path to be above the root. In this case, simply\n\t // checking whether the root is a prefix of the path won't work. Instead, we\n\t // need to remove components from the root one by one, until either we find\n\t // a prefix that fits, or we run out of components to remove.\n\t var level = 0;\n\t while (aPath.indexOf(aRoot + '/') !== 0) {\n\t var index = aRoot.lastIndexOf(\"/\");\n\t if (index < 0) {\n\t return aPath;\n\t }\n\t\n\t // If the only part of the root that is left is the scheme (i.e. http://,\n\t // file:///, etc.), one or more slashes (/), or simply nothing at all, we\n\t // have exhausted all components, so the path is not relative to the root.\n\t aRoot = aRoot.slice(0, index);\n\t if (aRoot.match(/^([^\\/]+:\\/)?\\/*$/)) {\n\t return aPath;\n\t }\n\t\n\t ++level;\n\t }\n\t\n\t // Make sure we add a \"../\" for each component we removed from the root.\n\t return Array(level + 1).join(\"../\") + aPath.substr(aRoot.length + 1);\n\t}\n\texports.relative = relative;\n\t\n\tvar supportsNullProto = (function () {\n\t var obj = Object.create(null);\n\t return !('__proto__' in obj);\n\t}());\n\t\n\tfunction identity (s) {\n\t return s;\n\t}\n\t\n\t/**\n\t * Because behavior goes wacky when you set `__proto__` on objects, we\n\t * have to prefix all the strings in our set with an arbitrary character.\n\t *\n\t * See https://github.com/mozilla/source-map/pull/31 and\n\t * https://github.com/mozilla/source-map/issues/30\n\t *\n\t * @param String aStr\n\t */\n\tfunction toSetString(aStr) {\n\t if (isProtoString(aStr)) {\n\t return '$' + aStr;\n\t }\n\t\n\t return aStr;\n\t}\n\texports.toSetString = supportsNullProto ? identity : toSetString;\n\t\n\tfunction fromSetString(aStr) {\n\t if (isProtoString(aStr)) {\n\t return aStr.slice(1);\n\t }\n\t\n\t return aStr;\n\t}\n\texports.fromSetString = supportsNullProto ? identity : fromSetString;\n\t\n\tfunction isProtoString(s) {\n\t if (!s) {\n\t return false;\n\t }\n\t\n\t var length = s.length;\n\t\n\t if (length < 9 /* \"__proto__\".length */) {\n\t return false;\n\t }\n\t\n\t if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||\n\t s.charCodeAt(length - 2) !== 95 /* '_' */ ||\n\t s.charCodeAt(length - 3) !== 111 /* 'o' */ ||\n\t s.charCodeAt(length - 4) !== 116 /* 't' */ ||\n\t s.charCodeAt(length - 5) !== 111 /* 'o' */ ||\n\t s.charCodeAt(length - 6) !== 114 /* 'r' */ ||\n\t s.charCodeAt(length - 7) !== 112 /* 'p' */ ||\n\t s.charCodeAt(length - 8) !== 95 /* '_' */ ||\n\t s.charCodeAt(length - 9) !== 95 /* '_' */) {\n\t return false;\n\t }\n\t\n\t for (var i = length - 10; i >= 0; i--) {\n\t if (s.charCodeAt(i) !== 36 /* '$' */) {\n\t return false;\n\t }\n\t }\n\t\n\t return true;\n\t}\n\t\n\t/**\n\t * Comparator between two mappings where the original positions are compared.\n\t *\n\t * Optionally pass in `true` as `onlyCompareGenerated` to consider two\n\t * mappings with the same original source/line/column, but different generated\n\t * line and column the same. Useful when searching for a mapping with a\n\t * stubbed out mapping.\n\t */\n\tfunction compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {\n\t var cmp = mappingA.source - mappingB.source;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.originalLine - mappingB.originalLine;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.originalColumn - mappingB.originalColumn;\n\t if (cmp !== 0 || onlyCompareOriginal) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.generatedLine - mappingB.generatedLine;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t return mappingA.name - mappingB.name;\n\t}\n\texports.compareByOriginalPositions = compareByOriginalPositions;\n\t\n\t/**\n\t * Comparator between two mappings with deflated source and name indices where\n\t * the generated positions are compared.\n\t *\n\t * Optionally pass in `true` as `onlyCompareGenerated` to consider two\n\t * mappings with the same generated line and column, but different\n\t * source/name/original line and column the same. Useful when searching for a\n\t * mapping with a stubbed out mapping.\n\t */\n\tfunction compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {\n\t var cmp = mappingA.generatedLine - mappingB.generatedLine;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n\t if (cmp !== 0 || onlyCompareGenerated) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.source - mappingB.source;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.originalLine - mappingB.originalLine;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.originalColumn - mappingB.originalColumn;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t return mappingA.name - mappingB.name;\n\t}\n\texports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;\n\t\n\tfunction strcmp(aStr1, aStr2) {\n\t if (aStr1 === aStr2) {\n\t return 0;\n\t }\n\t\n\t if (aStr1 > aStr2) {\n\t return 1;\n\t }\n\t\n\t return -1;\n\t}\n\t\n\t/**\n\t * Comparator between two mappings with inflated source and name strings where\n\t * the generated positions are compared.\n\t */\n\tfunction compareByGeneratedPositionsInflated(mappingA, mappingB) {\n\t var cmp = mappingA.generatedLine - mappingB.generatedLine;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = strcmp(mappingA.source, mappingB.source);\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.originalLine - mappingB.originalLine;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t cmp = mappingA.originalColumn - mappingB.originalColumn;\n\t if (cmp !== 0) {\n\t return cmp;\n\t }\n\t\n\t return strcmp(mappingA.name, mappingB.name);\n\t}\n\texports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\tvar util = __webpack_require__(4);\n\tvar has = Object.prototype.hasOwnProperty;\n\tvar hasNativeMap = typeof Map !== \"undefined\";\n\t\n\t/**\n\t * A data structure which is a combination of an array and a set. Adding a new\n\t * member is O(1), testing for membership is O(1), and finding the index of an\n\t * element is O(1). Removing elements from the set is not supported. Only\n\t * strings are supported for membership.\n\t */\n\tfunction ArraySet() {\n\t this._array = [];\n\t this._set = hasNativeMap ? new Map() : Object.create(null);\n\t}\n\t\n\t/**\n\t * Static method for creating ArraySet instances from an existing array.\n\t */\n\tArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {\n\t var set = new ArraySet();\n\t for (var i = 0, len = aArray.length; i < len; i++) {\n\t set.add(aArray[i], aAllowDuplicates);\n\t }\n\t return set;\n\t};\n\t\n\t/**\n\t * Return how many unique items are in this ArraySet. If duplicates have been\n\t * added, than those do not count towards the size.\n\t *\n\t * @returns Number\n\t */\n\tArraySet.prototype.size = function ArraySet_size() {\n\t return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;\n\t};\n\t\n\t/**\n\t * Add the given string to this set.\n\t *\n\t * @param String aStr\n\t */\n\tArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {\n\t var sStr = hasNativeMap ? aStr : util.toSetString(aStr);\n\t var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);\n\t var idx = this._array.length;\n\t if (!isDuplicate || aAllowDuplicates) {\n\t this._array.push(aStr);\n\t }\n\t if (!isDuplicate) {\n\t if (hasNativeMap) {\n\t this._set.set(aStr, idx);\n\t } else {\n\t this._set[sStr] = idx;\n\t }\n\t }\n\t};\n\t\n\t/**\n\t * Is the given string a member of this set?\n\t *\n\t * @param String aStr\n\t */\n\tArraySet.prototype.has = function ArraySet_has(aStr) {\n\t if (hasNativeMap) {\n\t return this._set.has(aStr);\n\t } else {\n\t var sStr = util.toSetString(aStr);\n\t return has.call(this._set, sStr);\n\t }\n\t};\n\t\n\t/**\n\t * What is the index of the given string in the array?\n\t *\n\t * @param String aStr\n\t */\n\tArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {\n\t if (hasNativeMap) {\n\t var idx = this._set.get(aStr);\n\t if (idx >= 0) {\n\t return idx;\n\t }\n\t } else {\n\t var sStr = util.toSetString(aStr);\n\t if (has.call(this._set, sStr)) {\n\t return this._set[sStr];\n\t }\n\t }\n\t\n\t throw new Error('\"' + aStr + '\" is not in the set.');\n\t};\n\t\n\t/**\n\t * What is the element at the given index?\n\t *\n\t * @param Number aIdx\n\t */\n\tArraySet.prototype.at = function ArraySet_at(aIdx) {\n\t if (aIdx >= 0 && aIdx < this._array.length) {\n\t return this._array[aIdx];\n\t }\n\t throw new Error('No element indexed by ' + aIdx);\n\t};\n\t\n\t/**\n\t * Returns the array representation of this set (which has the proper indices\n\t * indicated by indexOf). Note that this is a copy of the internal array used\n\t * for storing the members so that no one can mess with internal state.\n\t */\n\tArraySet.prototype.toArray = function ArraySet_toArray() {\n\t return this._array.slice();\n\t};\n\t\n\texports.ArraySet = ArraySet;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2014 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\tvar util = __webpack_require__(4);\n\t\n\t/**\n\t * Determine whether mappingB is after mappingA with respect to generated\n\t * position.\n\t */\n\tfunction generatedPositionAfter(mappingA, mappingB) {\n\t // Optimized for most common case\n\t var lineA = mappingA.generatedLine;\n\t var lineB = mappingB.generatedLine;\n\t var columnA = mappingA.generatedColumn;\n\t var columnB = mappingB.generatedColumn;\n\t return lineB > lineA || lineB == lineA && columnB >= columnA ||\n\t util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;\n\t}\n\t\n\t/**\n\t * A data structure to provide a sorted view of accumulated mappings in a\n\t * performance conscious manner. It trades a neglibable overhead in general\n\t * case for a large speedup in case of mappings being added in order.\n\t */\n\tfunction MappingList() {\n\t this._array = [];\n\t this._sorted = true;\n\t // Serves as infimum\n\t this._last = {generatedLine: -1, generatedColumn: 0};\n\t}\n\t\n\t/**\n\t * Iterate through internal items. This method takes the same arguments that\n\t * `Array.prototype.forEach` takes.\n\t *\n\t * NOTE: The order of the mappings is NOT guaranteed.\n\t */\n\tMappingList.prototype.unsortedForEach =\n\t function MappingList_forEach(aCallback, aThisArg) {\n\t this._array.forEach(aCallback, aThisArg);\n\t };\n\t\n\t/**\n\t * Add the given source mapping.\n\t *\n\t * @param Object aMapping\n\t */\n\tMappingList.prototype.add = function MappingList_add(aMapping) {\n\t if (generatedPositionAfter(this._last, aMapping)) {\n\t this._last = aMapping;\n\t this._array.push(aMapping);\n\t } else {\n\t this._sorted = false;\n\t this._array.push(aMapping);\n\t }\n\t};\n\t\n\t/**\n\t * Returns the flat, sorted array of mappings. The mappings are sorted by\n\t * generated position.\n\t *\n\t * WARNING: This method returns internal data without copying, for\n\t * performance. The return value must NOT be mutated, and should be treated as\n\t * an immutable borrow. If you want to take ownership, you must make your own\n\t * copy.\n\t */\n\tMappingList.prototype.toArray = function MappingList_toArray() {\n\t if (!this._sorted) {\n\t this._array.sort(util.compareByGeneratedPositionsInflated);\n\t this._sorted = true;\n\t }\n\t return this._array;\n\t};\n\t\n\texports.MappingList = MappingList;\n\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\tvar util = __webpack_require__(4);\n\tvar binarySearch = __webpack_require__(8);\n\tvar ArraySet = __webpack_require__(5).ArraySet;\n\tvar base64VLQ = __webpack_require__(2);\n\tvar quickSort = __webpack_require__(9).quickSort;\n\t\n\tfunction SourceMapConsumer(aSourceMap) {\n\t var sourceMap = aSourceMap;\n\t if (typeof aSourceMap === 'string') {\n\t sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n\t }\n\t\n\t return sourceMap.sections != null\n\t ? new IndexedSourceMapConsumer(sourceMap)\n\t : new BasicSourceMapConsumer(sourceMap);\n\t}\n\t\n\tSourceMapConsumer.fromSourceMap = function(aSourceMap) {\n\t return BasicSourceMapConsumer.fromSourceMap(aSourceMap);\n\t}\n\t\n\t/**\n\t * The version of the source mapping spec that we are consuming.\n\t */\n\tSourceMapConsumer.prototype._version = 3;\n\t\n\t// `__generatedMappings` and `__originalMappings` are arrays that hold the\n\t// parsed mapping coordinates from the source map's \"mappings\" attribute. They\n\t// are lazily instantiated, accessed via the `_generatedMappings` and\n\t// `_originalMappings` getters respectively, and we only parse the mappings\n\t// and create these arrays once queried for a source location. We jump through\n\t// these hoops because there can be many thousands of mappings, and parsing\n\t// them is expensive, so we only want to do it if we must.\n\t//\n\t// Each object in the arrays is of the form:\n\t//\n\t// {\n\t// generatedLine: The line number in the generated code,\n\t// generatedColumn: The column number in the generated code,\n\t// source: The path to the original source file that generated this\n\t// chunk of code,\n\t// originalLine: The line number in the original source that\n\t// corresponds to this chunk of generated code,\n\t// originalColumn: The column number in the original source that\n\t// corresponds to this chunk of generated code,\n\t// name: The name of the original symbol which generated this chunk of\n\t// code.\n\t// }\n\t//\n\t// All properties except for `generatedLine` and `generatedColumn` can be\n\t// `null`.\n\t//\n\t// `_generatedMappings` is ordered by the generated positions.\n\t//\n\t// `_originalMappings` is ordered by the original positions.\n\t\n\tSourceMapConsumer.prototype.__generatedMappings = null;\n\tObject.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {\n\t get: function () {\n\t if (!this.__generatedMappings) {\n\t this._parseMappings(this._mappings, this.sourceRoot);\n\t }\n\t\n\t return this.__generatedMappings;\n\t }\n\t});\n\t\n\tSourceMapConsumer.prototype.__originalMappings = null;\n\tObject.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {\n\t get: function () {\n\t if (!this.__originalMappings) {\n\t this._parseMappings(this._mappings, this.sourceRoot);\n\t }\n\t\n\t return this.__originalMappings;\n\t }\n\t});\n\t\n\tSourceMapConsumer.prototype._charIsMappingSeparator =\n\t function SourceMapConsumer_charIsMappingSeparator(aStr, index) {\n\t var c = aStr.charAt(index);\n\t return c === \";\" || c === \",\";\n\t };\n\t\n\t/**\n\t * Parse the mappings in a string in to a data structure which we can easily\n\t * query (the ordered arrays in the `this.__generatedMappings` and\n\t * `this.__originalMappings` properties).\n\t */\n\tSourceMapConsumer.prototype._parseMappings =\n\t function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n\t throw new Error(\"Subclasses must implement _parseMappings\");\n\t };\n\t\n\tSourceMapConsumer.GENERATED_ORDER = 1;\n\tSourceMapConsumer.ORIGINAL_ORDER = 2;\n\t\n\tSourceMapConsumer.GREATEST_LOWER_BOUND = 1;\n\tSourceMapConsumer.LEAST_UPPER_BOUND = 2;\n\t\n\t/**\n\t * Iterate over each mapping between an original source/line/column and a\n\t * generated line/column in this source map.\n\t *\n\t * @param Function aCallback\n\t * The function that is called with each mapping.\n\t * @param Object aContext\n\t * Optional. If specified, this object will be the value of `this` every\n\t * time that `aCallback` is called.\n\t * @param aOrder\n\t * Either `SourceMapConsumer.GENERATED_ORDER` or\n\t * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to\n\t * iterate over the mappings sorted by the generated file's line/column\n\t * order or the original's source/line/column order, respectively. Defaults to\n\t * `SourceMapConsumer.GENERATED_ORDER`.\n\t */\n\tSourceMapConsumer.prototype.eachMapping =\n\t function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {\n\t var context = aContext || null;\n\t var order = aOrder || SourceMapConsumer.GENERATED_ORDER;\n\t\n\t var mappings;\n\t switch (order) {\n\t case SourceMapConsumer.GENERATED_ORDER:\n\t mappings = this._generatedMappings;\n\t break;\n\t case SourceMapConsumer.ORIGINAL_ORDER:\n\t mappings = this._originalMappings;\n\t break;\n\t default:\n\t throw new Error(\"Unknown order of iteration.\");\n\t }\n\t\n\t var sourceRoot = this.sourceRoot;\n\t mappings.map(function (mapping) {\n\t var source = mapping.source === null ? null : this._sources.at(mapping.source);\n\t if (source != null && sourceRoot != null) {\n\t source = util.join(sourceRoot, source);\n\t }\n\t return {\n\t source: source,\n\t generatedLine: mapping.generatedLine,\n\t generatedColumn: mapping.generatedColumn,\n\t originalLine: mapping.originalLine,\n\t originalColumn: mapping.originalColumn,\n\t name: mapping.name === null ? null : this._names.at(mapping.name)\n\t };\n\t }, this).forEach(aCallback, context);\n\t };\n\t\n\t/**\n\t * Returns all generated line and column information for the original source,\n\t * line, and column provided. If no column is provided, returns all mappings\n\t * corresponding to a either the line we are searching for or the next\n\t * closest line that has any mappings. Otherwise, returns all mappings\n\t * corresponding to the given line and either the column we are searching for\n\t * or the next closest column that has any offsets.\n\t *\n\t * The only argument is an object with the following properties:\n\t *\n\t * - source: The filename of the original source.\n\t * - line: The line number in the original source.\n\t * - column: Optional. the column number in the original source.\n\t *\n\t * and an array of objects is returned, each with the following properties:\n\t *\n\t * - line: The line number in the generated source, or null.\n\t * - column: The column number in the generated source, or null.\n\t */\n\tSourceMapConsumer.prototype.allGeneratedPositionsFor =\n\t function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {\n\t var line = util.getArg(aArgs, 'line');\n\t\n\t // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping\n\t // returns the index of the closest mapping less than the needle. By\n\t // setting needle.originalColumn to 0, we thus find the last mapping for\n\t // the given line, provided such a mapping exists.\n\t var needle = {\n\t source: util.getArg(aArgs, 'source'),\n\t originalLine: line,\n\t originalColumn: util.getArg(aArgs, 'column', 0)\n\t };\n\t\n\t if (this.sourceRoot != null) {\n\t needle.source = util.relative(this.sourceRoot, needle.source);\n\t }\n\t if (!this._sources.has(needle.source)) {\n\t return [];\n\t }\n\t needle.source = this._sources.indexOf(needle.source);\n\t\n\t var mappings = [];\n\t\n\t var index = this._findMapping(needle,\n\t this._originalMappings,\n\t \"originalLine\",\n\t \"originalColumn\",\n\t util.compareByOriginalPositions,\n\t binarySearch.LEAST_UPPER_BOUND);\n\t if (index >= 0) {\n\t var mapping = this._originalMappings[index];\n\t\n\t if (aArgs.column === undefined) {\n\t var originalLine = mapping.originalLine;\n\t\n\t // Iterate until either we run out of mappings, or we run into\n\t // a mapping for a different line than the one we found. Since\n\t // mappings are sorted, this is guaranteed to find all mappings for\n\t // the line we found.\n\t while (mapping && mapping.originalLine === originalLine) {\n\t mappings.push({\n\t line: util.getArg(mapping, 'generatedLine', null),\n\t column: util.getArg(mapping, 'generatedColumn', null),\n\t lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n\t });\n\t\n\t mapping = this._originalMappings[++index];\n\t }\n\t } else {\n\t var originalColumn = mapping.originalColumn;\n\t\n\t // Iterate until either we run out of mappings, or we run into\n\t // a mapping for a different line than the one we were searching for.\n\t // Since mappings are sorted, this is guaranteed to find all mappings for\n\t // the line we are searching for.\n\t while (mapping &&\n\t mapping.originalLine === line &&\n\t mapping.originalColumn == originalColumn) {\n\t mappings.push({\n\t line: util.getArg(mapping, 'generatedLine', null),\n\t column: util.getArg(mapping, 'generatedColumn', null),\n\t lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n\t });\n\t\n\t mapping = this._originalMappings[++index];\n\t }\n\t }\n\t }\n\t\n\t return mappings;\n\t };\n\t\n\texports.SourceMapConsumer = SourceMapConsumer;\n\t\n\t/**\n\t * A BasicSourceMapConsumer instance represents a parsed source map which we can\n\t * query for information about the original file positions by giving it a file\n\t * position in the generated source.\n\t *\n\t * The only parameter is the raw source map (either as a JSON string, or\n\t * already parsed to an object). According to the spec, source maps have the\n\t * following attributes:\n\t *\n\t * - version: Which version of the source map spec this map is following.\n\t * - sources: An array of URLs to the original source files.\n\t * - names: An array of identifiers which can be referrenced by individual mappings.\n\t * - sourceRoot: Optional. The URL root from which all sources are relative.\n\t * - sourcesContent: Optional. An array of contents of the original source files.\n\t * - mappings: A string of base64 VLQs which contain the actual mappings.\n\t * - file: Optional. The generated file this source map is associated with.\n\t *\n\t * Here is an example source map, taken from the source map spec[0]:\n\t *\n\t * {\n\t * version : 3,\n\t * file: \"out.js\",\n\t * sourceRoot : \"\",\n\t * sources: [\"foo.js\", \"bar.js\"],\n\t * names: [\"src\", \"maps\", \"are\", \"fun\"],\n\t * mappings: \"AA,AB;;ABCDE;\"\n\t * }\n\t *\n\t * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#\n\t */\n\tfunction BasicSourceMapConsumer(aSourceMap) {\n\t var sourceMap = aSourceMap;\n\t if (typeof aSourceMap === 'string') {\n\t sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n\t }\n\t\n\t var version = util.getArg(sourceMap, 'version');\n\t var sources = util.getArg(sourceMap, 'sources');\n\t // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which\n\t // requires the array) to play nice here.\n\t var names = util.getArg(sourceMap, 'names', []);\n\t var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);\n\t var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);\n\t var mappings = util.getArg(sourceMap, 'mappings');\n\t var file = util.getArg(sourceMap, 'file', null);\n\t\n\t // Once again, Sass deviates from the spec and supplies the version as a\n\t // string rather than a number, so we use loose equality checking here.\n\t if (version != this._version) {\n\t throw new Error('Unsupported version: ' + version);\n\t }\n\t\n\t sources = sources\n\t .map(String)\n\t // Some source maps produce relative source paths like \"./foo.js\" instead of\n\t // \"foo.js\". Normalize these first so that future comparisons will succeed.\n\t // See bugzil.la/1090768.\n\t .map(util.normalize)\n\t // Always ensure that absolute sources are internally stored relative to\n\t // the source root, if the source root is absolute. Not doing this would\n\t // be particularly problematic when the source root is a prefix of the\n\t // source (valid, but why??). See github issue #199 and bugzil.la/1188982.\n\t .map(function (source) {\n\t return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)\n\t ? util.relative(sourceRoot, source)\n\t : source;\n\t });\n\t\n\t // Pass `true` below to allow duplicate names and sources. While source maps\n\t // are intended to be compressed and deduplicated, the TypeScript compiler\n\t // sometimes generates source maps with duplicates in them. See Github issue\n\t // #72 and bugzil.la/889492.\n\t this._names = ArraySet.fromArray(names.map(String), true);\n\t this._sources = ArraySet.fromArray(sources, true);\n\t\n\t this.sourceRoot = sourceRoot;\n\t this.sourcesContent = sourcesContent;\n\t this._mappings = mappings;\n\t this.file = file;\n\t}\n\t\n\tBasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);\n\tBasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;\n\t\n\t/**\n\t * Create a BasicSourceMapConsumer from a SourceMapGenerator.\n\t *\n\t * @param SourceMapGenerator aSourceMap\n\t * The source map that will be consumed.\n\t * @returns BasicSourceMapConsumer\n\t */\n\tBasicSourceMapConsumer.fromSourceMap =\n\t function SourceMapConsumer_fromSourceMap(aSourceMap) {\n\t var smc = Object.create(BasicSourceMapConsumer.prototype);\n\t\n\t var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);\n\t var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);\n\t smc.sourceRoot = aSourceMap._sourceRoot;\n\t smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),\n\t smc.sourceRoot);\n\t smc.file = aSourceMap._file;\n\t\n\t // Because we are modifying the entries (by converting string sources and\n\t // names to indices into the sources and names ArraySets), we have to make\n\t // a copy of the entry or else bad things happen. Shared mutable state\n\t // strikes again! See github issue #191.\n\t\n\t var generatedMappings = aSourceMap._mappings.toArray().slice();\n\t var destGeneratedMappings = smc.__generatedMappings = [];\n\t var destOriginalMappings = smc.__originalMappings = [];\n\t\n\t for (var i = 0, length = generatedMappings.length; i < length; i++) {\n\t var srcMapping = generatedMappings[i];\n\t var destMapping = new Mapping;\n\t destMapping.generatedLine = srcMapping.generatedLine;\n\t destMapping.generatedColumn = srcMapping.generatedColumn;\n\t\n\t if (srcMapping.source) {\n\t destMapping.source = sources.indexOf(srcMapping.source);\n\t destMapping.originalLine = srcMapping.originalLine;\n\t destMapping.originalColumn = srcMapping.originalColumn;\n\t\n\t if (srcMapping.name) {\n\t destMapping.name = names.indexOf(srcMapping.name);\n\t }\n\t\n\t destOriginalMappings.push(destMapping);\n\t }\n\t\n\t destGeneratedMappings.push(destMapping);\n\t }\n\t\n\t quickSort(smc.__originalMappings, util.compareByOriginalPositions);\n\t\n\t return smc;\n\t };\n\t\n\t/**\n\t * The version of the source mapping spec that we are consuming.\n\t */\n\tBasicSourceMapConsumer.prototype._version = 3;\n\t\n\t/**\n\t * The list of original sources.\n\t */\n\tObject.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {\n\t get: function () {\n\t return this._sources.toArray().map(function (s) {\n\t return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;\n\t }, this);\n\t }\n\t});\n\t\n\t/**\n\t * Provide the JIT with a nice shape / hidden class.\n\t */\n\tfunction Mapping() {\n\t this.generatedLine = 0;\n\t this.generatedColumn = 0;\n\t this.source = null;\n\t this.originalLine = null;\n\t this.originalColumn = null;\n\t this.name = null;\n\t}\n\t\n\t/**\n\t * Parse the mappings in a string in to a data structure which we can easily\n\t * query (the ordered arrays in the `this.__generatedMappings` and\n\t * `this.__originalMappings` properties).\n\t */\n\tBasicSourceMapConsumer.prototype._parseMappings =\n\t function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n\t var generatedLine = 1;\n\t var previousGeneratedColumn = 0;\n\t var previousOriginalLine = 0;\n\t var previousOriginalColumn = 0;\n\t var previousSource = 0;\n\t var previousName = 0;\n\t var length = aStr.length;\n\t var index = 0;\n\t var cachedSegments = {};\n\t var temp = {};\n\t var originalMappings = [];\n\t var generatedMappings = [];\n\t var mapping, str, segment, end, value;\n\t\n\t while (index < length) {\n\t if (aStr.charAt(index) === ';') {\n\t generatedLine++;\n\t index++;\n\t previousGeneratedColumn = 0;\n\t }\n\t else if (aStr.charAt(index) === ',') {\n\t index++;\n\t }\n\t else {\n\t mapping = new Mapping();\n\t mapping.generatedLine = generatedLine;\n\t\n\t // Because each offset is encoded relative to the previous one,\n\t // many segments often have the same encoding. We can exploit this\n\t // fact by caching the parsed variable length fields of each segment,\n\t // allowing us to avoid a second parse if we encounter the same\n\t // segment again.\n\t for (end = index; end < length; end++) {\n\t if (this._charIsMappingSeparator(aStr, end)) {\n\t break;\n\t }\n\t }\n\t str = aStr.slice(index, end);\n\t\n\t segment = cachedSegments[str];\n\t if (segment) {\n\t index += str.length;\n\t } else {\n\t segment = [];\n\t while (index < end) {\n\t base64VLQ.decode(aStr, index, temp);\n\t value = temp.value;\n\t index = temp.rest;\n\t segment.push(value);\n\t }\n\t\n\t if (segment.length === 2) {\n\t throw new Error('Found a source, but no line and column');\n\t }\n\t\n\t if (segment.length === 3) {\n\t throw new Error('Found a source and line, but no column');\n\t }\n\t\n\t cachedSegments[str] = segment;\n\t }\n\t\n\t // Generated column.\n\t mapping.generatedColumn = previousGeneratedColumn + segment[0];\n\t previousGeneratedColumn = mapping.generatedColumn;\n\t\n\t if (segment.length > 1) {\n\t // Original source.\n\t mapping.source = previousSource + segment[1];\n\t previousSource += segment[1];\n\t\n\t // Original line.\n\t mapping.originalLine = previousOriginalLine + segment[2];\n\t previousOriginalLine = mapping.originalLine;\n\t // Lines are stored 0-based\n\t mapping.originalLine += 1;\n\t\n\t // Original column.\n\t mapping.originalColumn = previousOriginalColumn + segment[3];\n\t previousOriginalColumn = mapping.originalColumn;\n\t\n\t if (segment.length > 4) {\n\t // Original name.\n\t mapping.name = previousName + segment[4];\n\t previousName += segment[4];\n\t }\n\t }\n\t\n\t generatedMappings.push(mapping);\n\t if (typeof mapping.originalLine === 'number') {\n\t originalMappings.push(mapping);\n\t }\n\t }\n\t }\n\t\n\t quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);\n\t this.__generatedMappings = generatedMappings;\n\t\n\t quickSort(originalMappings, util.compareByOriginalPositions);\n\t this.__originalMappings = originalMappings;\n\t };\n\t\n\t/**\n\t * Find the mapping that best matches the hypothetical \"needle\" mapping that\n\t * we are searching for in the given \"haystack\" of mappings.\n\t */\n\tBasicSourceMapConsumer.prototype._findMapping =\n\t function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,\n\t aColumnName, aComparator, aBias) {\n\t // To return the position we are searching for, we must first find the\n\t // mapping for the given position and then return the opposite position it\n\t // points to. Because the mappings are sorted, we can use binary search to\n\t // find the best mapping.\n\t\n\t if (aNeedle[aLineName] <= 0) {\n\t throw new TypeError('Line must be greater than or equal to 1, got '\n\t + aNeedle[aLineName]);\n\t }\n\t if (aNeedle[aColumnName] < 0) {\n\t throw new TypeError('Column must be greater than or equal to 0, got '\n\t + aNeedle[aColumnName]);\n\t }\n\t\n\t return binarySearch.search(aNeedle, aMappings, aComparator, aBias);\n\t };\n\t\n\t/**\n\t * Compute the last column for each generated mapping. The last column is\n\t * inclusive.\n\t */\n\tBasicSourceMapConsumer.prototype.computeColumnSpans =\n\t function SourceMapConsumer_computeColumnSpans() {\n\t for (var index = 0; index < this._generatedMappings.length; ++index) {\n\t var mapping = this._generatedMappings[index];\n\t\n\t // Mappings do not contain a field for the last generated columnt. We\n\t // can come up with an optimistic estimate, however, by assuming that\n\t // mappings are contiguous (i.e. given two consecutive mappings, the\n\t // first mapping ends where the second one starts).\n\t if (index + 1 < this._generatedMappings.length) {\n\t var nextMapping = this._generatedMappings[index + 1];\n\t\n\t if (mapping.generatedLine === nextMapping.generatedLine) {\n\t mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;\n\t continue;\n\t }\n\t }\n\t\n\t // The last mapping for each line spans the entire line.\n\t mapping.lastGeneratedColumn = Infinity;\n\t }\n\t };\n\t\n\t/**\n\t * Returns the original source, line, and column information for the generated\n\t * source's line and column positions provided. The only argument is an object\n\t * with the following properties:\n\t *\n\t * - line: The line number in the generated source.\n\t * - column: The column number in the generated source.\n\t * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or\n\t * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the\n\t * closest element that is smaller than or greater than the one we are\n\t * searching for, respectively, if the exact element cannot be found.\n\t * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.\n\t *\n\t * and an object is returned with the following properties:\n\t *\n\t * - source: The original source file, or null.\n\t * - line: The line number in the original source, or null.\n\t * - column: The column number in the original source, or null.\n\t * - name: The original identifier, or null.\n\t */\n\tBasicSourceMapConsumer.prototype.originalPositionFor =\n\t function SourceMapConsumer_originalPositionFor(aArgs) {\n\t var needle = {\n\t generatedLine: util.getArg(aArgs, 'line'),\n\t generatedColumn: util.getArg(aArgs, 'column')\n\t };\n\t\n\t var index = this._findMapping(\n\t needle,\n\t this._generatedMappings,\n\t \"generatedLine\",\n\t \"generatedColumn\",\n\t util.compareByGeneratedPositionsDeflated,\n\t util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)\n\t );\n\t\n\t if (index >= 0) {\n\t var mapping = this._generatedMappings[index];\n\t\n\t if (mapping.generatedLine === needle.generatedLine) {\n\t var source = util.getArg(mapping, 'source', null);\n\t if (source !== null) {\n\t source = this._sources.at(source);\n\t if (this.sourceRoot != null) {\n\t source = util.join(this.sourceRoot, source);\n\t }\n\t }\n\t var name = util.getArg(mapping, 'name', null);\n\t if (name !== null) {\n\t name = this._names.at(name);\n\t }\n\t return {\n\t source: source,\n\t line: util.getArg(mapping, 'originalLine', null),\n\t column: util.getArg(mapping, 'originalColumn', null),\n\t name: name\n\t };\n\t }\n\t }\n\t\n\t return {\n\t source: null,\n\t line: null,\n\t column: null,\n\t name: null\n\t };\n\t };\n\t\n\t/**\n\t * Return true if we have the source content for every source in the source\n\t * map, false otherwise.\n\t */\n\tBasicSourceMapConsumer.prototype.hasContentsOfAllSources =\n\t function BasicSourceMapConsumer_hasContentsOfAllSources() {\n\t if (!this.sourcesContent) {\n\t return false;\n\t }\n\t return this.sourcesContent.length >= this._sources.size() &&\n\t !this.sourcesContent.some(function (sc) { return sc == null; });\n\t };\n\t\n\t/**\n\t * Returns the original source content. The only argument is the url of the\n\t * original source file. Returns null if no original source content is\n\t * available.\n\t */\n\tBasicSourceMapConsumer.prototype.sourceContentFor =\n\t function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {\n\t if (!this.sourcesContent) {\n\t return null;\n\t }\n\t\n\t if (this.sourceRoot != null) {\n\t aSource = util.relative(this.sourceRoot, aSource);\n\t }\n\t\n\t if (this._sources.has(aSource)) {\n\t return this.sourcesContent[this._sources.indexOf(aSource)];\n\t }\n\t\n\t var url;\n\t if (this.sourceRoot != null\n\t && (url = util.urlParse(this.sourceRoot))) {\n\t // XXX: file:// URIs and absolute paths lead to unexpected behavior for\n\t // many users. We can help them out when they expect file:// URIs to\n\t // behave like it would if they were running a local HTTP server. See\n\t // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.\n\t var fileUriAbsPath = aSource.replace(/^file:\\/\\//, \"\");\n\t if (url.scheme == \"file\"\n\t && this._sources.has(fileUriAbsPath)) {\n\t return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]\n\t }\n\t\n\t if ((!url.path || url.path == \"/\")\n\t && this._sources.has(\"/\" + aSource)) {\n\t return this.sourcesContent[this._sources.indexOf(\"/\" + aSource)];\n\t }\n\t }\n\t\n\t // This function is used recursively from\n\t // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we\n\t // don't want to throw if we can't find the source - we just want to\n\t // return null, so we provide a flag to exit gracefully.\n\t if (nullOnMissing) {\n\t return null;\n\t }\n\t else {\n\t throw new Error('\"' + aSource + '\" is not in the SourceMap.');\n\t }\n\t };\n\t\n\t/**\n\t * Returns the generated line and column information for the original source,\n\t * line, and column positions provided. The only argument is an object with\n\t * the following properties:\n\t *\n\t * - source: The filename of the original source.\n\t * - line: The line number in the original source.\n\t * - column: The column number in the original source.\n\t * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or\n\t * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the\n\t * closest element that is smaller than or greater than the one we are\n\t * searching for, respectively, if the exact element cannot be found.\n\t * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.\n\t *\n\t * and an object is returned with the following properties:\n\t *\n\t * - line: The line number in the generated source, or null.\n\t * - column: The column number in the generated source, or null.\n\t */\n\tBasicSourceMapConsumer.prototype.generatedPositionFor =\n\t function SourceMapConsumer_generatedPositionFor(aArgs) {\n\t var source = util.getArg(aArgs, 'source');\n\t if (this.sourceRoot != null) {\n\t source = util.relative(this.sourceRoot, source);\n\t }\n\t if (!this._sources.has(source)) {\n\t return {\n\t line: null,\n\t column: null,\n\t lastColumn: null\n\t };\n\t }\n\t source = this._sources.indexOf(source);\n\t\n\t var needle = {\n\t source: source,\n\t originalLine: util.getArg(aArgs, 'line'),\n\t originalColumn: util.getArg(aArgs, 'column')\n\t };\n\t\n\t var index = this._findMapping(\n\t needle,\n\t this._originalMappings,\n\t \"originalLine\",\n\t \"originalColumn\",\n\t util.compareByOriginalPositions,\n\t util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)\n\t );\n\t\n\t if (index >= 0) {\n\t var mapping = this._originalMappings[index];\n\t\n\t if (mapping.source === needle.source) {\n\t return {\n\t line: util.getArg(mapping, 'generatedLine', null),\n\t column: util.getArg(mapping, 'generatedColumn', null),\n\t lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n\t };\n\t }\n\t }\n\t\n\t return {\n\t line: null,\n\t column: null,\n\t lastColumn: null\n\t };\n\t };\n\t\n\texports.BasicSourceMapConsumer = BasicSourceMapConsumer;\n\t\n\t/**\n\t * An IndexedSourceMapConsumer instance represents a parsed source map which\n\t * we can query for information. It differs from BasicSourceMapConsumer in\n\t * that it takes \"indexed\" source maps (i.e. ones with a \"sections\" field) as\n\t * input.\n\t *\n\t * The only parameter is a raw source map (either as a JSON string, or already\n\t * parsed to an object). According to the spec for indexed source maps, they\n\t * have the following attributes:\n\t *\n\t * - version: Which version of the source map spec this map is following.\n\t * - file: Optional. The generated file this source map is associated with.\n\t * - sections: A list of section definitions.\n\t *\n\t * Each value under the \"sections\" field has two fields:\n\t * - offset: The offset into the original specified at which this section\n\t * begins to apply, defined as an object with a \"line\" and \"column\"\n\t * field.\n\t * - map: A source map definition. This source map could also be indexed,\n\t * but doesn't have to be.\n\t *\n\t * Instead of the \"map\" field, it's also possible to have a \"url\" field\n\t * specifying a URL to retrieve a source map from, but that's currently\n\t * unsupported.\n\t *\n\t * Here's an example source map, taken from the source map spec[0], but\n\t * modified to omit a section which uses the \"url\" field.\n\t *\n\t * {\n\t * version : 3,\n\t * file: \"app.js\",\n\t * sections: [{\n\t * offset: {line:100, column:10},\n\t * map: {\n\t * version : 3,\n\t * file: \"section.js\",\n\t * sources: [\"foo.js\", \"bar.js\"],\n\t * names: [\"src\", \"maps\", \"are\", \"fun\"],\n\t * mappings: \"AAAA,E;;ABCDE;\"\n\t * }\n\t * }],\n\t * }\n\t *\n\t * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt\n\t */\n\tfunction IndexedSourceMapConsumer(aSourceMap) {\n\t var sourceMap = aSourceMap;\n\t if (typeof aSourceMap === 'string') {\n\t sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n\t }\n\t\n\t var version = util.getArg(sourceMap, 'version');\n\t var sections = util.getArg(sourceMap, 'sections');\n\t\n\t if (version != this._version) {\n\t throw new Error('Unsupported version: ' + version);\n\t }\n\t\n\t this._sources = new ArraySet();\n\t this._names = new ArraySet();\n\t\n\t var lastOffset = {\n\t line: -1,\n\t column: 0\n\t };\n\t this._sections = sections.map(function (s) {\n\t if (s.url) {\n\t // The url field will require support for asynchronicity.\n\t // See https://github.com/mozilla/source-map/issues/16\n\t throw new Error('Support for url field in sections not implemented.');\n\t }\n\t var offset = util.getArg(s, 'offset');\n\t var offsetLine = util.getArg(offset, 'line');\n\t var offsetColumn = util.getArg(offset, 'column');\n\t\n\t if (offsetLine < lastOffset.line ||\n\t (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {\n\t throw new Error('Section offsets must be ordered and non-overlapping.');\n\t }\n\t lastOffset = offset;\n\t\n\t return {\n\t generatedOffset: {\n\t // The offset fields are 0-based, but we use 1-based indices when\n\t // encoding/decoding from VLQ.\n\t generatedLine: offsetLine + 1,\n\t generatedColumn: offsetColumn + 1\n\t },\n\t consumer: new SourceMapConsumer(util.getArg(s, 'map'))\n\t }\n\t });\n\t}\n\t\n\tIndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);\n\tIndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;\n\t\n\t/**\n\t * The version of the source mapping spec that we are consuming.\n\t */\n\tIndexedSourceMapConsumer.prototype._version = 3;\n\t\n\t/**\n\t * The list of original sources.\n\t */\n\tObject.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {\n\t get: function () {\n\t var sources = [];\n\t for (var i = 0; i < this._sections.length; i++) {\n\t for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {\n\t sources.push(this._sections[i].consumer.sources[j]);\n\t }\n\t }\n\t return sources;\n\t }\n\t});\n\t\n\t/**\n\t * Returns the original source, line, and column information for the generated\n\t * source's line and column positions provided. The only argument is an object\n\t * with the following properties:\n\t *\n\t * - line: The line number in the generated source.\n\t * - column: The column number in the generated source.\n\t *\n\t * and an object is returned with the following properties:\n\t *\n\t * - source: The original source file, or null.\n\t * - line: The line number in the original source, or null.\n\t * - column: The column number in the original source, or null.\n\t * - name: The original identifier, or null.\n\t */\n\tIndexedSourceMapConsumer.prototype.originalPositionFor =\n\t function IndexedSourceMapConsumer_originalPositionFor(aArgs) {\n\t var needle = {\n\t generatedLine: util.getArg(aArgs, 'line'),\n\t generatedColumn: util.getArg(aArgs, 'column')\n\t };\n\t\n\t // Find the section containing the generated position we're trying to map\n\t // to an original position.\n\t var sectionIndex = binarySearch.search(needle, this._sections,\n\t function(needle, section) {\n\t var cmp = needle.generatedLine - section.generatedOffset.generatedLine;\n\t if (cmp) {\n\t return cmp;\n\t }\n\t\n\t return (needle.generatedColumn -\n\t section.generatedOffset.generatedColumn);\n\t });\n\t var section = this._sections[sectionIndex];\n\t\n\t if (!section) {\n\t return {\n\t source: null,\n\t line: null,\n\t column: null,\n\t name: null\n\t };\n\t }\n\t\n\t return section.consumer.originalPositionFor({\n\t line: needle.generatedLine -\n\t (section.generatedOffset.generatedLine - 1),\n\t column: needle.generatedColumn -\n\t (section.generatedOffset.generatedLine === needle.generatedLine\n\t ? section.generatedOffset.generatedColumn - 1\n\t : 0),\n\t bias: aArgs.bias\n\t });\n\t };\n\t\n\t/**\n\t * Return true if we have the source content for every source in the source\n\t * map, false otherwise.\n\t */\n\tIndexedSourceMapConsumer.prototype.hasContentsOfAllSources =\n\t function IndexedSourceMapConsumer_hasContentsOfAllSources() {\n\t return this._sections.every(function (s) {\n\t return s.consumer.hasContentsOfAllSources();\n\t });\n\t };\n\t\n\t/**\n\t * Returns the original source content. The only argument is the url of the\n\t * original source file. Returns null if no original source content is\n\t * available.\n\t */\n\tIndexedSourceMapConsumer.prototype.sourceContentFor =\n\t function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {\n\t for (var i = 0; i < this._sections.length; i++) {\n\t var section = this._sections[i];\n\t\n\t var content = section.consumer.sourceContentFor(aSource, true);\n\t if (content) {\n\t return content;\n\t }\n\t }\n\t if (nullOnMissing) {\n\t return null;\n\t }\n\t else {\n\t throw new Error('\"' + aSource + '\" is not in the SourceMap.');\n\t }\n\t };\n\t\n\t/**\n\t * Returns the generated line and column information for the original source,\n\t * line, and column positions provided. The only argument is an object with\n\t * the following properties:\n\t *\n\t * - source: The filename of the original source.\n\t * - line: The line number in the original source.\n\t * - column: The column number in the original source.\n\t *\n\t * and an object is returned with the following properties:\n\t *\n\t * - line: The line number in the generated source, or null.\n\t * - column: The column number in the generated source, or null.\n\t */\n\tIndexedSourceMapConsumer.prototype.generatedPositionFor =\n\t function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {\n\t for (var i = 0; i < this._sections.length; i++) {\n\t var section = this._sections[i];\n\t\n\t // Only consider this section if the requested source is in the list of\n\t // sources of the consumer.\n\t if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {\n\t continue;\n\t }\n\t var generatedPosition = section.consumer.generatedPositionFor(aArgs);\n\t if (generatedPosition) {\n\t var ret = {\n\t line: generatedPosition.line +\n\t (section.generatedOffset.generatedLine - 1),\n\t column: generatedPosition.column +\n\t (section.generatedOffset.generatedLine === generatedPosition.line\n\t ? section.generatedOffset.generatedColumn - 1\n\t : 0)\n\t };\n\t return ret;\n\t }\n\t }\n\t\n\t return {\n\t line: null,\n\t column: null\n\t };\n\t };\n\t\n\t/**\n\t * Parse the mappings in a string in to a data structure which we can easily\n\t * query (the ordered arrays in the `this.__generatedMappings` and\n\t * `this.__originalMappings` properties).\n\t */\n\tIndexedSourceMapConsumer.prototype._parseMappings =\n\t function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n\t this.__generatedMappings = [];\n\t this.__originalMappings = [];\n\t for (var i = 0; i < this._sections.length; i++) {\n\t var section = this._sections[i];\n\t var sectionMappings = section.consumer._generatedMappings;\n\t for (var j = 0; j < sectionMappings.length; j++) {\n\t var mapping = sectionMappings[j];\n\t\n\t var source = section.consumer._sources.at(mapping.source);\n\t if (section.consumer.sourceRoot !== null) {\n\t source = util.join(section.consumer.sourceRoot, source);\n\t }\n\t this._sources.add(source);\n\t source = this._sources.indexOf(source);\n\t\n\t var name = section.consumer._names.at(mapping.name);\n\t this._names.add(name);\n\t name = this._names.indexOf(name);\n\t\n\t // The mappings coming from the consumer for the section have\n\t // generated positions relative to the start of the section, so we\n\t // need to offset them to be relative to the start of the concatenated\n\t // generated file.\n\t var adjustedMapping = {\n\t source: source,\n\t generatedLine: mapping.generatedLine +\n\t (section.generatedOffset.generatedLine - 1),\n\t generatedColumn: mapping.generatedColumn +\n\t (section.generatedOffset.generatedLine === mapping.generatedLine\n\t ? section.generatedOffset.generatedColumn - 1\n\t : 0),\n\t originalLine: mapping.originalLine,\n\t originalColumn: mapping.originalColumn,\n\t name: name\n\t };\n\t\n\t this.__generatedMappings.push(adjustedMapping);\n\t if (typeof adjustedMapping.originalLine === 'number') {\n\t this.__originalMappings.push(adjustedMapping);\n\t }\n\t }\n\t }\n\t\n\t quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);\n\t quickSort(this.__originalMappings, util.compareByOriginalPositions);\n\t };\n\t\n\texports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;\n\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\texports.GREATEST_LOWER_BOUND = 1;\n\texports.LEAST_UPPER_BOUND = 2;\n\t\n\t/**\n\t * Recursive implementation of binary search.\n\t *\n\t * @param aLow Indices here and lower do not contain the needle.\n\t * @param aHigh Indices here and higher do not contain the needle.\n\t * @param aNeedle The element being searched for.\n\t * @param aHaystack The non-empty array being searched.\n\t * @param aCompare Function which takes two elements and returns -1, 0, or 1.\n\t * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or\n\t * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the\n\t * closest element that is smaller than or greater than the one we are\n\t * searching for, respectively, if the exact element cannot be found.\n\t */\n\tfunction recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {\n\t // This function terminates when one of the following is true:\n\t //\n\t // 1. We find the exact element we are looking for.\n\t //\n\t // 2. We did not find the exact element, but we can return the index of\n\t // the next-closest element.\n\t //\n\t // 3. We did not find the exact element, and there is no next-closest\n\t // element than the one we are searching for, so we return -1.\n\t var mid = Math.floor((aHigh - aLow) / 2) + aLow;\n\t var cmp = aCompare(aNeedle, aHaystack[mid], true);\n\t if (cmp === 0) {\n\t // Found the element we are looking for.\n\t return mid;\n\t }\n\t else if (cmp > 0) {\n\t // Our needle is greater than aHaystack[mid].\n\t if (aHigh - mid > 1) {\n\t // The element is in the upper half.\n\t return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);\n\t }\n\t\n\t // The exact needle element was not found in this haystack. Determine if\n\t // we are in termination case (3) or (2) and return the appropriate thing.\n\t if (aBias == exports.LEAST_UPPER_BOUND) {\n\t return aHigh < aHaystack.length ? aHigh : -1;\n\t } else {\n\t return mid;\n\t }\n\t }\n\t else {\n\t // Our needle is less than aHaystack[mid].\n\t if (mid - aLow > 1) {\n\t // The element is in the lower half.\n\t return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);\n\t }\n\t\n\t // we are in termination case (3) or (2) and return the appropriate thing.\n\t if (aBias == exports.LEAST_UPPER_BOUND) {\n\t return mid;\n\t } else {\n\t return aLow < 0 ? -1 : aLow;\n\t }\n\t }\n\t}\n\t\n\t/**\n\t * This is an implementation of binary search which will always try and return\n\t * the index of the closest element if there is no exact hit. This is because\n\t * mappings between original and generated line/col pairs are single points,\n\t * and there is an implicit region between each of them, so a miss just means\n\t * that you aren't on the very start of a region.\n\t *\n\t * @param aNeedle The element you are looking for.\n\t * @param aHaystack The array that is being searched.\n\t * @param aCompare A function which takes the needle and an element in the\n\t * array and returns -1, 0, or 1 depending on whether the needle is less\n\t * than, equal to, or greater than the element, respectively.\n\t * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or\n\t * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the\n\t * closest element that is smaller than or greater than the one we are\n\t * searching for, respectively, if the exact element cannot be found.\n\t * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.\n\t */\n\texports.search = function search(aNeedle, aHaystack, aCompare, aBias) {\n\t if (aHaystack.length === 0) {\n\t return -1;\n\t }\n\t\n\t var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,\n\t aCompare, aBias || exports.GREATEST_LOWER_BOUND);\n\t if (index < 0) {\n\t return -1;\n\t }\n\t\n\t // We have found either the exact element, or the next-closest element than\n\t // the one we are searching for. However, there may be more than one such\n\t // element. Make sure we always return the smallest of these.\n\t while (index - 1 >= 0) {\n\t if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {\n\t break;\n\t }\n\t --index;\n\t }\n\t\n\t return index;\n\t};\n\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\t// It turns out that some (most?) JavaScript engines don't self-host\n\t// `Array.prototype.sort`. This makes sense because C++ will likely remain\n\t// faster than JS when doing raw CPU-intensive sorting. However, when using a\n\t// custom comparator function, calling back and forth between the VM's C++ and\n\t// JIT'd JS is rather slow *and* loses JIT type information, resulting in\n\t// worse generated code for the comparator function than would be optimal. In\n\t// fact, when sorting with a comparator, these costs outweigh the benefits of\n\t// sorting in C++. By using our own JS-implemented Quick Sort (below), we get\n\t// a ~3500ms mean speed-up in `bench/bench.html`.\n\t\n\t/**\n\t * Swap the elements indexed by `x` and `y` in the array `ary`.\n\t *\n\t * @param {Array} ary\n\t * The array.\n\t * @param {Number} x\n\t * The index of the first item.\n\t * @param {Number} y\n\t * The index of the second item.\n\t */\n\tfunction swap(ary, x, y) {\n\t var temp = ary[x];\n\t ary[x] = ary[y];\n\t ary[y] = temp;\n\t}\n\t\n\t/**\n\t * Returns a random integer within the range `low .. high` inclusive.\n\t *\n\t * @param {Number} low\n\t * The lower bound on the range.\n\t * @param {Number} high\n\t * The upper bound on the range.\n\t */\n\tfunction randomIntInRange(low, high) {\n\t return Math.round(low + (Math.random() * (high - low)));\n\t}\n\t\n\t/**\n\t * The Quick Sort algorithm.\n\t *\n\t * @param {Array} ary\n\t * An array to sort.\n\t * @param {function} comparator\n\t * Function to use to compare two items.\n\t * @param {Number} p\n\t * Start index of the array\n\t * @param {Number} r\n\t * End index of the array\n\t */\n\tfunction doQuickSort(ary, comparator, p, r) {\n\t // If our lower bound is less than our upper bound, we (1) partition the\n\t // array into two pieces and (2) recurse on each half. If it is not, this is\n\t // the empty array and our base case.\n\t\n\t if (p < r) {\n\t // (1) Partitioning.\n\t //\n\t // The partitioning chooses a pivot between `p` and `r` and moves all\n\t // elements that are less than or equal to the pivot to the before it, and\n\t // all the elements that are greater than it after it. The effect is that\n\t // once partition is done, the pivot is in the exact place it will be when\n\t // the array is put in sorted order, and it will not need to be moved\n\t // again. This runs in O(n) time.\n\t\n\t // Always choose a random pivot so that an input array which is reverse\n\t // sorted does not cause O(n^2) running time.\n\t var pivotIndex = randomIntInRange(p, r);\n\t var i = p - 1;\n\t\n\t swap(ary, pivotIndex, r);\n\t var pivot = ary[r];\n\t\n\t // Immediately after `j` is incremented in this loop, the following hold\n\t // true:\n\t //\n\t // * Every element in `ary[p .. i]` is less than or equal to the pivot.\n\t //\n\t // * Every element in `ary[i+1 .. j-1]` is greater than the pivot.\n\t for (var j = p; j < r; j++) {\n\t if (comparator(ary[j], pivot) <= 0) {\n\t i += 1;\n\t swap(ary, i, j);\n\t }\n\t }\n\t\n\t swap(ary, i + 1, j);\n\t var q = i + 1;\n\t\n\t // (2) Recurse on each half.\n\t\n\t doQuickSort(ary, comparator, p, q - 1);\n\t doQuickSort(ary, comparator, q + 1, r);\n\t }\n\t}\n\t\n\t/**\n\t * Sort the given array in-place with the given comparator function.\n\t *\n\t * @param {Array} ary\n\t * An array to sort.\n\t * @param {function} comparator\n\t * Function to use to compare two items.\n\t */\n\texports.quickSort = function (ary, comparator) {\n\t doQuickSort(ary, comparator, 0, ary.length - 1);\n\t};\n\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t/* -*- Mode: js; js-indent-level: 2; -*- */\n\t/*\n\t * Copyright 2011 Mozilla Foundation and contributors\n\t * Licensed under the New BSD license. See LICENSE or:\n\t * http://opensource.org/licenses/BSD-3-Clause\n\t */\n\t\n\tvar SourceMapGenerator = __webpack_require__(1).SourceMapGenerator;\n\tvar util = __webpack_require__(4);\n\t\n\t// Matches a Windows-style `\\r\\n` newline or a `\\n` newline used by all other\n\t// operating systems these days (capturing the result).\n\tvar REGEX_NEWLINE = /(\\r?\\n)/;\n\t\n\t// Newline character code for charCodeAt() comparisons\n\tvar NEWLINE_CODE = 10;\n\t\n\t// Private symbol for identifying `SourceNode`s when multiple versions of\n\t// the source-map library are loaded. This MUST NOT CHANGE across\n\t// versions!\n\tvar isSourceNode = \"$$$isSourceNode$$$\";\n\t\n\t/**\n\t * SourceNodes provide a way to abstract over interpolating/concatenating\n\t * snippets of generated JavaScript source code while maintaining the line and\n\t * column information associated with the original source code.\n\t *\n\t * @param aLine The original line number.\n\t * @param aColumn The original column number.\n\t * @param aSource The original source's filename.\n\t * @param aChunks Optional. An array of strings which are snippets of\n\t * generated JS, or other SourceNodes.\n\t * @param aName The original identifier.\n\t */\n\tfunction SourceNode(aLine, aColumn, aSource, aChunks, aName) {\n\t this.children = [];\n\t this.sourceContents = {};\n\t this.line = aLine == null ? null : aLine;\n\t this.column = aColumn == null ? null : aColumn;\n\t this.source = aSource == null ? null : aSource;\n\t this.name = aName == null ? null : aName;\n\t this[isSourceNode] = true;\n\t if (aChunks != null) this.add(aChunks);\n\t}\n\t\n\t/**\n\t * Creates a SourceNode from generated code and a SourceMapConsumer.\n\t *\n\t * @param aGeneratedCode The generated code\n\t * @param aSourceMapConsumer The SourceMap for the generated code\n\t * @param aRelativePath Optional. The path that relative sources in the\n\t * SourceMapConsumer should be relative to.\n\t */\n\tSourceNode.fromStringWithSourceMap =\n\t function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {\n\t // The SourceNode we want to fill with the generated code\n\t // and the SourceMap\n\t var node = new SourceNode();\n\t\n\t // All even indices of this array are one line of the generated code,\n\t // while all odd indices are the newlines between two adjacent lines\n\t // (since `REGEX_NEWLINE` captures its match).\n\t // Processed fragments are accessed by calling `shiftNextLine`.\n\t var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);\n\t var remainingLinesIndex = 0;\n\t var shiftNextLine = function() {\n\t var lineContents = getNextLine();\n\t // The last line of a file might not have a newline.\n\t var newLine = getNextLine() || \"\";\n\t return lineContents + newLine;\n\t\n\t function getNextLine() {\n\t return remainingLinesIndex < remainingLines.length ?\n\t remainingLines[remainingLinesIndex++] : undefined;\n\t }\n\t };\n\t\n\t // We need to remember the position of \"remainingLines\"\n\t var lastGeneratedLine = 1, lastGeneratedColumn = 0;\n\t\n\t // The generate SourceNodes we need a code range.\n\t // To extract it current and last mapping is used.\n\t // Here we store the last mapping.\n\t var lastMapping = null;\n\t\n\t aSourceMapConsumer.eachMapping(function (mapping) {\n\t if (lastMapping !== null) {\n\t // We add the code from \"lastMapping\" to \"mapping\":\n\t // First check if there is a new line in between.\n\t if (lastGeneratedLine < mapping.generatedLine) {\n\t // Associate first line with \"lastMapping\"\n\t addMappingWithCode(lastMapping, shiftNextLine());\n\t lastGeneratedLine++;\n\t lastGeneratedColumn = 0;\n\t // The remaining code is added without mapping\n\t } else {\n\t // There is no new line in between.\n\t // Associate the code between \"lastGeneratedColumn\" and\n\t // \"mapping.generatedColumn\" with \"lastMapping\"\n\t var nextLine = remainingLines[remainingLinesIndex];\n\t var code = nextLine.substr(0, mapping.generatedColumn -\n\t lastGeneratedColumn);\n\t remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn -\n\t lastGeneratedColumn);\n\t lastGeneratedColumn = mapping.generatedColumn;\n\t addMappingWithCode(lastMapping, code);\n\t // No more remaining code, continue\n\t lastMapping = mapping;\n\t return;\n\t }\n\t }\n\t // We add the generated code until the first mapping\n\t // to the SourceNode without any mapping.\n\t // Each line is added as separate string.\n\t while (lastGeneratedLine < mapping.generatedLine) {\n\t node.add(shiftNextLine());\n\t lastGeneratedLine++;\n\t }\n\t if (lastGeneratedColumn < mapping.generatedColumn) {\n\t var nextLine = remainingLines[remainingLinesIndex];\n\t node.add(nextLine.substr(0, mapping.generatedColumn));\n\t remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);\n\t lastGeneratedColumn = mapping.generatedColumn;\n\t }\n\t lastMapping = mapping;\n\t }, this);\n\t // We have processed all mappings.\n\t if (remainingLinesIndex < remainingLines.length) {\n\t if (lastMapping) {\n\t // Associate the remaining code in the current line with \"lastMapping\"\n\t addMappingWithCode(lastMapping, shiftNextLine());\n\t }\n\t // and add the remaining lines without any mapping\n\t node.add(remainingLines.splice(remainingLinesIndex).join(\"\"));\n\t }\n\t\n\t // Copy sourcesContent into SourceNode\n\t aSourceMapConsumer.sources.forEach(function (sourceFile) {\n\t var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n\t if (content != null) {\n\t if (aRelativePath != null) {\n\t sourceFile = util.join(aRelativePath, sourceFile);\n\t }\n\t node.setSourceContent(sourceFile, content);\n\t }\n\t });\n\t\n\t return node;\n\t\n\t function addMappingWithCode(mapping, code) {\n\t if (mapping === null || mapping.source === undefined) {\n\t node.add(code);\n\t } else {\n\t var source = aRelativePath\n\t ? util.join(aRelativePath, mapping.source)\n\t : mapping.source;\n\t node.add(new SourceNode(mapping.originalLine,\n\t mapping.originalColumn,\n\t source,\n\t code,\n\t mapping.name));\n\t }\n\t }\n\t };\n\t\n\t/**\n\t * Add a chunk of generated JS to this source node.\n\t *\n\t * @param aChunk A string snippet of generated JS code, another instance of\n\t * SourceNode, or an array where each member is one of those things.\n\t */\n\tSourceNode.prototype.add = function SourceNode_add(aChunk) {\n\t if (Array.isArray(aChunk)) {\n\t aChunk.forEach(function (chunk) {\n\t this.add(chunk);\n\t }, this);\n\t }\n\t else if (aChunk[isSourceNode] || typeof aChunk === \"string\") {\n\t if (aChunk) {\n\t this.children.push(aChunk);\n\t }\n\t }\n\t else {\n\t throw new TypeError(\n\t \"Expected a SourceNode, string, or an array of SourceNodes and strings. Got \" + aChunk\n\t );\n\t }\n\t return this;\n\t};\n\t\n\t/**\n\t * Add a chunk of generated JS to the beginning of this source node.\n\t *\n\t * @param aChunk A string snippet of generated JS code, another instance of\n\t * SourceNode, or an array where each member is one of those things.\n\t */\n\tSourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {\n\t if (Array.isArray(aChunk)) {\n\t for (var i = aChunk.length-1; i >= 0; i--) {\n\t this.prepend(aChunk[i]);\n\t }\n\t }\n\t else if (aChunk[isSourceNode] || typeof aChunk === \"string\") {\n\t this.children.unshift(aChunk);\n\t }\n\t else {\n\t throw new TypeError(\n\t \"Expected a SourceNode, string, or an array of SourceNodes and strings. Got \" + aChunk\n\t );\n\t }\n\t return this;\n\t};\n\t\n\t/**\n\t * Walk over the tree of JS snippets in this node and its children. The\n\t * walking function is called once for each snippet of JS and is passed that\n\t * snippet and the its original associated source's line/column location.\n\t *\n\t * @param aFn The traversal function.\n\t */\n\tSourceNode.prototype.walk = function SourceNode_walk(aFn) {\n\t var chunk;\n\t for (var i = 0, len = this.children.length; i < len; i++) {\n\t chunk = this.children[i];\n\t if (chunk[isSourceNode]) {\n\t chunk.walk(aFn);\n\t }\n\t else {\n\t if (chunk !== '') {\n\t aFn(chunk, { source: this.source,\n\t line: this.line,\n\t column: this.column,\n\t name: this.name });\n\t }\n\t }\n\t }\n\t};\n\t\n\t/**\n\t * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between\n\t * each of `this.children`.\n\t *\n\t * @param aSep The separator.\n\t */\n\tSourceNode.prototype.join = function SourceNode_join(aSep) {\n\t var newChildren;\n\t var i;\n\t var len = this.children.length;\n\t if (len > 0) {\n\t newChildren = [];\n\t for (i = 0; i < len-1; i++) {\n\t newChildren.push(this.children[i]);\n\t newChildren.push(aSep);\n\t }\n\t newChildren.push(this.children[i]);\n\t this.children = newChildren;\n\t }\n\t return this;\n\t};\n\t\n\t/**\n\t * Call String.prototype.replace on the very right-most source snippet. Useful\n\t * for trimming whitespace from the end of a source node, etc.\n\t *\n\t * @param aPattern The pattern to replace.\n\t * @param aReplacement The thing to replace the pattern with.\n\t */\n\tSourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {\n\t var lastChild = this.children[this.children.length - 1];\n\t if (lastChild[isSourceNode]) {\n\t lastChild.replaceRight(aPattern, aReplacement);\n\t }\n\t else if (typeof lastChild === 'string') {\n\t this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);\n\t }\n\t else {\n\t this.children.push(''.replace(aPattern, aReplacement));\n\t }\n\t return this;\n\t};\n\t\n\t/**\n\t * Set the source content for a source file. This will be added to the SourceMapGenerator\n\t * in the sourcesContent field.\n\t *\n\t * @param aSourceFile The filename of the source file\n\t * @param aSourceContent The content of the source file\n\t */\n\tSourceNode.prototype.setSourceContent =\n\t function SourceNode_setSourceContent(aSourceFile, aSourceContent) {\n\t this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;\n\t };\n\t\n\t/**\n\t * Walk over the tree of SourceNodes. The walking function is called for each\n\t * source file content and is passed the filename and source content.\n\t *\n\t * @param aFn The traversal function.\n\t */\n\tSourceNode.prototype.walkSourceContents =\n\t function SourceNode_walkSourceContents(aFn) {\n\t for (var i = 0, len = this.children.length; i < len; i++) {\n\t if (this.children[i][isSourceNode]) {\n\t this.children[i].walkSourceContents(aFn);\n\t }\n\t }\n\t\n\t var sources = Object.keys(this.sourceContents);\n\t for (var i = 0, len = sources.length; i < len; i++) {\n\t aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);\n\t }\n\t };\n\t\n\t/**\n\t * Return the string representation of this source node. Walks over the tree\n\t * and concatenates all the various snippets together to one string.\n\t */\n\tSourceNode.prototype.toString = function SourceNode_toString() {\n\t var str = \"\";\n\t this.walk(function (chunk) {\n\t str += chunk;\n\t });\n\t return str;\n\t};\n\t\n\t/**\n\t * Returns the string representation of this source node along with a source\n\t * map.\n\t */\n\tSourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {\n\t var generated = {\n\t code: \"\",\n\t line: 1,\n\t column: 0\n\t };\n\t var map = new SourceMapGenerator(aArgs);\n\t var sourceMappingActive = false;\n\t var lastOriginalSource = null;\n\t var lastOriginalLine = null;\n\t var lastOriginalColumn = null;\n\t var lastOriginalName = null;\n\t this.walk(function (chunk, original) {\n\t generated.code += chunk;\n\t if (original.source !== null\n\t && original.line !== null\n\t && original.column !== null) {\n\t if(lastOriginalSource !== original.source\n\t || lastOriginalLine !== original.line\n\t || lastOriginalColumn !== original.column\n\t || lastOriginalName !== original.name) {\n\t map.addMapping({\n\t source: original.source,\n\t original: {\n\t line: original.line,\n\t column: original.column\n\t },\n\t generated: {\n\t line: generated.line,\n\t column: generated.column\n\t },\n\t name: original.name\n\t });\n\t }\n\t lastOriginalSource = original.source;\n\t lastOriginalLine = original.line;\n\t lastOriginalColumn = original.column;\n\t lastOriginalName = original.name;\n\t sourceMappingActive = true;\n\t } else if (sourceMappingActive) {\n\t map.addMapping({\n\t generated: {\n\t line: generated.line,\n\t column: generated.column\n\t }\n\t });\n\t lastOriginalSource = null;\n\t sourceMappingActive = false;\n\t }\n\t for (var idx = 0, length = chunk.length; idx < length; idx++) {\n\t if (chunk.charCodeAt(idx) === NEWLINE_CODE) {\n\t generated.line++;\n\t generated.column = 0;\n\t // Mappings end at eol\n\t if (idx + 1 === length) {\n\t lastOriginalSource = null;\n\t sourceMappingActive = false;\n\t } else if (sourceMappingActive) {\n\t map.addMapping({\n\t source: original.source,\n\t original: {\n\t line: original.line,\n\t column: original.column\n\t },\n\t generated: {\n\t line: generated.line,\n\t column: generated.column\n\t },\n\t name: original.name\n\t });\n\t }\n\t } else {\n\t generated.column++;\n\t }\n\t }\n\t });\n\t this.walkSourceContents(function (sourceFile, sourceContent) {\n\t map.setSourceContent(sourceFile, sourceContent);\n\t });\n\t\n\t return { code: generated.code, map: map };\n\t};\n\t\n\texports.SourceNode = SourceNode;\n\n\n/***/ })\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// source-map.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 42c329f865e32e011afb","/*\n * Copyright 2009-2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE.txt or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\nexports.SourceMapGenerator = require('./lib/source-map-generator').SourceMapGenerator;\nexports.SourceMapConsumer = require('./lib/source-map-consumer').SourceMapConsumer;\nexports.SourceNode = require('./lib/source-node').SourceNode;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./source-map.js\n// module id = 0\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nvar base64VLQ = require('./base64-vlq');\nvar util = require('./util');\nvar ArraySet = require('./array-set').ArraySet;\nvar MappingList = require('./mapping-list').MappingList;\n\n/**\n * An instance of the SourceMapGenerator represents a source map which is\n * being built incrementally. You may pass an object with the following\n * properties:\n *\n * - file: The filename of the generated source.\n * - sourceRoot: A root for all relative URLs in this source map.\n */\nfunction SourceMapGenerator(aArgs) {\n if (!aArgs) {\n aArgs = {};\n }\n this._file = util.getArg(aArgs, 'file', null);\n this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);\n this._skipValidation = util.getArg(aArgs, 'skipValidation', false);\n this._sources = new ArraySet();\n this._names = new ArraySet();\n this._mappings = new MappingList();\n this._sourcesContents = null;\n}\n\nSourceMapGenerator.prototype._version = 3;\n\n/**\n * Creates a new SourceMapGenerator based on a SourceMapConsumer\n *\n * @param aSourceMapConsumer The SourceMap.\n */\nSourceMapGenerator.fromSourceMap =\n function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {\n var sourceRoot = aSourceMapConsumer.sourceRoot;\n var generator = new SourceMapGenerator({\n file: aSourceMapConsumer.file,\n sourceRoot: sourceRoot\n });\n aSourceMapConsumer.eachMapping(function (mapping) {\n var newMapping = {\n generated: {\n line: mapping.generatedLine,\n column: mapping.generatedColumn\n }\n };\n\n if (mapping.source != null) {\n newMapping.source = mapping.source;\n if (sourceRoot != null) {\n newMapping.source = util.relative(sourceRoot, newMapping.source);\n }\n\n newMapping.original = {\n line: mapping.originalLine,\n column: mapping.originalColumn\n };\n\n if (mapping.name != null) {\n newMapping.name = mapping.name;\n }\n }\n\n generator.addMapping(newMapping);\n });\n aSourceMapConsumer.sources.forEach(function (sourceFile) {\n var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n if (content != null) {\n generator.setSourceContent(sourceFile, content);\n }\n });\n return generator;\n };\n\n/**\n * Add a single mapping from original source line and column to the generated\n * source's line and column for this source map being created. The mapping\n * object should have the following properties:\n *\n * - generated: An object with the generated line and column positions.\n * - original: An object with the original line and column positions.\n * - source: The original source file (relative to the sourceRoot).\n * - name: An optional original token name for this mapping.\n */\nSourceMapGenerator.prototype.addMapping =\n function SourceMapGenerator_addMapping(aArgs) {\n var generated = util.getArg(aArgs, 'generated');\n var original = util.getArg(aArgs, 'original', null);\n var source = util.getArg(aArgs, 'source', null);\n var name = util.getArg(aArgs, 'name', null);\n\n if (!this._skipValidation) {\n this._validateMapping(generated, original, source, name);\n }\n\n if (source != null) {\n source = String(source);\n if (!this._sources.has(source)) {\n this._sources.add(source);\n }\n }\n\n if (name != null) {\n name = String(name);\n if (!this._names.has(name)) {\n this._names.add(name);\n }\n }\n\n this._mappings.add({\n generatedLine: generated.line,\n generatedColumn: generated.column,\n originalLine: original != null && original.line,\n originalColumn: original != null && original.column,\n source: source,\n name: name\n });\n };\n\n/**\n * Set the source content for a source file.\n */\nSourceMapGenerator.prototype.setSourceContent =\n function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {\n var source = aSourceFile;\n if (this._sourceRoot != null) {\n source = util.relative(this._sourceRoot, source);\n }\n\n if (aSourceContent != null) {\n // Add the source content to the _sourcesContents map.\n // Create a new _sourcesContents map if the property is null.\n if (!this._sourcesContents) {\n this._sourcesContents = Object.create(null);\n }\n this._sourcesContents[util.toSetString(source)] = aSourceContent;\n } else if (this._sourcesContents) {\n // Remove the source file from the _sourcesContents map.\n // If the _sourcesContents map is empty, set the property to null.\n delete this._sourcesContents[util.toSetString(source)];\n if (Object.keys(this._sourcesContents).length === 0) {\n this._sourcesContents = null;\n }\n }\n };\n\n/**\n * Applies the mappings of a sub-source-map for a specific source file to the\n * source map being generated. Each mapping to the supplied source file is\n * rewritten using the supplied source map. Note: The resolution for the\n * resulting mappings is the minimium of this map and the supplied map.\n *\n * @param aSourceMapConsumer The source map to be applied.\n * @param aSourceFile Optional. The filename of the source file.\n * If omitted, SourceMapConsumer's file property will be used.\n * @param aSourceMapPath Optional. The dirname of the path to the source map\n * to be applied. If relative, it is relative to the SourceMapConsumer.\n * This parameter is needed when the two source maps aren't in the same\n * directory, and the source map to be applied contains relative source\n * paths. If so, those relative source paths need to be rewritten\n * relative to the SourceMapGenerator.\n */\nSourceMapGenerator.prototype.applySourceMap =\n function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {\n var sourceFile = aSourceFile;\n // If aSourceFile is omitted, we will use the file property of the SourceMap\n if (aSourceFile == null) {\n if (aSourceMapConsumer.file == null) {\n throw new Error(\n 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +\n 'or the source map\\'s \"file\" property. Both were omitted.'\n );\n }\n sourceFile = aSourceMapConsumer.file;\n }\n var sourceRoot = this._sourceRoot;\n // Make \"sourceFile\" relative if an absolute Url is passed.\n if (sourceRoot != null) {\n sourceFile = util.relative(sourceRoot, sourceFile);\n }\n // Applying the SourceMap can add and remove items from the sources and\n // the names array.\n var newSources = new ArraySet();\n var newNames = new ArraySet();\n\n // Find mappings for the \"sourceFile\"\n this._mappings.unsortedForEach(function (mapping) {\n if (mapping.source === sourceFile && mapping.originalLine != null) {\n // Check if it can be mapped by the source map, then update the mapping.\n var original = aSourceMapConsumer.originalPositionFor({\n line: mapping.originalLine,\n column: mapping.originalColumn\n });\n if (original.source != null) {\n // Copy mapping\n mapping.source = original.source;\n if (aSourceMapPath != null) {\n mapping.source = util.join(aSourceMapPath, mapping.source)\n }\n if (sourceRoot != null) {\n mapping.source = util.relative(sourceRoot, mapping.source);\n }\n mapping.originalLine = original.line;\n mapping.originalColumn = original.column;\n if (original.name != null) {\n mapping.name = original.name;\n }\n }\n }\n\n var source = mapping.source;\n if (source != null && !newSources.has(source)) {\n newSources.add(source);\n }\n\n var name = mapping.name;\n if (name != null && !newNames.has(name)) {\n newNames.add(name);\n }\n\n }, this);\n this._sources = newSources;\n this._names = newNames;\n\n // Copy sourcesContents of applied map.\n aSourceMapConsumer.sources.forEach(function (sourceFile) {\n var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n if (content != null) {\n if (aSourceMapPath != null) {\n sourceFile = util.join(aSourceMapPath, sourceFile);\n }\n if (sourceRoot != null) {\n sourceFile = util.relative(sourceRoot, sourceFile);\n }\n this.setSourceContent(sourceFile, content);\n }\n }, this);\n };\n\n/**\n * A mapping can have one of the three levels of data:\n *\n * 1. Just the generated position.\n * 2. The Generated position, original position, and original source.\n * 3. Generated and original position, original source, as well as a name\n * token.\n *\n * To maintain consistency, we validate that any new mapping being added falls\n * in to one of these categories.\n */\nSourceMapGenerator.prototype._validateMapping =\n function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,\n aName) {\n // When aOriginal is truthy but has empty values for .line and .column,\n // it is most likely a programmer error. In this case we throw a very\n // specific error message to try to guide them the right way.\n // For example: https://github.com/Polymer/polymer-bundler/pull/519\n if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {\n throw new Error(\n 'original.line and original.column are not numbers -- you probably meant to omit ' +\n 'the original mapping entirely and only map the generated position. If so, pass ' +\n 'null for the original mapping instead of an object with empty or null values.'\n );\n }\n\n if (aGenerated && 'line' in aGenerated && 'column' in aGenerated\n && aGenerated.line > 0 && aGenerated.column >= 0\n && !aOriginal && !aSource && !aName) {\n // Case 1.\n return;\n }\n else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated\n && aOriginal && 'line' in aOriginal && 'column' in aOriginal\n && aGenerated.line > 0 && aGenerated.column >= 0\n && aOriginal.line > 0 && aOriginal.column >= 0\n && aSource) {\n // Cases 2 and 3.\n return;\n }\n else {\n throw new Error('Invalid mapping: ' + JSON.stringify({\n generated: aGenerated,\n source: aSource,\n original: aOriginal,\n name: aName\n }));\n }\n };\n\n/**\n * Serialize the accumulated mappings in to the stream of base 64 VLQs\n * specified by the source map format.\n */\nSourceMapGenerator.prototype._serializeMappings =\n function SourceMapGenerator_serializeMappings() {\n var previousGeneratedColumn = 0;\n var previousGeneratedLine = 1;\n var previousOriginalColumn = 0;\n var previousOriginalLine = 0;\n var previousName = 0;\n var previousSource = 0;\n var result = '';\n var next;\n var mapping;\n var nameIdx;\n var sourceIdx;\n\n var mappings = this._mappings.toArray();\n for (var i = 0, len = mappings.length; i < len; i++) {\n mapping = mappings[i];\n next = ''\n\n if (mapping.generatedLine !== previousGeneratedLine) {\n previousGeneratedColumn = 0;\n while (mapping.generatedLine !== previousGeneratedLine) {\n next += ';';\n previousGeneratedLine++;\n }\n }\n else {\n if (i > 0) {\n if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {\n continue;\n }\n next += ',';\n }\n }\n\n next += base64VLQ.encode(mapping.generatedColumn\n - previousGeneratedColumn);\n previousGeneratedColumn = mapping.generatedColumn;\n\n if (mapping.source != null) {\n sourceIdx = this._sources.indexOf(mapping.source);\n next += base64VLQ.encode(sourceIdx - previousSource);\n previousSource = sourceIdx;\n\n // lines are stored 0-based in SourceMap spec version 3\n next += base64VLQ.encode(mapping.originalLine - 1\n - previousOriginalLine);\n previousOriginalLine = mapping.originalLine - 1;\n\n next += base64VLQ.encode(mapping.originalColumn\n - previousOriginalColumn);\n previousOriginalColumn = mapping.originalColumn;\n\n if (mapping.name != null) {\n nameIdx = this._names.indexOf(mapping.name);\n next += base64VLQ.encode(nameIdx - previousName);\n previousName = nameIdx;\n }\n }\n\n result += next;\n }\n\n return result;\n };\n\nSourceMapGenerator.prototype._generateSourcesContent =\n function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {\n return aSources.map(function (source) {\n if (!this._sourcesContents) {\n return null;\n }\n if (aSourceRoot != null) {\n source = util.relative(aSourceRoot, source);\n }\n var key = util.toSetString(source);\n return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)\n ? this._sourcesContents[key]\n : null;\n }, this);\n };\n\n/**\n * Externalize the source map.\n */\nSourceMapGenerator.prototype.toJSON =\n function SourceMapGenerator_toJSON() {\n var map = {\n version: this._version,\n sources: this._sources.toArray(),\n names: this._names.toArray(),\n mappings: this._serializeMappings()\n };\n if (this._file != null) {\n map.file = this._file;\n }\n if (this._sourceRoot != null) {\n map.sourceRoot = this._sourceRoot;\n }\n if (this._sourcesContents) {\n map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);\n }\n\n return map;\n };\n\n/**\n * Render the source map being generated to a string.\n */\nSourceMapGenerator.prototype.toString =\n function SourceMapGenerator_toString() {\n return JSON.stringify(this.toJSON());\n };\n\nexports.SourceMapGenerator = SourceMapGenerator;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/source-map-generator.js\n// module id = 1\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n *\n * Based on the Base 64 VLQ implementation in Closure Compiler:\n * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java\n *\n * Copyright 2011 The Closure Compiler Authors. All rights reserved.\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following\n * disclaimer in the documentation and/or other materials provided\n * with the distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nvar base64 = require('./base64');\n\n// A single base 64 digit can contain 6 bits of data. For the base 64 variable\n// length quantities we use in the source map spec, the first bit is the sign,\n// the next four bits are the actual value, and the 6th bit is the\n// continuation bit. The continuation bit tells us whether there are more\n// digits in this value following this digit.\n//\n// Continuation\n// | Sign\n// | |\n// V V\n// 101011\n\nvar VLQ_BASE_SHIFT = 5;\n\n// binary: 100000\nvar VLQ_BASE = 1 << VLQ_BASE_SHIFT;\n\n// binary: 011111\nvar VLQ_BASE_MASK = VLQ_BASE - 1;\n\n// binary: 100000\nvar VLQ_CONTINUATION_BIT = VLQ_BASE;\n\n/**\n * Converts from a two-complement value to a value where the sign bit is\n * placed in the least significant bit. For example, as decimals:\n * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)\n * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)\n */\nfunction toVLQSigned(aValue) {\n return aValue < 0\n ? ((-aValue) << 1) + 1\n : (aValue << 1) + 0;\n}\n\n/**\n * Converts to a two-complement value from a value where the sign bit is\n * placed in the least significant bit. For example, as decimals:\n * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1\n * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2\n */\nfunction fromVLQSigned(aValue) {\n var isNegative = (aValue & 1) === 1;\n var shifted = aValue >> 1;\n return isNegative\n ? -shifted\n : shifted;\n}\n\n/**\n * Returns the base 64 VLQ encoded value.\n */\nexports.encode = function base64VLQ_encode(aValue) {\n var encoded = \"\";\n var digit;\n\n var vlq = toVLQSigned(aValue);\n\n do {\n digit = vlq & VLQ_BASE_MASK;\n vlq >>>= VLQ_BASE_SHIFT;\n if (vlq > 0) {\n // There are still more digits in this value, so we must make sure the\n // continuation bit is marked.\n digit |= VLQ_CONTINUATION_BIT;\n }\n encoded += base64.encode(digit);\n } while (vlq > 0);\n\n return encoded;\n};\n\n/**\n * Decodes the next base 64 VLQ value from the given string and returns the\n * value and the rest of the string via the out parameter.\n */\nexports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {\n var strLen = aStr.length;\n var result = 0;\n var shift = 0;\n var continuation, digit;\n\n do {\n if (aIndex >= strLen) {\n throw new Error(\"Expected more digits in base 64 VLQ value.\");\n }\n\n digit = base64.decode(aStr.charCodeAt(aIndex++));\n if (digit === -1) {\n throw new Error(\"Invalid base64 digit: \" + aStr.charAt(aIndex - 1));\n }\n\n continuation = !!(digit & VLQ_CONTINUATION_BIT);\n digit &= VLQ_BASE_MASK;\n result = result + (digit << shift);\n shift += VLQ_BASE_SHIFT;\n } while (continuation);\n\n aOutParam.value = fromVLQSigned(result);\n aOutParam.rest = aIndex;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/base64-vlq.js\n// module id = 2\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nvar intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');\n\n/**\n * Encode an integer in the range of 0 to 63 to a single base 64 digit.\n */\nexports.encode = function (number) {\n if (0 <= number && number < intToCharMap.length) {\n return intToCharMap[number];\n }\n throw new TypeError(\"Must be between 0 and 63: \" + number);\n};\n\n/**\n * Decode a single base 64 character code digit to an integer. Returns -1 on\n * failure.\n */\nexports.decode = function (charCode) {\n var bigA = 65; // 'A'\n var bigZ = 90; // 'Z'\n\n var littleA = 97; // 'a'\n var littleZ = 122; // 'z'\n\n var zero = 48; // '0'\n var nine = 57; // '9'\n\n var plus = 43; // '+'\n var slash = 47; // '/'\n\n var littleOffset = 26;\n var numberOffset = 52;\n\n // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ\n if (bigA <= charCode && charCode <= bigZ) {\n return (charCode - bigA);\n }\n\n // 26 - 51: abcdefghijklmnopqrstuvwxyz\n if (littleA <= charCode && charCode <= littleZ) {\n return (charCode - littleA + littleOffset);\n }\n\n // 52 - 61: 0123456789\n if (zero <= charCode && charCode <= nine) {\n return (charCode - zero + numberOffset);\n }\n\n // 62: +\n if (charCode == plus) {\n return 62;\n }\n\n // 63: /\n if (charCode == slash) {\n return 63;\n }\n\n // Invalid base64 digit.\n return -1;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/base64.js\n// module id = 3\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\n/**\n * This is a helper function for getting values from parameter/options\n * objects.\n *\n * @param args The object we are extracting values from\n * @param name The name of the property we are getting.\n * @param defaultValue An optional value to return if the property is missing\n * from the object. If this is not specified and the property is missing, an\n * error will be thrown.\n */\nfunction getArg(aArgs, aName, aDefaultValue) {\n if (aName in aArgs) {\n return aArgs[aName];\n } else if (arguments.length === 3) {\n return aDefaultValue;\n } else {\n throw new Error('\"' + aName + '\" is a required argument.');\n }\n}\nexports.getArg = getArg;\n\nvar urlRegexp = /^(?:([\\w+\\-.]+):)?\\/\\/(?:(\\w+:\\w+)@)?([\\w.]*)(?::(\\d+))?(\\S*)$/;\nvar dataUrlRegexp = /^data:.+\\,.+$/;\n\nfunction urlParse(aUrl) {\n var match = aUrl.match(urlRegexp);\n if (!match) {\n return null;\n }\n return {\n scheme: match[1],\n auth: match[2],\n host: match[3],\n port: match[4],\n path: match[5]\n };\n}\nexports.urlParse = urlParse;\n\nfunction urlGenerate(aParsedUrl) {\n var url = '';\n if (aParsedUrl.scheme) {\n url += aParsedUrl.scheme + ':';\n }\n url += '//';\n if (aParsedUrl.auth) {\n url += aParsedUrl.auth + '@';\n }\n if (aParsedUrl.host) {\n url += aParsedUrl.host;\n }\n if (aParsedUrl.port) {\n url += \":\" + aParsedUrl.port\n }\n if (aParsedUrl.path) {\n url += aParsedUrl.path;\n }\n return url;\n}\nexports.urlGenerate = urlGenerate;\n\n/**\n * Normalizes a path, or the path portion of a URL:\n *\n * - Replaces consecutive slashes with one slash.\n * - Removes unnecessary '.' parts.\n * - Removes unnecessary '/..' parts.\n *\n * Based on code in the Node.js 'path' core module.\n *\n * @param aPath The path or url to normalize.\n */\nfunction normalize(aPath) {\n var path = aPath;\n var url = urlParse(aPath);\n if (url) {\n if (!url.path) {\n return aPath;\n }\n path = url.path;\n }\n var isAbsolute = exports.isAbsolute(path);\n\n var parts = path.split(/\\/+/);\n for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {\n part = parts[i];\n if (part === '.') {\n parts.splice(i, 1);\n } else if (part === '..') {\n up++;\n } else if (up > 0) {\n if (part === '') {\n // The first part is blank if the path is absolute. Trying to go\n // above the root is a no-op. Therefore we can remove all '..' parts\n // directly after the root.\n parts.splice(i + 1, up);\n up = 0;\n } else {\n parts.splice(i, 2);\n up--;\n }\n }\n }\n path = parts.join('/');\n\n if (path === '') {\n path = isAbsolute ? '/' : '.';\n }\n\n if (url) {\n url.path = path;\n return urlGenerate(url);\n }\n return path;\n}\nexports.normalize = normalize;\n\n/**\n * Joins two paths/URLs.\n *\n * @param aRoot The root path or URL.\n * @param aPath The path or URL to be joined with the root.\n *\n * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a\n * scheme-relative URL: Then the scheme of aRoot, if any, is prepended\n * first.\n * - Otherwise aPath is a path. If aRoot is a URL, then its path portion\n * is updated with the result and aRoot is returned. Otherwise the result\n * is returned.\n * - If aPath is absolute, the result is aPath.\n * - Otherwise the two paths are joined with a slash.\n * - Joining for example 'http://' and 'www.example.com' is also supported.\n */\nfunction join(aRoot, aPath) {\n if (aRoot === \"\") {\n aRoot = \".\";\n }\n if (aPath === \"\") {\n aPath = \".\";\n }\n var aPathUrl = urlParse(aPath);\n var aRootUrl = urlParse(aRoot);\n if (aRootUrl) {\n aRoot = aRootUrl.path || '/';\n }\n\n // `join(foo, '//www.example.org')`\n if (aPathUrl && !aPathUrl.scheme) {\n if (aRootUrl) {\n aPathUrl.scheme = aRootUrl.scheme;\n }\n return urlGenerate(aPathUrl);\n }\n\n if (aPathUrl || aPath.match(dataUrlRegexp)) {\n return aPath;\n }\n\n // `join('http://', 'www.example.com')`\n if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {\n aRootUrl.host = aPath;\n return urlGenerate(aRootUrl);\n }\n\n var joined = aPath.charAt(0) === '/'\n ? aPath\n : normalize(aRoot.replace(/\\/+$/, '') + '/' + aPath);\n\n if (aRootUrl) {\n aRootUrl.path = joined;\n return urlGenerate(aRootUrl);\n }\n return joined;\n}\nexports.join = join;\n\nexports.isAbsolute = function (aPath) {\n return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp);\n};\n\n/**\n * Make a path relative to a URL or another path.\n *\n * @param aRoot The root path or URL.\n * @param aPath The path or URL to be made relative to aRoot.\n */\nfunction relative(aRoot, aPath) {\n if (aRoot === \"\") {\n aRoot = \".\";\n }\n\n aRoot = aRoot.replace(/\\/$/, '');\n\n // It is possible for the path to be above the root. In this case, simply\n // checking whether the root is a prefix of the path won't work. Instead, we\n // need to remove components from the root one by one, until either we find\n // a prefix that fits, or we run out of components to remove.\n var level = 0;\n while (aPath.indexOf(aRoot + '/') !== 0) {\n var index = aRoot.lastIndexOf(\"/\");\n if (index < 0) {\n return aPath;\n }\n\n // If the only part of the root that is left is the scheme (i.e. http://,\n // file:///, etc.), one or more slashes (/), or simply nothing at all, we\n // have exhausted all components, so the path is not relative to the root.\n aRoot = aRoot.slice(0, index);\n if (aRoot.match(/^([^\\/]+:\\/)?\\/*$/)) {\n return aPath;\n }\n\n ++level;\n }\n\n // Make sure we add a \"../\" for each component we removed from the root.\n return Array(level + 1).join(\"../\") + aPath.substr(aRoot.length + 1);\n}\nexports.relative = relative;\n\nvar supportsNullProto = (function () {\n var obj = Object.create(null);\n return !('__proto__' in obj);\n}());\n\nfunction identity (s) {\n return s;\n}\n\n/**\n * Because behavior goes wacky when you set `__proto__` on objects, we\n * have to prefix all the strings in our set with an arbitrary character.\n *\n * See https://github.com/mozilla/source-map/pull/31 and\n * https://github.com/mozilla/source-map/issues/30\n *\n * @param String aStr\n */\nfunction toSetString(aStr) {\n if (isProtoString(aStr)) {\n return '$' + aStr;\n }\n\n return aStr;\n}\nexports.toSetString = supportsNullProto ? identity : toSetString;\n\nfunction fromSetString(aStr) {\n if (isProtoString(aStr)) {\n return aStr.slice(1);\n }\n\n return aStr;\n}\nexports.fromSetString = supportsNullProto ? identity : fromSetString;\n\nfunction isProtoString(s) {\n if (!s) {\n return false;\n }\n\n var length = s.length;\n\n if (length < 9 /* \"__proto__\".length */) {\n return false;\n }\n\n if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||\n s.charCodeAt(length - 2) !== 95 /* '_' */ ||\n s.charCodeAt(length - 3) !== 111 /* 'o' */ ||\n s.charCodeAt(length - 4) !== 116 /* 't' */ ||\n s.charCodeAt(length - 5) !== 111 /* 'o' */ ||\n s.charCodeAt(length - 6) !== 114 /* 'r' */ ||\n s.charCodeAt(length - 7) !== 112 /* 'p' */ ||\n s.charCodeAt(length - 8) !== 95 /* '_' */ ||\n s.charCodeAt(length - 9) !== 95 /* '_' */) {\n return false;\n }\n\n for (var i = length - 10; i >= 0; i--) {\n if (s.charCodeAt(i) !== 36 /* '$' */) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Comparator between two mappings where the original positions are compared.\n *\n * Optionally pass in `true` as `onlyCompareGenerated` to consider two\n * mappings with the same original source/line/column, but different generated\n * line and column the same. Useful when searching for a mapping with a\n * stubbed out mapping.\n */\nfunction compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {\n var cmp = mappingA.source - mappingB.source;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.originalLine - mappingB.originalLine;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.originalColumn - mappingB.originalColumn;\n if (cmp !== 0 || onlyCompareOriginal) {\n return cmp;\n }\n\n cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.generatedLine - mappingB.generatedLine;\n if (cmp !== 0) {\n return cmp;\n }\n\n return mappingA.name - mappingB.name;\n}\nexports.compareByOriginalPositions = compareByOriginalPositions;\n\n/**\n * Comparator between two mappings with deflated source and name indices where\n * the generated positions are compared.\n *\n * Optionally pass in `true` as `onlyCompareGenerated` to consider two\n * mappings with the same generated line and column, but different\n * source/name/original line and column the same. Useful when searching for a\n * mapping with a stubbed out mapping.\n */\nfunction compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {\n var cmp = mappingA.generatedLine - mappingB.generatedLine;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n if (cmp !== 0 || onlyCompareGenerated) {\n return cmp;\n }\n\n cmp = mappingA.source - mappingB.source;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.originalLine - mappingB.originalLine;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.originalColumn - mappingB.originalColumn;\n if (cmp !== 0) {\n return cmp;\n }\n\n return mappingA.name - mappingB.name;\n}\nexports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;\n\nfunction strcmp(aStr1, aStr2) {\n if (aStr1 === aStr2) {\n return 0;\n }\n\n if (aStr1 > aStr2) {\n return 1;\n }\n\n return -1;\n}\n\n/**\n * Comparator between two mappings with inflated source and name strings where\n * the generated positions are compared.\n */\nfunction compareByGeneratedPositionsInflated(mappingA, mappingB) {\n var cmp = mappingA.generatedLine - mappingB.generatedLine;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = strcmp(mappingA.source, mappingB.source);\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.originalLine - mappingB.originalLine;\n if (cmp !== 0) {\n return cmp;\n }\n\n cmp = mappingA.originalColumn - mappingB.originalColumn;\n if (cmp !== 0) {\n return cmp;\n }\n\n return strcmp(mappingA.name, mappingB.name);\n}\nexports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/util.js\n// module id = 4\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nvar util = require('./util');\nvar has = Object.prototype.hasOwnProperty;\nvar hasNativeMap = typeof Map !== \"undefined\";\n\n/**\n * A data structure which is a combination of an array and a set. Adding a new\n * member is O(1), testing for membership is O(1), and finding the index of an\n * element is O(1). Removing elements from the set is not supported. Only\n * strings are supported for membership.\n */\nfunction ArraySet() {\n this._array = [];\n this._set = hasNativeMap ? new Map() : Object.create(null);\n}\n\n/**\n * Static method for creating ArraySet instances from an existing array.\n */\nArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {\n var set = new ArraySet();\n for (var i = 0, len = aArray.length; i < len; i++) {\n set.add(aArray[i], aAllowDuplicates);\n }\n return set;\n};\n\n/**\n * Return how many unique items are in this ArraySet. If duplicates have been\n * added, than those do not count towards the size.\n *\n * @returns Number\n */\nArraySet.prototype.size = function ArraySet_size() {\n return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;\n};\n\n/**\n * Add the given string to this set.\n *\n * @param String aStr\n */\nArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {\n var sStr = hasNativeMap ? aStr : util.toSetString(aStr);\n var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);\n var idx = this._array.length;\n if (!isDuplicate || aAllowDuplicates) {\n this._array.push(aStr);\n }\n if (!isDuplicate) {\n if (hasNativeMap) {\n this._set.set(aStr, idx);\n } else {\n this._set[sStr] = idx;\n }\n }\n};\n\n/**\n * Is the given string a member of this set?\n *\n * @param String aStr\n */\nArraySet.prototype.has = function ArraySet_has(aStr) {\n if (hasNativeMap) {\n return this._set.has(aStr);\n } else {\n var sStr = util.toSetString(aStr);\n return has.call(this._set, sStr);\n }\n};\n\n/**\n * What is the index of the given string in the array?\n *\n * @param String aStr\n */\nArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {\n if (hasNativeMap) {\n var idx = this._set.get(aStr);\n if (idx >= 0) {\n return idx;\n }\n } else {\n var sStr = util.toSetString(aStr);\n if (has.call(this._set, sStr)) {\n return this._set[sStr];\n }\n }\n\n throw new Error('\"' + aStr + '\" is not in the set.');\n};\n\n/**\n * What is the element at the given index?\n *\n * @param Number aIdx\n */\nArraySet.prototype.at = function ArraySet_at(aIdx) {\n if (aIdx >= 0 && aIdx < this._array.length) {\n return this._array[aIdx];\n }\n throw new Error('No element indexed by ' + aIdx);\n};\n\n/**\n * Returns the array representation of this set (which has the proper indices\n * indicated by indexOf). Note that this is a copy of the internal array used\n * for storing the members so that no one can mess with internal state.\n */\nArraySet.prototype.toArray = function ArraySet_toArray() {\n return this._array.slice();\n};\n\nexports.ArraySet = ArraySet;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/array-set.js\n// module id = 5\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2014 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nvar util = require('./util');\n\n/**\n * Determine whether mappingB is after mappingA with respect to generated\n * position.\n */\nfunction generatedPositionAfter(mappingA, mappingB) {\n // Optimized for most common case\n var lineA = mappingA.generatedLine;\n var lineB = mappingB.generatedLine;\n var columnA = mappingA.generatedColumn;\n var columnB = mappingB.generatedColumn;\n return lineB > lineA || lineB == lineA && columnB >= columnA ||\n util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;\n}\n\n/**\n * A data structure to provide a sorted view of accumulated mappings in a\n * performance conscious manner. It trades a neglibable overhead in general\n * case for a large speedup in case of mappings being added in order.\n */\nfunction MappingList() {\n this._array = [];\n this._sorted = true;\n // Serves as infimum\n this._last = {generatedLine: -1, generatedColumn: 0};\n}\n\n/**\n * Iterate through internal items. This method takes the same arguments that\n * `Array.prototype.forEach` takes.\n *\n * NOTE: The order of the mappings is NOT guaranteed.\n */\nMappingList.prototype.unsortedForEach =\n function MappingList_forEach(aCallback, aThisArg) {\n this._array.forEach(aCallback, aThisArg);\n };\n\n/**\n * Add the given source mapping.\n *\n * @param Object aMapping\n */\nMappingList.prototype.add = function MappingList_add(aMapping) {\n if (generatedPositionAfter(this._last, aMapping)) {\n this._last = aMapping;\n this._array.push(aMapping);\n } else {\n this._sorted = false;\n this._array.push(aMapping);\n }\n};\n\n/**\n * Returns the flat, sorted array of mappings. The mappings are sorted by\n * generated position.\n *\n * WARNING: This method returns internal data without copying, for\n * performance. The return value must NOT be mutated, and should be treated as\n * an immutable borrow. If you want to take ownership, you must make your own\n * copy.\n */\nMappingList.prototype.toArray = function MappingList_toArray() {\n if (!this._sorted) {\n this._array.sort(util.compareByGeneratedPositionsInflated);\n this._sorted = true;\n }\n return this._array;\n};\n\nexports.MappingList = MappingList;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/mapping-list.js\n// module id = 6\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nvar util = require('./util');\nvar binarySearch = require('./binary-search');\nvar ArraySet = require('./array-set').ArraySet;\nvar base64VLQ = require('./base64-vlq');\nvar quickSort = require('./quick-sort').quickSort;\n\nfunction SourceMapConsumer(aSourceMap) {\n var sourceMap = aSourceMap;\n if (typeof aSourceMap === 'string') {\n sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n }\n\n return sourceMap.sections != null\n ? new IndexedSourceMapConsumer(sourceMap)\n : new BasicSourceMapConsumer(sourceMap);\n}\n\nSourceMapConsumer.fromSourceMap = function(aSourceMap) {\n return BasicSourceMapConsumer.fromSourceMap(aSourceMap);\n}\n\n/**\n * The version of the source mapping spec that we are consuming.\n */\nSourceMapConsumer.prototype._version = 3;\n\n// `__generatedMappings` and `__originalMappings` are arrays that hold the\n// parsed mapping coordinates from the source map's \"mappings\" attribute. They\n// are lazily instantiated, accessed via the `_generatedMappings` and\n// `_originalMappings` getters respectively, and we only parse the mappings\n// and create these arrays once queried for a source location. We jump through\n// these hoops because there can be many thousands of mappings, and parsing\n// them is expensive, so we only want to do it if we must.\n//\n// Each object in the arrays is of the form:\n//\n// {\n// generatedLine: The line number in the generated code,\n// generatedColumn: The column number in the generated code,\n// source: The path to the original source file that generated this\n// chunk of code,\n// originalLine: The line number in the original source that\n// corresponds to this chunk of generated code,\n// originalColumn: The column number in the original source that\n// corresponds to this chunk of generated code,\n// name: The name of the original symbol which generated this chunk of\n// code.\n// }\n//\n// All properties except for `generatedLine` and `generatedColumn` can be\n// `null`.\n//\n// `_generatedMappings` is ordered by the generated positions.\n//\n// `_originalMappings` is ordered by the original positions.\n\nSourceMapConsumer.prototype.__generatedMappings = null;\nObject.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {\n get: function () {\n if (!this.__generatedMappings) {\n this._parseMappings(this._mappings, this.sourceRoot);\n }\n\n return this.__generatedMappings;\n }\n});\n\nSourceMapConsumer.prototype.__originalMappings = null;\nObject.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {\n get: function () {\n if (!this.__originalMappings) {\n this._parseMappings(this._mappings, this.sourceRoot);\n }\n\n return this.__originalMappings;\n }\n});\n\nSourceMapConsumer.prototype._charIsMappingSeparator =\n function SourceMapConsumer_charIsMappingSeparator(aStr, index) {\n var c = aStr.charAt(index);\n return c === \";\" || c === \",\";\n };\n\n/**\n * Parse the mappings in a string in to a data structure which we can easily\n * query (the ordered arrays in the `this.__generatedMappings` and\n * `this.__originalMappings` properties).\n */\nSourceMapConsumer.prototype._parseMappings =\n function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n throw new Error(\"Subclasses must implement _parseMappings\");\n };\n\nSourceMapConsumer.GENERATED_ORDER = 1;\nSourceMapConsumer.ORIGINAL_ORDER = 2;\n\nSourceMapConsumer.GREATEST_LOWER_BOUND = 1;\nSourceMapConsumer.LEAST_UPPER_BOUND = 2;\n\n/**\n * Iterate over each mapping between an original source/line/column and a\n * generated line/column in this source map.\n *\n * @param Function aCallback\n * The function that is called with each mapping.\n * @param Object aContext\n * Optional. If specified, this object will be the value of `this` every\n * time that `aCallback` is called.\n * @param aOrder\n * Either `SourceMapConsumer.GENERATED_ORDER` or\n * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to\n * iterate over the mappings sorted by the generated file's line/column\n * order or the original's source/line/column order, respectively. Defaults to\n * `SourceMapConsumer.GENERATED_ORDER`.\n */\nSourceMapConsumer.prototype.eachMapping =\n function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {\n var context = aContext || null;\n var order = aOrder || SourceMapConsumer.GENERATED_ORDER;\n\n var mappings;\n switch (order) {\n case SourceMapConsumer.GENERATED_ORDER:\n mappings = this._generatedMappings;\n break;\n case SourceMapConsumer.ORIGINAL_ORDER:\n mappings = this._originalMappings;\n break;\n default:\n throw new Error(\"Unknown order of iteration.\");\n }\n\n var sourceRoot = this.sourceRoot;\n mappings.map(function (mapping) {\n var source = mapping.source === null ? null : this._sources.at(mapping.source);\n if (source != null && sourceRoot != null) {\n source = util.join(sourceRoot, source);\n }\n return {\n source: source,\n generatedLine: mapping.generatedLine,\n generatedColumn: mapping.generatedColumn,\n originalLine: mapping.originalLine,\n originalColumn: mapping.originalColumn,\n name: mapping.name === null ? null : this._names.at(mapping.name)\n };\n }, this).forEach(aCallback, context);\n };\n\n/**\n * Returns all generated line and column information for the original source,\n * line, and column provided. If no column is provided, returns all mappings\n * corresponding to a either the line we are searching for or the next\n * closest line that has any mappings. Otherwise, returns all mappings\n * corresponding to the given line and either the column we are searching for\n * or the next closest column that has any offsets.\n *\n * The only argument is an object with the following properties:\n *\n * - source: The filename of the original source.\n * - line: The line number in the original source.\n * - column: Optional. the column number in the original source.\n *\n * and an array of objects is returned, each with the following properties:\n *\n * - line: The line number in the generated source, or null.\n * - column: The column number in the generated source, or null.\n */\nSourceMapConsumer.prototype.allGeneratedPositionsFor =\n function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {\n var line = util.getArg(aArgs, 'line');\n\n // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping\n // returns the index of the closest mapping less than the needle. By\n // setting needle.originalColumn to 0, we thus find the last mapping for\n // the given line, provided such a mapping exists.\n var needle = {\n source: util.getArg(aArgs, 'source'),\n originalLine: line,\n originalColumn: util.getArg(aArgs, 'column', 0)\n };\n\n if (this.sourceRoot != null) {\n needle.source = util.relative(this.sourceRoot, needle.source);\n }\n if (!this._sources.has(needle.source)) {\n return [];\n }\n needle.source = this._sources.indexOf(needle.source);\n\n var mappings = [];\n\n var index = this._findMapping(needle,\n this._originalMappings,\n \"originalLine\",\n \"originalColumn\",\n util.compareByOriginalPositions,\n binarySearch.LEAST_UPPER_BOUND);\n if (index >= 0) {\n var mapping = this._originalMappings[index];\n\n if (aArgs.column === undefined) {\n var originalLine = mapping.originalLine;\n\n // Iterate until either we run out of mappings, or we run into\n // a mapping for a different line than the one we found. Since\n // mappings are sorted, this is guaranteed to find all mappings for\n // the line we found.\n while (mapping && mapping.originalLine === originalLine) {\n mappings.push({\n line: util.getArg(mapping, 'generatedLine', null),\n column: util.getArg(mapping, 'generatedColumn', null),\n lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n });\n\n mapping = this._originalMappings[++index];\n }\n } else {\n var originalColumn = mapping.originalColumn;\n\n // Iterate until either we run out of mappings, or we run into\n // a mapping for a different line than the one we were searching for.\n // Since mappings are sorted, this is guaranteed to find all mappings for\n // the line we are searching for.\n while (mapping &&\n mapping.originalLine === line &&\n mapping.originalColumn == originalColumn) {\n mappings.push({\n line: util.getArg(mapping, 'generatedLine', null),\n column: util.getArg(mapping, 'generatedColumn', null),\n lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n });\n\n mapping = this._originalMappings[++index];\n }\n }\n }\n\n return mappings;\n };\n\nexports.SourceMapConsumer = SourceMapConsumer;\n\n/**\n * A BasicSourceMapConsumer instance represents a parsed source map which we can\n * query for information about the original file positions by giving it a file\n * position in the generated source.\n *\n * The only parameter is the raw source map (either as a JSON string, or\n * already parsed to an object). According to the spec, source maps have the\n * following attributes:\n *\n * - version: Which version of the source map spec this map is following.\n * - sources: An array of URLs to the original source files.\n * - names: An array of identifiers which can be referrenced by individual mappings.\n * - sourceRoot: Optional. The URL root from which all sources are relative.\n * - sourcesContent: Optional. An array of contents of the original source files.\n * - mappings: A string of base64 VLQs which contain the actual mappings.\n * - file: Optional. The generated file this source map is associated with.\n *\n * Here is an example source map, taken from the source map spec[0]:\n *\n * {\n * version : 3,\n * file: \"out.js\",\n * sourceRoot : \"\",\n * sources: [\"foo.js\", \"bar.js\"],\n * names: [\"src\", \"maps\", \"are\", \"fun\"],\n * mappings: \"AA,AB;;ABCDE;\"\n * }\n *\n * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#\n */\nfunction BasicSourceMapConsumer(aSourceMap) {\n var sourceMap = aSourceMap;\n if (typeof aSourceMap === 'string') {\n sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n }\n\n var version = util.getArg(sourceMap, 'version');\n var sources = util.getArg(sourceMap, 'sources');\n // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which\n // requires the array) to play nice here.\n var names = util.getArg(sourceMap, 'names', []);\n var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);\n var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);\n var mappings = util.getArg(sourceMap, 'mappings');\n var file = util.getArg(sourceMap, 'file', null);\n\n // Once again, Sass deviates from the spec and supplies the version as a\n // string rather than a number, so we use loose equality checking here.\n if (version != this._version) {\n throw new Error('Unsupported version: ' + version);\n }\n\n sources = sources\n .map(String)\n // Some source maps produce relative source paths like \"./foo.js\" instead of\n // \"foo.js\". Normalize these first so that future comparisons will succeed.\n // See bugzil.la/1090768.\n .map(util.normalize)\n // Always ensure that absolute sources are internally stored relative to\n // the source root, if the source root is absolute. Not doing this would\n // be particularly problematic when the source root is a prefix of the\n // source (valid, but why??). See github issue #199 and bugzil.la/1188982.\n .map(function (source) {\n return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)\n ? util.relative(sourceRoot, source)\n : source;\n });\n\n // Pass `true` below to allow duplicate names and sources. While source maps\n // are intended to be compressed and deduplicated, the TypeScript compiler\n // sometimes generates source maps with duplicates in them. See Github issue\n // #72 and bugzil.la/889492.\n this._names = ArraySet.fromArray(names.map(String), true);\n this._sources = ArraySet.fromArray(sources, true);\n\n this.sourceRoot = sourceRoot;\n this.sourcesContent = sourcesContent;\n this._mappings = mappings;\n this.file = file;\n}\n\nBasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);\nBasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;\n\n/**\n * Create a BasicSourceMapConsumer from a SourceMapGenerator.\n *\n * @param SourceMapGenerator aSourceMap\n * The source map that will be consumed.\n * @returns BasicSourceMapConsumer\n */\nBasicSourceMapConsumer.fromSourceMap =\n function SourceMapConsumer_fromSourceMap(aSourceMap) {\n var smc = Object.create(BasicSourceMapConsumer.prototype);\n\n var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);\n var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);\n smc.sourceRoot = aSourceMap._sourceRoot;\n smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),\n smc.sourceRoot);\n smc.file = aSourceMap._file;\n\n // Because we are modifying the entries (by converting string sources and\n // names to indices into the sources and names ArraySets), we have to make\n // a copy of the entry or else bad things happen. Shared mutable state\n // strikes again! See github issue #191.\n\n var generatedMappings = aSourceMap._mappings.toArray().slice();\n var destGeneratedMappings = smc.__generatedMappings = [];\n var destOriginalMappings = smc.__originalMappings = [];\n\n for (var i = 0, length = generatedMappings.length; i < length; i++) {\n var srcMapping = generatedMappings[i];\n var destMapping = new Mapping;\n destMapping.generatedLine = srcMapping.generatedLine;\n destMapping.generatedColumn = srcMapping.generatedColumn;\n\n if (srcMapping.source) {\n destMapping.source = sources.indexOf(srcMapping.source);\n destMapping.originalLine = srcMapping.originalLine;\n destMapping.originalColumn = srcMapping.originalColumn;\n\n if (srcMapping.name) {\n destMapping.name = names.indexOf(srcMapping.name);\n }\n\n destOriginalMappings.push(destMapping);\n }\n\n destGeneratedMappings.push(destMapping);\n }\n\n quickSort(smc.__originalMappings, util.compareByOriginalPositions);\n\n return smc;\n };\n\n/**\n * The version of the source mapping spec that we are consuming.\n */\nBasicSourceMapConsumer.prototype._version = 3;\n\n/**\n * The list of original sources.\n */\nObject.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {\n get: function () {\n return this._sources.toArray().map(function (s) {\n return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;\n }, this);\n }\n});\n\n/**\n * Provide the JIT with a nice shape / hidden class.\n */\nfunction Mapping() {\n this.generatedLine = 0;\n this.generatedColumn = 0;\n this.source = null;\n this.originalLine = null;\n this.originalColumn = null;\n this.name = null;\n}\n\n/**\n * Parse the mappings in a string in to a data structure which we can easily\n * query (the ordered arrays in the `this.__generatedMappings` and\n * `this.__originalMappings` properties).\n */\nBasicSourceMapConsumer.prototype._parseMappings =\n function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n var generatedLine = 1;\n var previousGeneratedColumn = 0;\n var previousOriginalLine = 0;\n var previousOriginalColumn = 0;\n var previousSource = 0;\n var previousName = 0;\n var length = aStr.length;\n var index = 0;\n var cachedSegments = {};\n var temp = {};\n var originalMappings = [];\n var generatedMappings = [];\n var mapping, str, segment, end, value;\n\n while (index < length) {\n if (aStr.charAt(index) === ';') {\n generatedLine++;\n index++;\n previousGeneratedColumn = 0;\n }\n else if (aStr.charAt(index) === ',') {\n index++;\n }\n else {\n mapping = new Mapping();\n mapping.generatedLine = generatedLine;\n\n // Because each offset is encoded relative to the previous one,\n // many segments often have the same encoding. We can exploit this\n // fact by caching the parsed variable length fields of each segment,\n // allowing us to avoid a second parse if we encounter the same\n // segment again.\n for (end = index; end < length; end++) {\n if (this._charIsMappingSeparator(aStr, end)) {\n break;\n }\n }\n str = aStr.slice(index, end);\n\n segment = cachedSegments[str];\n if (segment) {\n index += str.length;\n } else {\n segment = [];\n while (index < end) {\n base64VLQ.decode(aStr, index, temp);\n value = temp.value;\n index = temp.rest;\n segment.push(value);\n }\n\n if (segment.length === 2) {\n throw new Error('Found a source, but no line and column');\n }\n\n if (segment.length === 3) {\n throw new Error('Found a source and line, but no column');\n }\n\n cachedSegments[str] = segment;\n }\n\n // Generated column.\n mapping.generatedColumn = previousGeneratedColumn + segment[0];\n previousGeneratedColumn = mapping.generatedColumn;\n\n if (segment.length > 1) {\n // Original source.\n mapping.source = previousSource + segment[1];\n previousSource += segment[1];\n\n // Original line.\n mapping.originalLine = previousOriginalLine + segment[2];\n previousOriginalLine = mapping.originalLine;\n // Lines are stored 0-based\n mapping.originalLine += 1;\n\n // Original column.\n mapping.originalColumn = previousOriginalColumn + segment[3];\n previousOriginalColumn = mapping.originalColumn;\n\n if (segment.length > 4) {\n // Original name.\n mapping.name = previousName + segment[4];\n previousName += segment[4];\n }\n }\n\n generatedMappings.push(mapping);\n if (typeof mapping.originalLine === 'number') {\n originalMappings.push(mapping);\n }\n }\n }\n\n quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);\n this.__generatedMappings = generatedMappings;\n\n quickSort(originalMappings, util.compareByOriginalPositions);\n this.__originalMappings = originalMappings;\n };\n\n/**\n * Find the mapping that best matches the hypothetical \"needle\" mapping that\n * we are searching for in the given \"haystack\" of mappings.\n */\nBasicSourceMapConsumer.prototype._findMapping =\n function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,\n aColumnName, aComparator, aBias) {\n // To return the position we are searching for, we must first find the\n // mapping for the given position and then return the opposite position it\n // points to. Because the mappings are sorted, we can use binary search to\n // find the best mapping.\n\n if (aNeedle[aLineName] <= 0) {\n throw new TypeError('Line must be greater than or equal to 1, got '\n + aNeedle[aLineName]);\n }\n if (aNeedle[aColumnName] < 0) {\n throw new TypeError('Column must be greater than or equal to 0, got '\n + aNeedle[aColumnName]);\n }\n\n return binarySearch.search(aNeedle, aMappings, aComparator, aBias);\n };\n\n/**\n * Compute the last column for each generated mapping. The last column is\n * inclusive.\n */\nBasicSourceMapConsumer.prototype.computeColumnSpans =\n function SourceMapConsumer_computeColumnSpans() {\n for (var index = 0; index < this._generatedMappings.length; ++index) {\n var mapping = this._generatedMappings[index];\n\n // Mappings do not contain a field for the last generated columnt. We\n // can come up with an optimistic estimate, however, by assuming that\n // mappings are contiguous (i.e. given two consecutive mappings, the\n // first mapping ends where the second one starts).\n if (index + 1 < this._generatedMappings.length) {\n var nextMapping = this._generatedMappings[index + 1];\n\n if (mapping.generatedLine === nextMapping.generatedLine) {\n mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;\n continue;\n }\n }\n\n // The last mapping for each line spans the entire line.\n mapping.lastGeneratedColumn = Infinity;\n }\n };\n\n/**\n * Returns the original source, line, and column information for the generated\n * source's line and column positions provided. The only argument is an object\n * with the following properties:\n *\n * - line: The line number in the generated source.\n * - column: The column number in the generated source.\n * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or\n * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.\n *\n * and an object is returned with the following properties:\n *\n * - source: The original source file, or null.\n * - line: The line number in the original source, or null.\n * - column: The column number in the original source, or null.\n * - name: The original identifier, or null.\n */\nBasicSourceMapConsumer.prototype.originalPositionFor =\n function SourceMapConsumer_originalPositionFor(aArgs) {\n var needle = {\n generatedLine: util.getArg(aArgs, 'line'),\n generatedColumn: util.getArg(aArgs, 'column')\n };\n\n var index = this._findMapping(\n needle,\n this._generatedMappings,\n \"generatedLine\",\n \"generatedColumn\",\n util.compareByGeneratedPositionsDeflated,\n util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)\n );\n\n if (index >= 0) {\n var mapping = this._generatedMappings[index];\n\n if (mapping.generatedLine === needle.generatedLine) {\n var source = util.getArg(mapping, 'source', null);\n if (source !== null) {\n source = this._sources.at(source);\n if (this.sourceRoot != null) {\n source = util.join(this.sourceRoot, source);\n }\n }\n var name = util.getArg(mapping, 'name', null);\n if (name !== null) {\n name = this._names.at(name);\n }\n return {\n source: source,\n line: util.getArg(mapping, 'originalLine', null),\n column: util.getArg(mapping, 'originalColumn', null),\n name: name\n };\n }\n }\n\n return {\n source: null,\n line: null,\n column: null,\n name: null\n };\n };\n\n/**\n * Return true if we have the source content for every source in the source\n * map, false otherwise.\n */\nBasicSourceMapConsumer.prototype.hasContentsOfAllSources =\n function BasicSourceMapConsumer_hasContentsOfAllSources() {\n if (!this.sourcesContent) {\n return false;\n }\n return this.sourcesContent.length >= this._sources.size() &&\n !this.sourcesContent.some(function (sc) { return sc == null; });\n };\n\n/**\n * Returns the original source content. The only argument is the url of the\n * original source file. Returns null if no original source content is\n * available.\n */\nBasicSourceMapConsumer.prototype.sourceContentFor =\n function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {\n if (!this.sourcesContent) {\n return null;\n }\n\n if (this.sourceRoot != null) {\n aSource = util.relative(this.sourceRoot, aSource);\n }\n\n if (this._sources.has(aSource)) {\n return this.sourcesContent[this._sources.indexOf(aSource)];\n }\n\n var url;\n if (this.sourceRoot != null\n && (url = util.urlParse(this.sourceRoot))) {\n // XXX: file:// URIs and absolute paths lead to unexpected behavior for\n // many users. We can help them out when they expect file:// URIs to\n // behave like it would if they were running a local HTTP server. See\n // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.\n var fileUriAbsPath = aSource.replace(/^file:\\/\\//, \"\");\n if (url.scheme == \"file\"\n && this._sources.has(fileUriAbsPath)) {\n return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]\n }\n\n if ((!url.path || url.path == \"/\")\n && this._sources.has(\"/\" + aSource)) {\n return this.sourcesContent[this._sources.indexOf(\"/\" + aSource)];\n }\n }\n\n // This function is used recursively from\n // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we\n // don't want to throw if we can't find the source - we just want to\n // return null, so we provide a flag to exit gracefully.\n if (nullOnMissing) {\n return null;\n }\n else {\n throw new Error('\"' + aSource + '\" is not in the SourceMap.');\n }\n };\n\n/**\n * Returns the generated line and column information for the original source,\n * line, and column positions provided. The only argument is an object with\n * the following properties:\n *\n * - source: The filename of the original source.\n * - line: The line number in the original source.\n * - column: The column number in the original source.\n * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or\n * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.\n *\n * and an object is returned with the following properties:\n *\n * - line: The line number in the generated source, or null.\n * - column: The column number in the generated source, or null.\n */\nBasicSourceMapConsumer.prototype.generatedPositionFor =\n function SourceMapConsumer_generatedPositionFor(aArgs) {\n var source = util.getArg(aArgs, 'source');\n if (this.sourceRoot != null) {\n source = util.relative(this.sourceRoot, source);\n }\n if (!this._sources.has(source)) {\n return {\n line: null,\n column: null,\n lastColumn: null\n };\n }\n source = this._sources.indexOf(source);\n\n var needle = {\n source: source,\n originalLine: util.getArg(aArgs, 'line'),\n originalColumn: util.getArg(aArgs, 'column')\n };\n\n var index = this._findMapping(\n needle,\n this._originalMappings,\n \"originalLine\",\n \"originalColumn\",\n util.compareByOriginalPositions,\n util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)\n );\n\n if (index >= 0) {\n var mapping = this._originalMappings[index];\n\n if (mapping.source === needle.source) {\n return {\n line: util.getArg(mapping, 'generatedLine', null),\n column: util.getArg(mapping, 'generatedColumn', null),\n lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n };\n }\n }\n\n return {\n line: null,\n column: null,\n lastColumn: null\n };\n };\n\nexports.BasicSourceMapConsumer = BasicSourceMapConsumer;\n\n/**\n * An IndexedSourceMapConsumer instance represents a parsed source map which\n * we can query for information. It differs from BasicSourceMapConsumer in\n * that it takes \"indexed\" source maps (i.e. ones with a \"sections\" field) as\n * input.\n *\n * The only parameter is a raw source map (either as a JSON string, or already\n * parsed to an object). According to the spec for indexed source maps, they\n * have the following attributes:\n *\n * - version: Which version of the source map spec this map is following.\n * - file: Optional. The generated file this source map is associated with.\n * - sections: A list of section definitions.\n *\n * Each value under the \"sections\" field has two fields:\n * - offset: The offset into the original specified at which this section\n * begins to apply, defined as an object with a \"line\" and \"column\"\n * field.\n * - map: A source map definition. This source map could also be indexed,\n * but doesn't have to be.\n *\n * Instead of the \"map\" field, it's also possible to have a \"url\" field\n * specifying a URL to retrieve a source map from, but that's currently\n * unsupported.\n *\n * Here's an example source map, taken from the source map spec[0], but\n * modified to omit a section which uses the \"url\" field.\n *\n * {\n * version : 3,\n * file: \"app.js\",\n * sections: [{\n * offset: {line:100, column:10},\n * map: {\n * version : 3,\n * file: \"section.js\",\n * sources: [\"foo.js\", \"bar.js\"],\n * names: [\"src\", \"maps\", \"are\", \"fun\"],\n * mappings: \"AAAA,E;;ABCDE;\"\n * }\n * }],\n * }\n *\n * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt\n */\nfunction IndexedSourceMapConsumer(aSourceMap) {\n var sourceMap = aSourceMap;\n if (typeof aSourceMap === 'string') {\n sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n }\n\n var version = util.getArg(sourceMap, 'version');\n var sections = util.getArg(sourceMap, 'sections');\n\n if (version != this._version) {\n throw new Error('Unsupported version: ' + version);\n }\n\n this._sources = new ArraySet();\n this._names = new ArraySet();\n\n var lastOffset = {\n line: -1,\n column: 0\n };\n this._sections = sections.map(function (s) {\n if (s.url) {\n // The url field will require support for asynchronicity.\n // See https://github.com/mozilla/source-map/issues/16\n throw new Error('Support for url field in sections not implemented.');\n }\n var offset = util.getArg(s, 'offset');\n var offsetLine = util.getArg(offset, 'line');\n var offsetColumn = util.getArg(offset, 'column');\n\n if (offsetLine < lastOffset.line ||\n (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {\n throw new Error('Section offsets must be ordered and non-overlapping.');\n }\n lastOffset = offset;\n\n return {\n generatedOffset: {\n // The offset fields are 0-based, but we use 1-based indices when\n // encoding/decoding from VLQ.\n generatedLine: offsetLine + 1,\n generatedColumn: offsetColumn + 1\n },\n consumer: new SourceMapConsumer(util.getArg(s, 'map'))\n }\n });\n}\n\nIndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);\nIndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;\n\n/**\n * The version of the source mapping spec that we are consuming.\n */\nIndexedSourceMapConsumer.prototype._version = 3;\n\n/**\n * The list of original sources.\n */\nObject.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {\n get: function () {\n var sources = [];\n for (var i = 0; i < this._sections.length; i++) {\n for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {\n sources.push(this._sections[i].consumer.sources[j]);\n }\n }\n return sources;\n }\n});\n\n/**\n * Returns the original source, line, and column information for the generated\n * source's line and column positions provided. The only argument is an object\n * with the following properties:\n *\n * - line: The line number in the generated source.\n * - column: The column number in the generated source.\n *\n * and an object is returned with the following properties:\n *\n * - source: The original source file, or null.\n * - line: The line number in the original source, or null.\n * - column: The column number in the original source, or null.\n * - name: The original identifier, or null.\n */\nIndexedSourceMapConsumer.prototype.originalPositionFor =\n function IndexedSourceMapConsumer_originalPositionFor(aArgs) {\n var needle = {\n generatedLine: util.getArg(aArgs, 'line'),\n generatedColumn: util.getArg(aArgs, 'column')\n };\n\n // Find the section containing the generated position we're trying to map\n // to an original position.\n var sectionIndex = binarySearch.search(needle, this._sections,\n function(needle, section) {\n var cmp = needle.generatedLine - section.generatedOffset.generatedLine;\n if (cmp) {\n return cmp;\n }\n\n return (needle.generatedColumn -\n section.generatedOffset.generatedColumn);\n });\n var section = this._sections[sectionIndex];\n\n if (!section) {\n return {\n source: null,\n line: null,\n column: null,\n name: null\n };\n }\n\n return section.consumer.originalPositionFor({\n line: needle.generatedLine -\n (section.generatedOffset.generatedLine - 1),\n column: needle.generatedColumn -\n (section.generatedOffset.generatedLine === needle.generatedLine\n ? section.generatedOffset.generatedColumn - 1\n : 0),\n bias: aArgs.bias\n });\n };\n\n/**\n * Return true if we have the source content for every source in the source\n * map, false otherwise.\n */\nIndexedSourceMapConsumer.prototype.hasContentsOfAllSources =\n function IndexedSourceMapConsumer_hasContentsOfAllSources() {\n return this._sections.every(function (s) {\n return s.consumer.hasContentsOfAllSources();\n });\n };\n\n/**\n * Returns the original source content. The only argument is the url of the\n * original source file. Returns null if no original source content is\n * available.\n */\nIndexedSourceMapConsumer.prototype.sourceContentFor =\n function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n\n var content = section.consumer.sourceContentFor(aSource, true);\n if (content) {\n return content;\n }\n }\n if (nullOnMissing) {\n return null;\n }\n else {\n throw new Error('\"' + aSource + '\" is not in the SourceMap.');\n }\n };\n\n/**\n * Returns the generated line and column information for the original source,\n * line, and column positions provided. The only argument is an object with\n * the following properties:\n *\n * - source: The filename of the original source.\n * - line: The line number in the original source.\n * - column: The column number in the original source.\n *\n * and an object is returned with the following properties:\n *\n * - line: The line number in the generated source, or null.\n * - column: The column number in the generated source, or null.\n */\nIndexedSourceMapConsumer.prototype.generatedPositionFor =\n function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n\n // Only consider this section if the requested source is in the list of\n // sources of the consumer.\n if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {\n continue;\n }\n var generatedPosition = section.consumer.generatedPositionFor(aArgs);\n if (generatedPosition) {\n var ret = {\n line: generatedPosition.line +\n (section.generatedOffset.generatedLine - 1),\n column: generatedPosition.column +\n (section.generatedOffset.generatedLine === generatedPosition.line\n ? section.generatedOffset.generatedColumn - 1\n : 0)\n };\n return ret;\n }\n }\n\n return {\n line: null,\n column: null\n };\n };\n\n/**\n * Parse the mappings in a string in to a data structure which we can easily\n * query (the ordered arrays in the `this.__generatedMappings` and\n * `this.__originalMappings` properties).\n */\nIndexedSourceMapConsumer.prototype._parseMappings =\n function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n this.__generatedMappings = [];\n this.__originalMappings = [];\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n var sectionMappings = section.consumer._generatedMappings;\n for (var j = 0; j < sectionMappings.length; j++) {\n var mapping = sectionMappings[j];\n\n var source = section.consumer._sources.at(mapping.source);\n if (section.consumer.sourceRoot !== null) {\n source = util.join(section.consumer.sourceRoot, source);\n }\n this._sources.add(source);\n source = this._sources.indexOf(source);\n\n var name = section.consumer._names.at(mapping.name);\n this._names.add(name);\n name = this._names.indexOf(name);\n\n // The mappings coming from the consumer for the section have\n // generated positions relative to the start of the section, so we\n // need to offset them to be relative to the start of the concatenated\n // generated file.\n var adjustedMapping = {\n source: source,\n generatedLine: mapping.generatedLine +\n (section.generatedOffset.generatedLine - 1),\n generatedColumn: mapping.generatedColumn +\n (section.generatedOffset.generatedLine === mapping.generatedLine\n ? section.generatedOffset.generatedColumn - 1\n : 0),\n originalLine: mapping.originalLine,\n originalColumn: mapping.originalColumn,\n name: name\n };\n\n this.__generatedMappings.push(adjustedMapping);\n if (typeof adjustedMapping.originalLine === 'number') {\n this.__originalMappings.push(adjustedMapping);\n }\n }\n }\n\n quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);\n quickSort(this.__originalMappings, util.compareByOriginalPositions);\n };\n\nexports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/source-map-consumer.js\n// module id = 7\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nexports.GREATEST_LOWER_BOUND = 1;\nexports.LEAST_UPPER_BOUND = 2;\n\n/**\n * Recursive implementation of binary search.\n *\n * @param aLow Indices here and lower do not contain the needle.\n * @param aHigh Indices here and higher do not contain the needle.\n * @param aNeedle The element being searched for.\n * @param aHaystack The non-empty array being searched.\n * @param aCompare Function which takes two elements and returns -1, 0, or 1.\n * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or\n * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n */\nfunction recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {\n // This function terminates when one of the following is true:\n //\n // 1. We find the exact element we are looking for.\n //\n // 2. We did not find the exact element, but we can return the index of\n // the next-closest element.\n //\n // 3. We did not find the exact element, and there is no next-closest\n // element than the one we are searching for, so we return -1.\n var mid = Math.floor((aHigh - aLow) / 2) + aLow;\n var cmp = aCompare(aNeedle, aHaystack[mid], true);\n if (cmp === 0) {\n // Found the element we are looking for.\n return mid;\n }\n else if (cmp > 0) {\n // Our needle is greater than aHaystack[mid].\n if (aHigh - mid > 1) {\n // The element is in the upper half.\n return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);\n }\n\n // The exact needle element was not found in this haystack. Determine if\n // we are in termination case (3) or (2) and return the appropriate thing.\n if (aBias == exports.LEAST_UPPER_BOUND) {\n return aHigh < aHaystack.length ? aHigh : -1;\n } else {\n return mid;\n }\n }\n else {\n // Our needle is less than aHaystack[mid].\n if (mid - aLow > 1) {\n // The element is in the lower half.\n return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);\n }\n\n // we are in termination case (3) or (2) and return the appropriate thing.\n if (aBias == exports.LEAST_UPPER_BOUND) {\n return mid;\n } else {\n return aLow < 0 ? -1 : aLow;\n }\n }\n}\n\n/**\n * This is an implementation of binary search which will always try and return\n * the index of the closest element if there is no exact hit. This is because\n * mappings between original and generated line/col pairs are single points,\n * and there is an implicit region between each of them, so a miss just means\n * that you aren't on the very start of a region.\n *\n * @param aNeedle The element you are looking for.\n * @param aHaystack The array that is being searched.\n * @param aCompare A function which takes the needle and an element in the\n * array and returns -1, 0, or 1 depending on whether the needle is less\n * than, equal to, or greater than the element, respectively.\n * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or\n * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.\n */\nexports.search = function search(aNeedle, aHaystack, aCompare, aBias) {\n if (aHaystack.length === 0) {\n return -1;\n }\n\n var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,\n aCompare, aBias || exports.GREATEST_LOWER_BOUND);\n if (index < 0) {\n return -1;\n }\n\n // We have found either the exact element, or the next-closest element than\n // the one we are searching for. However, there may be more than one such\n // element. Make sure we always return the smallest of these.\n while (index - 1 >= 0) {\n if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {\n break;\n }\n --index;\n }\n\n return index;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/binary-search.js\n// module id = 8\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\n// It turns out that some (most?) JavaScript engines don't self-host\n// `Array.prototype.sort`. This makes sense because C++ will likely remain\n// faster than JS when doing raw CPU-intensive sorting. However, when using a\n// custom comparator function, calling back and forth between the VM's C++ and\n// JIT'd JS is rather slow *and* loses JIT type information, resulting in\n// worse generated code for the comparator function than would be optimal. In\n// fact, when sorting with a comparator, these costs outweigh the benefits of\n// sorting in C++. By using our own JS-implemented Quick Sort (below), we get\n// a ~3500ms mean speed-up in `bench/bench.html`.\n\n/**\n * Swap the elements indexed by `x` and `y` in the array `ary`.\n *\n * @param {Array} ary\n * The array.\n * @param {Number} x\n * The index of the first item.\n * @param {Number} y\n * The index of the second item.\n */\nfunction swap(ary, x, y) {\n var temp = ary[x];\n ary[x] = ary[y];\n ary[y] = temp;\n}\n\n/**\n * Returns a random integer within the range `low .. high` inclusive.\n *\n * @param {Number} low\n * The lower bound on the range.\n * @param {Number} high\n * The upper bound on the range.\n */\nfunction randomIntInRange(low, high) {\n return Math.round(low + (Math.random() * (high - low)));\n}\n\n/**\n * The Quick Sort algorithm.\n *\n * @param {Array} ary\n * An array to sort.\n * @param {function} comparator\n * Function to use to compare two items.\n * @param {Number} p\n * Start index of the array\n * @param {Number} r\n * End index of the array\n */\nfunction doQuickSort(ary, comparator, p, r) {\n // If our lower bound is less than our upper bound, we (1) partition the\n // array into two pieces and (2) recurse on each half. If it is not, this is\n // the empty array and our base case.\n\n if (p < r) {\n // (1) Partitioning.\n //\n // The partitioning chooses a pivot between `p` and `r` and moves all\n // elements that are less than or equal to the pivot to the before it, and\n // all the elements that are greater than it after it. The effect is that\n // once partition is done, the pivot is in the exact place it will be when\n // the array is put in sorted order, and it will not need to be moved\n // again. This runs in O(n) time.\n\n // Always choose a random pivot so that an input array which is reverse\n // sorted does not cause O(n^2) running time.\n var pivotIndex = randomIntInRange(p, r);\n var i = p - 1;\n\n swap(ary, pivotIndex, r);\n var pivot = ary[r];\n\n // Immediately after `j` is incremented in this loop, the following hold\n // true:\n //\n // * Every element in `ary[p .. i]` is less than or equal to the pivot.\n //\n // * Every element in `ary[i+1 .. j-1]` is greater than the pivot.\n for (var j = p; j < r; j++) {\n if (comparator(ary[j], pivot) <= 0) {\n i += 1;\n swap(ary, i, j);\n }\n }\n\n swap(ary, i + 1, j);\n var q = i + 1;\n\n // (2) Recurse on each half.\n\n doQuickSort(ary, comparator, p, q - 1);\n doQuickSort(ary, comparator, q + 1, r);\n }\n}\n\n/**\n * Sort the given array in-place with the given comparator function.\n *\n * @param {Array} ary\n * An array to sort.\n * @param {function} comparator\n * Function to use to compare two items.\n */\nexports.quickSort = function (ary, comparator) {\n doQuickSort(ary, comparator, 0, ary.length - 1);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/quick-sort.js\n// module id = 9\n// module chunks = 0","/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\nvar SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;\nvar util = require('./util');\n\n// Matches a Windows-style `\\r\\n` newline or a `\\n` newline used by all other\n// operating systems these days (capturing the result).\nvar REGEX_NEWLINE = /(\\r?\\n)/;\n\n// Newline character code for charCodeAt() comparisons\nvar NEWLINE_CODE = 10;\n\n// Private symbol for identifying `SourceNode`s when multiple versions of\n// the source-map library are loaded. This MUST NOT CHANGE across\n// versions!\nvar isSourceNode = \"$$$isSourceNode$$$\";\n\n/**\n * SourceNodes provide a way to abstract over interpolating/concatenating\n * snippets of generated JavaScript source code while maintaining the line and\n * column information associated with the original source code.\n *\n * @param aLine The original line number.\n * @param aColumn The original column number.\n * @param aSource The original source's filename.\n * @param aChunks Optional. An array of strings which are snippets of\n * generated JS, or other SourceNodes.\n * @param aName The original identifier.\n */\nfunction SourceNode(aLine, aColumn, aSource, aChunks, aName) {\n this.children = [];\n this.sourceContents = {};\n this.line = aLine == null ? null : aLine;\n this.column = aColumn == null ? null : aColumn;\n this.source = aSource == null ? null : aSource;\n this.name = aName == null ? null : aName;\n this[isSourceNode] = true;\n if (aChunks != null) this.add(aChunks);\n}\n\n/**\n * Creates a SourceNode from generated code and a SourceMapConsumer.\n *\n * @param aGeneratedCode The generated code\n * @param aSourceMapConsumer The SourceMap for the generated code\n * @param aRelativePath Optional. The path that relative sources in the\n * SourceMapConsumer should be relative to.\n */\nSourceNode.fromStringWithSourceMap =\n function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {\n // The SourceNode we want to fill with the generated code\n // and the SourceMap\n var node = new SourceNode();\n\n // All even indices of this array are one line of the generated code,\n // while all odd indices are the newlines between two adjacent lines\n // (since `REGEX_NEWLINE` captures its match).\n // Processed fragments are accessed by calling `shiftNextLine`.\n var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);\n var remainingLinesIndex = 0;\n var shiftNextLine = function() {\n var lineContents = getNextLine();\n // The last line of a file might not have a newline.\n var newLine = getNextLine() || \"\";\n return lineContents + newLine;\n\n function getNextLine() {\n return remainingLinesIndex < remainingLines.length ?\n remainingLines[remainingLinesIndex++] : undefined;\n }\n };\n\n // We need to remember the position of \"remainingLines\"\n var lastGeneratedLine = 1, lastGeneratedColumn = 0;\n\n // The generate SourceNodes we need a code range.\n // To extract it current and last mapping is used.\n // Here we store the last mapping.\n var lastMapping = null;\n\n aSourceMapConsumer.eachMapping(function (mapping) {\n if (lastMapping !== null) {\n // We add the code from \"lastMapping\" to \"mapping\":\n // First check if there is a new line in between.\n if (lastGeneratedLine < mapping.generatedLine) {\n // Associate first line with \"lastMapping\"\n addMappingWithCode(lastMapping, shiftNextLine());\n lastGeneratedLine++;\n lastGeneratedColumn = 0;\n // The remaining code is added without mapping\n } else {\n // There is no new line in between.\n // Associate the code between \"lastGeneratedColumn\" and\n // \"mapping.generatedColumn\" with \"lastMapping\"\n var nextLine = remainingLines[remainingLinesIndex];\n var code = nextLine.substr(0, mapping.generatedColumn -\n lastGeneratedColumn);\n remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn -\n lastGeneratedColumn);\n lastGeneratedColumn = mapping.generatedColumn;\n addMappingWithCode(lastMapping, code);\n // No more remaining code, continue\n lastMapping = mapping;\n return;\n }\n }\n // We add the generated code until the first mapping\n // to the SourceNode without any mapping.\n // Each line is added as separate string.\n while (lastGeneratedLine < mapping.generatedLine) {\n node.add(shiftNextLine());\n lastGeneratedLine++;\n }\n if (lastGeneratedColumn < mapping.generatedColumn) {\n var nextLine = remainingLines[remainingLinesIndex];\n node.add(nextLine.substr(0, mapping.generatedColumn));\n remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);\n lastGeneratedColumn = mapping.generatedColumn;\n }\n lastMapping = mapping;\n }, this);\n // We have processed all mappings.\n if (remainingLinesIndex < remainingLines.length) {\n if (lastMapping) {\n // Associate the remaining code in the current line with \"lastMapping\"\n addMappingWithCode(lastMapping, shiftNextLine());\n }\n // and add the remaining lines without any mapping\n node.add(remainingLines.splice(remainingLinesIndex).join(\"\"));\n }\n\n // Copy sourcesContent into SourceNode\n aSourceMapConsumer.sources.forEach(function (sourceFile) {\n var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n if (content != null) {\n if (aRelativePath != null) {\n sourceFile = util.join(aRelativePath, sourceFile);\n }\n node.setSourceContent(sourceFile, content);\n }\n });\n\n return node;\n\n function addMappingWithCode(mapping, code) {\n if (mapping === null || mapping.source === undefined) {\n node.add(code);\n } else {\n var source = aRelativePath\n ? util.join(aRelativePath, mapping.source)\n : mapping.source;\n node.add(new SourceNode(mapping.originalLine,\n mapping.originalColumn,\n source,\n code,\n mapping.name));\n }\n }\n };\n\n/**\n * Add a chunk of generated JS to this source node.\n *\n * @param aChunk A string snippet of generated JS code, another instance of\n * SourceNode, or an array where each member is one of those things.\n */\nSourceNode.prototype.add = function SourceNode_add(aChunk) {\n if (Array.isArray(aChunk)) {\n aChunk.forEach(function (chunk) {\n this.add(chunk);\n }, this);\n }\n else if (aChunk[isSourceNode] || typeof aChunk === \"string\") {\n if (aChunk) {\n this.children.push(aChunk);\n }\n }\n else {\n throw new TypeError(\n \"Expected a SourceNode, string, or an array of SourceNodes and strings. Got \" + aChunk\n );\n }\n return this;\n};\n\n/**\n * Add a chunk of generated JS to the beginning of this source node.\n *\n * @param aChunk A string snippet of generated JS code, another instance of\n * SourceNode, or an array where each member is one of those things.\n */\nSourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {\n if (Array.isArray(aChunk)) {\n for (var i = aChunk.length-1; i >= 0; i--) {\n this.prepend(aChunk[i]);\n }\n }\n else if (aChunk[isSourceNode] || typeof aChunk === \"string\") {\n this.children.unshift(aChunk);\n }\n else {\n throw new TypeError(\n \"Expected a SourceNode, string, or an array of SourceNodes and strings. Got \" + aChunk\n );\n }\n return this;\n};\n\n/**\n * Walk over the tree of JS snippets in this node and its children. The\n * walking function is called once for each snippet of JS and is passed that\n * snippet and the its original associated source's line/column location.\n *\n * @param aFn The traversal function.\n */\nSourceNode.prototype.walk = function SourceNode_walk(aFn) {\n var chunk;\n for (var i = 0, len = this.children.length; i < len; i++) {\n chunk = this.children[i];\n if (chunk[isSourceNode]) {\n chunk.walk(aFn);\n }\n else {\n if (chunk !== '') {\n aFn(chunk, { source: this.source,\n line: this.line,\n column: this.column,\n name: this.name });\n }\n }\n }\n};\n\n/**\n * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between\n * each of `this.children`.\n *\n * @param aSep The separator.\n */\nSourceNode.prototype.join = function SourceNode_join(aSep) {\n var newChildren;\n var i;\n var len = this.children.length;\n if (len > 0) {\n newChildren = [];\n for (i = 0; i < len-1; i++) {\n newChildren.push(this.children[i]);\n newChildren.push(aSep);\n }\n newChildren.push(this.children[i]);\n this.children = newChildren;\n }\n return this;\n};\n\n/**\n * Call String.prototype.replace on the very right-most source snippet. Useful\n * for trimming whitespace from the end of a source node, etc.\n *\n * @param aPattern The pattern to replace.\n * @param aReplacement The thing to replace the pattern with.\n */\nSourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {\n var lastChild = this.children[this.children.length - 1];\n if (lastChild[isSourceNode]) {\n lastChild.replaceRight(aPattern, aReplacement);\n }\n else if (typeof lastChild === 'string') {\n this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);\n }\n else {\n this.children.push(''.replace(aPattern, aReplacement));\n }\n return this;\n};\n\n/**\n * Set the source content for a source file. This will be added to the SourceMapGenerator\n * in the sourcesContent field.\n *\n * @param aSourceFile The filename of the source file\n * @param aSourceContent The content of the source file\n */\nSourceNode.prototype.setSourceContent =\n function SourceNode_setSourceContent(aSourceFile, aSourceContent) {\n this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;\n };\n\n/**\n * Walk over the tree of SourceNodes. The walking function is called for each\n * source file content and is passed the filename and source content.\n *\n * @param aFn The traversal function.\n */\nSourceNode.prototype.walkSourceContents =\n function SourceNode_walkSourceContents(aFn) {\n for (var i = 0, len = this.children.length; i < len; i++) {\n if (this.children[i][isSourceNode]) {\n this.children[i].walkSourceContents(aFn);\n }\n }\n\n var sources = Object.keys(this.sourceContents);\n for (var i = 0, len = sources.length; i < len; i++) {\n aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);\n }\n };\n\n/**\n * Return the string representation of this source node. Walks over the tree\n * and concatenates all the various snippets together to one string.\n */\nSourceNode.prototype.toString = function SourceNode_toString() {\n var str = \"\";\n this.walk(function (chunk) {\n str += chunk;\n });\n return str;\n};\n\n/**\n * Returns the string representation of this source node along with a source\n * map.\n */\nSourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {\n var generated = {\n code: \"\",\n line: 1,\n column: 0\n };\n var map = new SourceMapGenerator(aArgs);\n var sourceMappingActive = false;\n var lastOriginalSource = null;\n var lastOriginalLine = null;\n var lastOriginalColumn = null;\n var lastOriginalName = null;\n this.walk(function (chunk, original) {\n generated.code += chunk;\n if (original.source !== null\n && original.line !== null\n && original.column !== null) {\n if(lastOriginalSource !== original.source\n || lastOriginalLine !== original.line\n || lastOriginalColumn !== original.column\n || lastOriginalName !== original.name) {\n map.addMapping({\n source: original.source,\n original: {\n line: original.line,\n column: original.column\n },\n generated: {\n line: generated.line,\n column: generated.column\n },\n name: original.name\n });\n }\n lastOriginalSource = original.source;\n lastOriginalLine = original.line;\n lastOriginalColumn = original.column;\n lastOriginalName = original.name;\n sourceMappingActive = true;\n } else if (sourceMappingActive) {\n map.addMapping({\n generated: {\n line: generated.line,\n column: generated.column\n }\n });\n lastOriginalSource = null;\n sourceMappingActive = false;\n }\n for (var idx = 0, length = chunk.length; idx < length; idx++) {\n if (chunk.charCodeAt(idx) === NEWLINE_CODE) {\n generated.line++;\n generated.column = 0;\n // Mappings end at eol\n if (idx + 1 === length) {\n lastOriginalSource = null;\n sourceMappingActive = false;\n } else if (sourceMappingActive) {\n map.addMapping({\n source: original.source,\n original: {\n line: original.line,\n column: original.column\n },\n generated: {\n line: generated.line,\n column: generated.column\n },\n name: original.name\n });\n }\n } else {\n generated.column++;\n }\n }\n });\n this.walkSourceContents(function (sourceFile, sourceContent) {\n map.setSourceContent(sourceFile, sourceContent);\n });\n\n return { code: generated.code, map: map };\n};\n\nexports.SourceNode = SourceNode;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/source-node.js\n// module id = 10\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/js/node_modules/source-map/lib/array-set.js b/js/node_modules/source-map/lib/array-set.js new file mode 100644 index 0000000..fbd5c81 --- /dev/null +++ b/js/node_modules/source-map/lib/array-set.js @@ -0,0 +1,121 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var util = require('./util'); +var has = Object.prototype.hasOwnProperty; +var hasNativeMap = typeof Map !== "undefined"; + +/** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ +function ArraySet() { + this._array = []; + this._set = hasNativeMap ? new Map() : Object.create(null); +} + +/** + * Static method for creating ArraySet instances from an existing array. + */ +ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; +}; + +/** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ +ArraySet.prototype.size = function ArraySet_size() { + return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; +}; + +/** + * Add the given string to this set. + * + * @param String aStr + */ +ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = hasNativeMap ? aStr : util.toSetString(aStr); + var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + if (hasNativeMap) { + this._set.set(aStr, idx); + } else { + this._set[sStr] = idx; + } + } +}; + +/** + * Is the given string a member of this set? + * + * @param String aStr + */ +ArraySet.prototype.has = function ArraySet_has(aStr) { + if (hasNativeMap) { + return this._set.has(aStr); + } else { + var sStr = util.toSetString(aStr); + return has.call(this._set, sStr); + } +}; + +/** + * What is the index of the given string in the array? + * + * @param String aStr + */ +ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (hasNativeMap) { + var idx = this._set.get(aStr); + if (idx >= 0) { + return idx; + } + } else { + var sStr = util.toSetString(aStr); + if (has.call(this._set, sStr)) { + return this._set[sStr]; + } + } + + throw new Error('"' + aStr + '" is not in the set.'); +}; + +/** + * What is the element at the given index? + * + * @param Number aIdx + */ +ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); +}; + +/** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ +ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); +}; + +exports.ArraySet = ArraySet; diff --git a/js/node_modules/source-map/lib/base64-vlq.js b/js/node_modules/source-map/lib/base64-vlq.js new file mode 100644 index 0000000..612b404 --- /dev/null +++ b/js/node_modules/source-map/lib/base64-vlq.js @@ -0,0 +1,140 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +var base64 = require('./base64'); + +// A single base 64 digit can contain 6 bits of data. For the base 64 variable +// length quantities we use in the source map spec, the first bit is the sign, +// the next four bits are the actual value, and the 6th bit is the +// continuation bit. The continuation bit tells us whether there are more +// digits in this value following this digit. +// +// Continuation +// | Sign +// | | +// V V +// 101011 + +var VLQ_BASE_SHIFT = 5; + +// binary: 100000 +var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + +// binary: 011111 +var VLQ_BASE_MASK = VLQ_BASE - 1; + +// binary: 100000 +var VLQ_CONTINUATION_BIT = VLQ_BASE; + +/** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ +function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; +} + +/** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ +function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; +} + +/** + * Returns the base 64 VLQ encoded value. + */ +exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; +}; + +/** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ +exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; +}; diff --git a/js/node_modules/source-map/lib/base64.js b/js/node_modules/source-map/lib/base64.js new file mode 100644 index 0000000..8aa86b3 --- /dev/null +++ b/js/node_modules/source-map/lib/base64.js @@ -0,0 +1,67 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + +/** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ +exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); +}; + +/** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ +exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; +}; diff --git a/js/node_modules/source-map/lib/binary-search.js b/js/node_modules/source-map/lib/binary-search.js new file mode 100644 index 0000000..010ac94 --- /dev/null +++ b/js/node_modules/source-map/lib/binary-search.js @@ -0,0 +1,111 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +exports.GREATEST_LOWER_BOUND = 1; +exports.LEAST_UPPER_BOUND = 2; + +/** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ +function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } + + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } + + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } +} + +/** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ +exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } + + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } + + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } + + return index; +}; diff --git a/js/node_modules/source-map/lib/mapping-list.js b/js/node_modules/source-map/lib/mapping-list.js new file mode 100644 index 0000000..06d1274 --- /dev/null +++ b/js/node_modules/source-map/lib/mapping-list.js @@ -0,0 +1,79 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var util = require('./util'); + +/** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ +function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; +} + +/** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ +function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; +} + +/** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ +MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + +/** + * Add the given source mapping. + * + * @param Object aMapping + */ +MappingList.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } +}; + +/** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ +MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; +}; + +exports.MappingList = MappingList; diff --git a/js/node_modules/source-map/lib/quick-sort.js b/js/node_modules/source-map/lib/quick-sort.js new file mode 100644 index 0000000..6a7caad --- /dev/null +++ b/js/node_modules/source-map/lib/quick-sort.js @@ -0,0 +1,114 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +// It turns out that some (most?) JavaScript engines don't self-host +// `Array.prototype.sort`. This makes sense because C++ will likely remain +// faster than JS when doing raw CPU-intensive sorting. However, when using a +// custom comparator function, calling back and forth between the VM's C++ and +// JIT'd JS is rather slow *and* loses JIT type information, resulting in +// worse generated code for the comparator function than would be optimal. In +// fact, when sorting with a comparator, these costs outweigh the benefits of +// sorting in C++. By using our own JS-implemented Quick Sort (below), we get +// a ~3500ms mean speed-up in `bench/bench.html`. + +/** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ +function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; +} + +/** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ +function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); +} + +/** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ +function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. + + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. + + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; + + swap(ary, pivotIndex, r); + var pivot = ary[r]; + + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); + } + } + + swap(ary, i + 1, j); + var q = i + 1; + + // (2) Recurse on each half. + + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } +} + +/** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ +exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); +}; diff --git a/js/node_modules/source-map/lib/source-map-consumer.js b/js/node_modules/source-map/lib/source-map-consumer.js new file mode 100644 index 0000000..6abcc28 --- /dev/null +++ b/js/node_modules/source-map/lib/source-map-consumer.js @@ -0,0 +1,1082 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var util = require('./util'); +var binarySearch = require('./binary-search'); +var ArraySet = require('./array-set').ArraySet; +var base64VLQ = require('./base64-vlq'); +var quickSort = require('./quick-sort').quickSort; + +function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); +} + +SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); +} + +/** + * The version of the source mapping spec that we are consuming. + */ +SourceMapConsumer.prototype._version = 3; + +// `__generatedMappings` and `__originalMappings` are arrays that hold the +// parsed mapping coordinates from the source map's "mappings" attribute. They +// are lazily instantiated, accessed via the `_generatedMappings` and +// `_originalMappings` getters respectively, and we only parse the mappings +// and create these arrays once queried for a source location. We jump through +// these hoops because there can be many thousands of mappings, and parsing +// them is expensive, so we only want to do it if we must. +// +// Each object in the arrays is of the form: +// +// { +// generatedLine: The line number in the generated code, +// generatedColumn: The column number in the generated code, +// source: The path to the original source file that generated this +// chunk of code, +// originalLine: The line number in the original source that +// corresponds to this chunk of generated code, +// originalColumn: The column number in the original source that +// corresponds to this chunk of generated code, +// name: The name of the original symbol which generated this chunk of +// code. +// } +// +// All properties except for `generatedLine` and `generatedColumn` can be +// `null`. +// +// `_generatedMappings` is ordered by the generated positions. +// +// `_originalMappings` is ordered by the original positions. + +SourceMapConsumer.prototype.__generatedMappings = null; +Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } +}); + +SourceMapConsumer.prototype.__originalMappings = null; +Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } +}); + +SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; + +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + +SourceMapConsumer.GENERATED_ORDER = 1; +SourceMapConsumer.ORIGINAL_ORDER = 2; + +SourceMapConsumer.GREATEST_LOWER_BOUND = 1; +SourceMapConsumer.LEAST_UPPER_BOUND = 2; + +/** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ +SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; + +/** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; + } + needle.source = this._sources.indexOf(needle.source); + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } + } + + return mappings; + }; + +exports.SourceMapConsumer = SourceMapConsumer; + +/** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ +function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + sources = sources + .map(String) + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) + ? util.relative(sourceRoot, source) + : source; + }); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names.map(String), true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; +} + +BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); +BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; + +/** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer + */ +BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); + } + + destGeneratedMappings.push(destMapping); + } + + quickSort(smc.__originalMappings, util.compareByOriginalPositions); + + return smc; + }; + +/** + * The version of the source mapping spec that we are consuming. + */ +BasicSourceMapConsumer.prototype._version = 3; + +/** + * The list of original sources. + */ +Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } +}); + +/** + * Provide the JIT with a nice shape / hidden class. + */ +function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; +} + +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; + } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + str = aStr.slice(index, end); + + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + cachedSegments[str] = segment; + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } + } + } + + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; + + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; + }; + +/** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ +BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; + +/** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ +BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + +/** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ +BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + +/** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ +BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; + +/** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ +BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + +/** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); + } + if (!this._sources.has(source)) { + return { + line: null, + column: null, + lastColumn: null + }; + } + source = this._sources.indexOf(source); + + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + +exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + +/** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ +function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); + + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); + } + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); + + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) + } + }); +} + +IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); +IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; + +/** + * The version of the source mapping spec that we are consuming. + */ +IndexedSourceMapConsumer.prototype._version = 3; + +/** + * The list of original sources. + */ +Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); + } + } + return sources; + } +}); + +/** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ +IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + +/** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ +IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + +/** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ +IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + +/** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; + +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[j]; + + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); + } + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.generatedColumn + + (section.generatedOffset.generatedLine === mapping.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; + + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } + } + } + + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; + +exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; diff --git a/js/node_modules/source-map/lib/source-map-generator.js b/js/node_modules/source-map/lib/source-map-generator.js new file mode 100644 index 0000000..aff1e7f --- /dev/null +++ b/js/node_modules/source-map/lib/source-map-generator.js @@ -0,0 +1,416 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var base64VLQ = require('./base64-vlq'); +var util = require('./util'); +var ArraySet = require('./array-set').ArraySet; +var MappingList = require('./mapping-list').MappingList; + +/** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ +function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; +} + +SourceMapGenerator.prototype._version = 3; + +/** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ +SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + +/** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ +SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null) { + source = String(source); + if (!this._sources.has(source)) { + this._sources.add(source); + } + } + + if (name != null) { + name = String(name); + if (!this._names.has(name)) { + this._names.add(name); + } + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + +/** + * Set the source content for a source file. + */ +SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = Object.create(null); + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + +/** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ +SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + +/** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ +SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + // When aOriginal is truthy but has empty values for .line and .column, + // it is most likely a programmer error. In this case we throw a very + // specific error message to try to guide them the right way. + // For example: https://github.com/Polymer/polymer-bundler/pull/519 + if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { + throw new Error( + 'original.line and original.column are not numbers -- you probably meant to omit ' + + 'the original mapping entirely and only map the generated position. If so, pass ' + + 'null for the original mapping instead of an object with empty or null values.' + ); + } + + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + +/** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ +SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var next; + var mapping; + var nameIdx; + var sourceIdx; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + next = '' + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + next += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; + } + next += ','; + } + } + + next += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + next += base64VLQ.encode(sourceIdx - previousSource); + previousSource = sourceIdx; + + // lines are stored 0-based in SourceMap spec version 3 + next += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + next += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + next += base64VLQ.encode(nameIdx - previousName); + previousName = nameIdx; + } + } + + result += next; + } + + return result; + }; + +SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) + ? this._sourcesContents[key] + : null; + }, this); + }; + +/** + * Externalize the source map. + */ +SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + +/** + * Render the source map being generated to a string. + */ +SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; + +exports.SourceMapGenerator = SourceMapGenerator; diff --git a/js/node_modules/source-map/lib/source-node.js b/js/node_modules/source-map/lib/source-node.js new file mode 100644 index 0000000..d196a53 --- /dev/null +++ b/js/node_modules/source-map/lib/source-node.js @@ -0,0 +1,413 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; +var util = require('./util'); + +// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other +// operating systems these days (capturing the result). +var REGEX_NEWLINE = /(\r?\n)/; + +// Newline character code for charCodeAt() comparisons +var NEWLINE_CODE = 10; + +// Private symbol for identifying `SourceNode`s when multiple versions of +// the source-map library are loaded. This MUST NOT CHANGE across +// versions! +var isSourceNode = "$$$isSourceNode$$$"; + +/** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ +function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); +} + +/** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ +SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are accessed by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var remainingLinesIndex = 0; + var shiftNextLine = function() { + var lineContents = getNextLine(); + // The last line of a file might not have a newline. + var newLine = getNextLine() || ""; + return lineContents + newLine; + + function getNextLine() { + return remainingLinesIndex < remainingLines.length ? + remainingLines[remainingLinesIndex++] : undefined; + } + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[remainingLinesIndex]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[remainingLinesIndex]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLinesIndex < remainingLines.length) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.splice(remainingLinesIndex).join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + +/** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ +SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; +}; + +/** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ +SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; +}; + +/** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ +SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } +}; + +/** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ +SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; +}; + +/** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ +SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; +}; + +/** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ +SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + +/** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ +SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + +/** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ +SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; +}; + +/** + * Returns the string representation of this source node along with a source + * map. + */ +SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; +}; + +exports.SourceNode = SourceNode; diff --git a/js/node_modules/source-map/lib/util.js b/js/node_modules/source-map/lib/util.js new file mode 100644 index 0000000..44e0e45 --- /dev/null +++ b/js/node_modules/source-map/lib/util.js @@ -0,0 +1,417 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ +function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } +} +exports.getArg = getArg; + +var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; +var dataUrlRegexp = /^data:.+\,.+$/; + +function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; +} +exports.urlParse = urlParse; + +function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; +} +exports.urlGenerate = urlGenerate; + +/** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consecutive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ +function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; +} +exports.normalize = normalize; + +/** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ +function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; +} +exports.join = join; + +exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); +}; + +/** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ +function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; + } + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; + } + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); +} +exports.relative = relative; + +var supportsNullProto = (function () { + var obj = Object.create(null); + return !('__proto__' in obj); +}()); + +function identity (s) { + return s; +} + +/** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ +function toSetString(aStr) { + if (isProtoString(aStr)) { + return '$' + aStr; + } + + return aStr; +} +exports.toSetString = supportsNullProto ? identity : toSetString; + +function fromSetString(aStr) { + if (isProtoString(aStr)) { + return aStr.slice(1); + } + + return aStr; +} +exports.fromSetString = supportsNullProto ? identity : fromSetString; + +function isProtoString(s) { + if (!s) { + return false; + } + + var length = s.length; + + if (length < 9 /* "__proto__".length */) { + return false; + } + + if (s.charCodeAt(length - 1) !== 95 /* '_' */ || + s.charCodeAt(length - 2) !== 95 /* '_' */ || + s.charCodeAt(length - 3) !== 111 /* 'o' */ || + s.charCodeAt(length - 4) !== 116 /* 't' */ || + s.charCodeAt(length - 5) !== 111 /* 'o' */ || + s.charCodeAt(length - 6) !== 114 /* 'r' */ || + s.charCodeAt(length - 7) !== 112 /* 'p' */ || + s.charCodeAt(length - 8) !== 95 /* '_' */ || + s.charCodeAt(length - 9) !== 95 /* '_' */) { + return false; + } + + for (var i = length - 10; i >= 0; i--) { + if (s.charCodeAt(i) !== 36 /* '$' */) { + return false; + } + } + + return true; +} + +/** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ +function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; +} +exports.compareByOriginalPositions = compareByOriginalPositions; + +/** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ +function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; +} +exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + +function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; +} + +/** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ +function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); +} +exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; diff --git a/js/node_modules/source-map/package.json b/js/node_modules/source-map/package.json new file mode 100644 index 0000000..be9eba3 --- /dev/null +++ b/js/node_modules/source-map/package.json @@ -0,0 +1,211 @@ +{ + "_from": "source-map@^0.5.6", + "_id": "source-map@0.5.7", + "_inBundle": false, + "_integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "_location": "/source-map", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "source-map@^0.5.6", + "name": "source-map", + "escapedName": "source-map", + "rawSpec": "^0.5.6", + "saveSpec": null, + "fetchSpec": "^0.5.6" + }, + "_requiredBy": [ + "/snapdragon" + ], + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "_shasum": "8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc", + "_spec": "source-map@^0.5.6", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/snapdragon", + "author": { + "name": "Nick Fitzgerald", + "email": "nfitzgerald@mozilla.com" + }, + "bugs": { + "url": "https://github.com/mozilla/source-map/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + }, + { + "name": "Chase Douglas", + "email": "chase@newrelic.com" + }, + { + "name": "Evan Wallace", + "email": "evan.exe@gmail.com" + }, + { + "name": "Heather Arthur", + "email": "fayearthur@gmail.com" + }, + { + "name": "Hugh Kennedy", + "email": "hughskennedy@gmail.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + }, + { + "name": "Simon Lydell", + "email": "simon.lydell@gmail.com" + }, + { + "name": "Jmeas Smith", + "email": "jellyes2@gmail.com" + }, + { + "name": "Michael Z Goddard", + "email": "mzgoddard@gmail.com" + }, + { + "name": "azu", + "email": "azu@users.noreply.github.com" + }, + { + "name": "John Gozde", + "email": "john@gozde.ca" + }, + { + "name": "Adam Kirkton", + "email": "akirkton@truefitinnovation.com" + }, + { + "name": "Chris Montgomery", + "email": "christopher.montgomery@dowjones.com" + }, + { + "name": "J. Ryan Stinnett", + "email": "jryans@gmail.com" + }, + { + "name": "Jack Herrington", + "email": "jherrington@walmartlabs.com" + }, + { + "name": "Chris Truter", + "email": "jeffpalentine@gmail.com" + }, + { + "name": "Daniel Espeset", + "email": "daniel@danielespeset.com" + }, + { + "name": "Jamie Wong", + "email": "jamie.lf.wong@gmail.com" + }, + { + "name": "Eddy Bruël", + "email": "ejpbruel@mozilla.com" + }, + { + "name": "Hawken Rives", + "email": "hawkrives@gmail.com" + }, + { + "name": "Gilad Peleg", + "email": "giladp007@gmail.com" + }, + { + "name": "djchie", + "email": "djchie.dev@gmail.com" + }, + { + "name": "Gary Ye", + "email": "garysye@gmail.com" + }, + { + "name": "Nicolas Lalevée", + "email": "nicolas.lalevee@hibnet.org" + } + ], + "deprecated": false, + "description": "Generates and consumes source maps", + "devDependencies": { + "doctoc": "^0.15.0", + "webpack": "^1.12.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "source-map.js", + "lib/", + "dist/source-map.debug.js", + "dist/source-map.js", + "dist/source-map.min.js", + "dist/source-map.min.js.map" + ], + "homepage": "https://github.com/mozilla/source-map", + "license": "BSD-3-Clause", + "main": "./source-map.js", + "name": "source-map", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/mozilla/source-map.git" + }, + "scripts": { + "build": "webpack --color", + "test": "npm run build && node test/run-tests.js", + "toc": "doctoc --title '## Table of Contents' README.md && doctoc --title '## Table of Contents' CONTRIBUTING.md" + }, + "typings": "source-map", + "version": "0.5.7" +} diff --git a/js/node_modules/source-map/source-map.js b/js/node_modules/source-map/source-map.js new file mode 100644 index 0000000..bc88fe8 --- /dev/null +++ b/js/node_modules/source-map/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./lib/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./lib/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./lib/source-node').SourceNode; diff --git a/js/node_modules/split-string/LICENSE b/js/node_modules/split-string/LICENSE new file mode 100644 index 0000000..e33d14b --- /dev/null +++ b/js/node_modules/split-string/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2017, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/split-string/README.md b/js/node_modules/split-string/README.md new file mode 100644 index 0000000..d622e44 --- /dev/null +++ b/js/node_modules/split-string/README.md @@ -0,0 +1,321 @@ +# split-string [![NPM version](https://img.shields.io/npm/v/split-string.svg?style=flat)](https://www.npmjs.com/package/split-string) [![NPM monthly downloads](https://img.shields.io/npm/dm/split-string.svg?style=flat)](https://npmjs.org/package/split-string) [![NPM total downloads](https://img.shields.io/npm/dt/split-string.svg?style=flat)](https://npmjs.org/package/split-string) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/split-string.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/split-string) + +> Split a string on a character except when the character is escaped. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save split-string +``` + + + +
+Why use this? + +
+ +Although it's easy to split on a string: + +```js +console.log('a.b.c'.split('.')); +//=> ['a', 'b', 'c'] +``` + +It's more challenging to split a string whilst respecting escaped or quoted characters. + +**Bad** + +```js +console.log('a\\.b.c'.split('.')); +//=> ['a\\', 'b', 'c'] + +console.log('"a.b.c".d'.split('.')); +//=> ['"a', 'b', 'c"', 'd'] +``` + +**Good** + +```js +var split = require('split-string'); +console.log(split('a\\.b.c')); +//=> ['a.b', 'c'] + +console.log(split('"a.b.c".d')); +//=> ['a.b.c', 'd'] +``` + +See the [options](#options) to learn how to choose the separator or retain quotes or escaping. + +
+ +
+ +## Usage + +```js +var split = require('split-string'); + +split('a.b.c'); +//=> ['a', 'b', 'c'] + +// respects escaped characters +split('a.b.c\\.d'); +//=> ['a', 'b', 'c.d'] + +// respects double-quoted strings +split('a."b.c.d".e'); +//=> ['a', 'b.c.d', 'e'] +``` + +**Brackets** + +Also respects brackets [unless disabled](#optionsbrackets): + +```js +split('a (b c d) e', ' '); +//=> ['a', '(b c d)', 'e'] +``` + +## Options + +### options.brackets + +**Type**: `object|boolean` + +**Default**: `undefined` + +**Description** + +If enabled, split-string will not split inside brackets. The following brackets types are supported when `options.brackets` is `true`, + +```js +{ + '<': '>', + '(': ')', + '[': ']', + '{': '}' +} +``` + +Or, if object of brackets must be passed, each property on the object must be a bracket type, where the property key is the opening delimiter and property value is the closing delimiter. + +**Examples** + +```js +// no bracket support by default +split('a.{b.c}'); +//=> [ 'a', '{b', 'c}' ] + +// support all basic bracket types: "<>{}[]()" +split('a.{b.c}', {brackets: true}); +//=> [ 'a', '{b.c}' ] + +// also supports nested brackets +split('a.{b.{c.d}.e}.f', {brackets: true}); +//=> [ 'a', '{b.{c.d}.e}', 'f' ] + +// support only the specified brackets +split('[a.b].(c.d)', {brackets: {'[': ']'}}); +//=> [ '[a.b]', '(c', 'd)' ] +``` + +### options.sep + +**Type**: `string` + +**Default**: `.` + +The separator/character to split on. + +**Example** + +```js +split('a.b,c', {sep: ','}); +//=> ['a.b', 'c'] + +// you can also pass the separator as string as the last argument +split('a.b,c', ','); +//=> ['a.b', 'c'] +``` + +### options.keepEscaping + +**Type**: `boolean` + +**Default**: `undefined` + +Keep backslashes in the result. + +**Example** + +```js +split('a.b\\.c'); +//=> ['a', 'b.c'] + +split('a.b.\\c', {keepEscaping: true}); +//=> ['a', 'b\.c'] +``` + +### options.keepQuotes + +**Type**: `boolean` + +**Default**: `undefined` + +Keep single- or double-quotes in the result. + +**Example** + +```js +split('a."b.c.d".e'); +//=> ['a', 'b.c.d', 'e'] + +split('a."b.c.d".e', {keepQuotes: true}); +//=> ['a', '"b.c.d"', 'e'] + +split('a.\'b.c.d\'.e', {keepQuotes: true}); +//=> ['a', '\'b.c.d\'', 'e'] +``` + +### options.keepDoubleQuotes + +**Type**: `boolean` + +**Default**: `undefined` + +Keep double-quotes in the result. + +**Example** + +```js +split('a."b.c.d".e'); +//=> ['a', 'b.c.d', 'e'] + +split('a."b.c.d".e', {keepDoubleQuotes: true}); +//=> ['a', '"b.c.d"', 'e'] +``` + +### options.keepSingleQuotes + +**Type**: `boolean` + +**Default**: `undefined` + +Keep single-quotes in the result. + +**Example** + +```js +split('a.\'b.c.d\'.e'); +//=> ['a', 'b.c.d', 'e'] + +split('a.\'b.c.d\'.e', {keepSingleQuotes: true}); +//=> ['a', '\'b.c.d\'', 'e'] +``` + +## Customizer + +**Type**: `function` + +**Default**: `undefined` + +Pass a function as the last argument to customize how tokens are added to the array. + +**Example** + +```js +var arr = split('a.b', function(tok) { + if (tok.arr[tok.arr.length - 1] === 'a') { + tok.split = false; + } +}); +console.log(arr); +//=> ['a.b'] +``` + +**Properties** + +The `tok` object has the following properties: + +* `tok.val` (string) The current value about to be pushed onto the result array +* `tok.idx` (number) the current index in the string +* `tok.str` (string) the entire string +* `tok.arr` (array) the result array + +## Release history + +### v3.0.0 - 2017-06-17 + +**Added** + +* adds support for brackets + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [deromanize](https://www.npmjs.com/package/deromanize): Convert roman numerals to arabic numbers (useful for books, outlines, documentation, slide decks, etc) | [homepage](https://github.com/jonschlinkert/deromanize "Convert roman numerals to arabic numbers (useful for books, outlines, documentation, slide decks, etc)") +* [randomatic](https://www.npmjs.com/package/randomatic): Generate randomized strings of a specified length using simple character sequences. The original generate-password. | [homepage](https://github.com/jonschlinkert/randomatic "Generate randomized strings of a specified length using simple character sequences. The original generate-password.") +* [repeat-string](https://www.npmjs.com/package/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. | [homepage](https://github.com/jonschlinkert/repeat-string "Repeat the given string n times. Fastest implementation for repeating a string.") +* [romanize](https://www.npmjs.com/package/romanize): Convert numbers to roman numerals (useful for books, outlines, documentation, slide decks, etc) | [homepage](https://github.com/jonschlinkert/romanize "Convert numbers to roman numerals (useful for books, outlines, documentation, slide decks, etc)") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 28 | [jonschlinkert](https://github.com/jonschlinkert) | +| 9 | [doowb](https://github.com/doowb) | + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on November 19, 2017._ \ No newline at end of file diff --git a/js/node_modules/split-string/index.js b/js/node_modules/split-string/index.js new file mode 100644 index 0000000..7bc0ea9 --- /dev/null +++ b/js/node_modules/split-string/index.js @@ -0,0 +1,171 @@ +/*! + * split-string + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +var extend = require('extend-shallow'); + +module.exports = function(str, options, fn) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); + } + + if (typeof options === 'function') { + fn = options; + options = null; + } + + // allow separator to be defined as a string + if (typeof options === 'string') { + options = { sep: options }; + } + + var opts = extend({sep: '.'}, options); + var quotes = opts.quotes || ['"', "'", '`']; + var brackets; + + if (opts.brackets === true) { + brackets = { + '<': '>', + '(': ')', + '[': ']', + '{': '}' + }; + } else if (opts.brackets) { + brackets = opts.brackets; + } + + var tokens = []; + var stack = []; + var arr = ['']; + var sep = opts.sep; + var len = str.length; + var idx = -1; + var closeIdx; + + function expected() { + if (brackets && stack.length) { + return brackets[stack[stack.length - 1]]; + } + } + + while (++idx < len) { + var ch = str[idx]; + var next = str[idx + 1]; + var tok = { val: ch, idx: idx, arr: arr, str: str }; + tokens.push(tok); + + if (ch === '\\') { + tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; + tok.escaped = true; + if (typeof fn === 'function') { + fn(tok); + } + arr[arr.length - 1] += tok.val; + idx++; + continue; + } + + if (brackets && brackets[ch]) { + stack.push(ch); + var e = expected(); + var i = idx + 1; + + if (str.indexOf(e, i + 1) !== -1) { + while (stack.length && i < len) { + var s = str[++i]; + if (s === '\\') { + s++; + continue; + } + + if (quotes.indexOf(s) !== -1) { + i = getClosingQuote(str, s, i + 1); + continue; + } + + e = expected(); + if (stack.length && str.indexOf(e, i + 1) === -1) { + break; + } + + if (brackets[s]) { + stack.push(s); + continue; + } + + if (e === s) { + stack.pop(); + } + } + } + + closeIdx = i; + if (closeIdx === -1) { + arr[arr.length - 1] += ch; + continue; + } + + ch = str.slice(idx, closeIdx + 1); + tok.val = ch; + tok.idx = idx = closeIdx; + } + + if (quotes.indexOf(ch) !== -1) { + closeIdx = getClosingQuote(str, ch, idx + 1); + if (closeIdx === -1) { + arr[arr.length - 1] += ch; + continue; + } + + if (keepQuotes(ch, opts) === true) { + ch = str.slice(idx, closeIdx + 1); + } else { + ch = str.slice(idx + 1, closeIdx); + } + + tok.val = ch; + tok.idx = idx = closeIdx; + } + + if (typeof fn === 'function') { + fn(tok, tokens); + ch = tok.val; + idx = tok.idx; + } + + if (tok.val === sep && tok.split !== false) { + arr.push(''); + continue; + } + + arr[arr.length - 1] += tok.val; + } + + return arr; +}; + +function getClosingQuote(str, ch, i, brackets) { + var idx = str.indexOf(ch, i); + if (str.charAt(idx - 1) === '\\') { + return getClosingQuote(str, ch, idx + 1); + } + return idx; +} + +function keepQuotes(ch, opts) { + if (opts.keepDoubleQuotes === true && ch === '"') return true; + if (opts.keepSingleQuotes === true && ch === "'") return true; + return opts.keepQuotes; +} + +function keepEscaping(opts, str, idx) { + if (typeof opts.keepEscaping === 'function') { + return opts.keepEscaping(str, idx); + } + return opts.keepEscaping === true || str[idx + 1] === '\\'; +} diff --git a/js/node_modules/split-string/package.json b/js/node_modules/split-string/package.json new file mode 100644 index 0000000..4b4edab --- /dev/null +++ b/js/node_modules/split-string/package.json @@ -0,0 +1,103 @@ +{ + "_from": "split-string@^3.0.2", + "_id": "split-string@3.1.0", + "_inBundle": false, + "_integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "_location": "/split-string", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "split-string@^3.0.2", + "name": "split-string", + "escapedName": "split-string", + "rawSpec": "^3.0.2", + "saveSpec": null, + "fetchSpec": "^3.0.2" + }, + "_requiredBy": [ + "/findup-sync/braces", + "/set-value" + ], + "_resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "_shasum": "7cb09dda3a86585705c64b39a6466038682e8fe2", + "_spec": "split-string@^3.0.2", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/findup-sync/node_modules/braces", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/split-string/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Brian Woodward", + "url": "https://twitter.com/doowb" + }, + { + "name": "Jon Schlinkert", + "url": "http://twitter.com/jonschlinkert" + } + ], + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "deprecated": false, + "description": "Split a string on a character except when the character is escaped.", + "devDependencies": { + "gulp-format-md": "^1.0.0", + "mocha": "^3.5.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/split-string", + "keywords": [ + "character", + "escape", + "split", + "string" + ], + "license": "MIT", + "main": "index.js", + "name": "split-string", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/split-string.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "titles": [ + ".", + "install", + "Why use this?" + ], + "related": { + "list": [ + "deromanize", + "randomatic", + "repeat-string", + "romanize" + ] + }, + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + } + }, + "version": "3.1.0" +} diff --git a/js/node_modules/static-extend/LICENSE b/js/node_modules/static-extend/LICENSE new file mode 100644 index 0000000..e28e603 --- /dev/null +++ b/js/node_modules/static-extend/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/static-extend/index.js b/js/node_modules/static-extend/index.js new file mode 100644 index 0000000..f4124b2 --- /dev/null +++ b/js/node_modules/static-extend/index.js @@ -0,0 +1,90 @@ +/*! + * static-extend + * + * Copyright (c) 2016, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var copy = require('object-copy'); +var define = require('define-property'); +var util = require('util'); + +/** + * Returns a function for extending the static properties, + * prototype properties, and descriptors from the `Parent` + * constructor onto `Child` constructors. + * + * ```js + * var extend = require('static-extend'); + * Parent.extend = extend(Parent); + * + * // optionally pass a custom merge function as the second arg + * Parent.extend = extend(Parent, function(Child) { + * Child.prototype.mixin = function(key, val) { + * Child.prototype[key] = val; + * }; + * }); + * + * // extend "child" constructors + * Parent.extend(Child); + * + * // optionally define prototype methods as the second arg + * Parent.extend(Child, { + * foo: function() {}, + * bar: function() {} + * }); + * ``` + * @param {Function} `Parent` Parent ctor + * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. + * @param {Function} `Child` Child ctor + * @param {Object} `proto` Optionally pass additional prototype properties to inherit. + * @return {Object} + * @api public + */ + +function extend(Parent, extendFn) { + if (typeof Parent !== 'function') { + throw new TypeError('expected Parent to be a function.'); + } + + return function(Ctor, proto) { + if (typeof Ctor !== 'function') { + throw new TypeError('expected Ctor to be a function.'); + } + + util.inherits(Ctor, Parent); + copy(Ctor, Parent); + + // proto can be null or a plain object + if (typeof proto === 'object') { + var obj = Object.create(proto); + + for (var k in obj) { + Ctor.prototype[k] = obj[k]; + } + } + + // keep a reference to the parent prototype + define(Ctor.prototype, '_parent_', { + configurable: true, + set: function() {}, + get: function() { + return Parent.prototype; + } + }); + + if (typeof extendFn === 'function') { + extendFn(Ctor, Parent); + } + + Ctor.extend = extend(Ctor, extendFn); + }; +}; + +/** + * Expose `extend` + */ + +module.exports = extend; diff --git a/js/node_modules/static-extend/node_modules/define-property/LICENSE b/js/node_modules/static-extend/node_modules/define-property/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/js/node_modules/static-extend/node_modules/define-property/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/static-extend/node_modules/define-property/README.md b/js/node_modules/static-extend/node_modules/define-property/README.md new file mode 100644 index 0000000..8cac698 --- /dev/null +++ b/js/node_modules/static-extend/node_modules/define-property/README.md @@ -0,0 +1,77 @@ +# define-property [![NPM version](https://badge.fury.io/js/define-property.svg)](http://badge.fury.io/js/define-property) + +> Define a non-enumerable property on an object. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i define-property --save +``` + +## Usage + +**Params** + +* `obj`: The object on which to define the property. +* `prop`: The name of the property to be defined or modified. +* `descriptor`: The descriptor for the property being defined or modified. + +```js +var define = require('define-property'); +var obj = {}; +define(obj, 'foo', function(val) { + return val.toUpperCase(); +}); + +console.log(obj); +//=> {} + +console.log(obj.foo('bar')); +//=> 'BAR' +``` + +**get/set** + +```js +define(obj, 'foo', { + get: function() {}, + set: function() {} +}); +``` + +## Related projects + +* [delegate-object](https://www.npmjs.com/package/delegate-object): Copy properties from an object to another object, where properties with function values will be… [more](https://www.npmjs.com/package/delegate-object) | [homepage](https://github.com/doowb/delegate-object) +* [forward-object](https://www.npmjs.com/package/forward-object): Copy properties from an object to another object, where properties with function values will be… [more](https://www.npmjs.com/package/forward-object) | [homepage](https://github.com/doowb/forward-object) +* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep) +* [mixin-object](https://www.npmjs.com/package/mixin-object): Mixin the own and inherited properties of other objects onto the first object. Pass an… [more](https://www.npmjs.com/package/mixin-object) | [homepage](https://github.com/jonschlinkert/mixin-object) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/define-property/issues/new). + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on August 31, 2015._ diff --git a/js/node_modules/static-extend/node_modules/define-property/index.js b/js/node_modules/static-extend/node_modules/define-property/index.js new file mode 100644 index 0000000..3e0e5e1 --- /dev/null +++ b/js/node_modules/static-extend/node_modules/define-property/index.js @@ -0,0 +1,31 @@ +/*! + * define-property + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var isDescriptor = require('is-descriptor'); + +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); + } + + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } + + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); + } + + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); +}; diff --git a/js/node_modules/static-extend/node_modules/define-property/package.json b/js/node_modules/static-extend/node_modules/define-property/package.json new file mode 100644 index 0000000..feeafdf --- /dev/null +++ b/js/node_modules/static-extend/node_modules/define-property/package.json @@ -0,0 +1,82 @@ +{ + "_from": "define-property@^0.2.5", + "_id": "define-property@0.2.5", + "_inBundle": false, + "_integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "_location": "/static-extend/define-property", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "define-property@^0.2.5", + "name": "define-property", + "escapedName": "define-property", + "rawSpec": "^0.2.5", + "saveSpec": null, + "fetchSpec": "^0.2.5" + }, + "_requiredBy": [ + "/static-extend" + ], + "_resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "_shasum": "c35b1ef918ec3c990f9a5bc57be04aacec5c8116", + "_spec": "define-property@^0.2.5", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/static-extend", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/define-property/issues" + }, + "bundleDependencies": false, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "deprecated": false, + "description": "Define a non-enumerable property on an object.", + "devDependencies": { + "mocha": "*", + "should": "^7.0.4" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/define-property", + "keywords": [ + "define", + "define-property", + "enumerable", + "key", + "non", + "non-enumerable", + "object", + "prop", + "property", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "define-property", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/define-property.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "mixin-deep", + "mixin-object", + "delegate-object", + "forward-object" + ] + } + }, + "version": "0.2.5" +} diff --git a/js/node_modules/static-extend/package.json b/js/node_modules/static-extend/package.json new file mode 100644 index 0000000..563de61 --- /dev/null +++ b/js/node_modules/static-extend/package.json @@ -0,0 +1,96 @@ +{ + "_from": "static-extend@^0.1.1", + "_id": "static-extend@0.1.2", + "_inBundle": false, + "_integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "_location": "/static-extend", + "_phantomChildren": { + "is-descriptor": "0.1.6" + }, + "_requested": { + "type": "range", + "registry": true, + "raw": "static-extend@^0.1.1", + "name": "static-extend", + "escapedName": "static-extend", + "rawSpec": "^0.1.1", + "saveSpec": null, + "fetchSpec": "^0.1.1" + }, + "_requiredBy": [ + "/class-utils" + ], + "_resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "_shasum": "60809c39cbff55337226fd5e0b520f341f1fb5c6", + "_spec": "static-extend@^0.1.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/class-utils", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/static-extend/issues" + }, + "bundleDependencies": false, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "deprecated": false, + "description": "Adds a static `extend` method to a class, to simplify inheritance. Extends the static properties, prototype properties, and descriptors from a `Parent` constructor onto `Child` constructors.", + "devDependencies": { + "gulp-format-md": "^0.1.9", + "mocha": "^2.5.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/static-extend", + "keywords": [ + "class", + "ctor", + "descriptor", + "extend", + "extends", + "inherit", + "inheritance", + "merge", + "method", + "prop", + "properties", + "property", + "prototype" + ], + "license": "MIT", + "main": "index.js", + "name": "static-extend", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/static-extend.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "run": true, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "reflinks": [ + "verb", + "verb-readme-generator" + ], + "lint": { + "reflinks": true + } + }, + "version": "0.1.2" +} diff --git a/js/node_modules/string_decoder/.travis.yml b/js/node_modules/string_decoder/.travis.yml new file mode 100644 index 0000000..3347a72 --- /dev/null +++ b/js/node_modules/string_decoder/.travis.yml @@ -0,0 +1,50 @@ +sudo: false +language: node_js +before_install: + - npm install -g npm@2 + - test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g +notifications: + email: false +matrix: + fast_finish: true + include: + - node_js: '0.8' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: '0.10' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: '0.11' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: '0.12' + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 1 + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 2 + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 3 + env: + - TASK=test + - NPM_LEGACY=true + - node_js: 4 + env: TASK=test + - node_js: 5 + env: TASK=test + - node_js: 6 + env: TASK=test + - node_js: 7 + env: TASK=test + - node_js: 8 + env: TASK=test + - node_js: 9 + env: TASK=test diff --git a/js/node_modules/string_decoder/LICENSE b/js/node_modules/string_decoder/LICENSE new file mode 100644 index 0000000..778edb2 --- /dev/null +++ b/js/node_modules/string_decoder/LICENSE @@ -0,0 +1,48 @@ +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + diff --git a/js/node_modules/string_decoder/README.md b/js/node_modules/string_decoder/README.md new file mode 100644 index 0000000..5fd5831 --- /dev/null +++ b/js/node_modules/string_decoder/README.md @@ -0,0 +1,47 @@ +# string_decoder + +***Node-core v8.9.4 string_decoder for userland*** + + +[![NPM](https://nodei.co/npm/string_decoder.png?downloads=true&downloadRank=true)](https://nodei.co/npm/string_decoder/) +[![NPM](https://nodei.co/npm-dl/string_decoder.png?&months=6&height=3)](https://nodei.co/npm/string_decoder/) + + +```bash +npm install --save string_decoder +``` + +***Node-core string_decoder for userland*** + +This package is a mirror of the string_decoder implementation in Node-core. + +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/). + +As of version 1.0.0 **string_decoder** uses semantic versioning. + +## Previous versions + +Previous version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. + +## Update + +The *build/* directory contains a build script that will scrape the source from the [nodejs/node](https://github.com/nodejs/node) repo given a specific Node version. + +## Streams Working Group + +`string_decoder` is maintained by the Streams Working Group, which +oversees the development and maintenance of the Streams API within +Node.js. The responsibilities of the Streams Working Group include: + +* Addressing stream issues on the Node.js issue tracker. +* Authoring and editing stream documentation within the Node.js project. +* Reviewing changes to stream subclasses within the Node.js project. +* Redirecting changes to streams from the Node.js project to this + project. +* Assisting in the implementation of stream providers within Node.js. +* Recommending versions of `readable-stream` to be included in Node.js. +* Messaging about the future of streams to give the community advance + notice of changes. + +See [readable-stream](https://github.com/nodejs/readable-stream) for +more details. diff --git a/js/node_modules/string_decoder/lib/string_decoder.js b/js/node_modules/string_decoder/lib/string_decoder.js new file mode 100644 index 0000000..2e89e63 --- /dev/null +++ b/js/node_modules/string_decoder/lib/string_decoder.js @@ -0,0 +1,296 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var Buffer = require('safe-buffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} \ No newline at end of file diff --git a/js/node_modules/string_decoder/package.json b/js/node_modules/string_decoder/package.json new file mode 100644 index 0000000..bc041fa --- /dev/null +++ b/js/node_modules/string_decoder/package.json @@ -0,0 +1,59 @@ +{ + "_from": "string_decoder@~1.1.1", + "_id": "string_decoder@1.1.1", + "_inBundle": false, + "_integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "_location": "/string_decoder", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "string_decoder@~1.1.1", + "name": "string_decoder", + "escapedName": "string_decoder", + "rawSpec": "~1.1.1", + "saveSpec": null, + "fetchSpec": "~1.1.1" + }, + "_requiredBy": [ + "/readable-stream" + ], + "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "_shasum": "9cf1611ba62685d7030ae9e4ba34149c3af03fc8", + "_spec": "string_decoder@~1.1.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/readable-stream", + "bugs": { + "url": "https://github.com/nodejs/string_decoder/issues" + }, + "bundleDependencies": false, + "dependencies": { + "safe-buffer": "~5.1.0" + }, + "deprecated": false, + "description": "The string_decoder module from Node core", + "devDependencies": { + "babel-polyfill": "^6.23.0", + "core-util-is": "^1.0.2", + "inherits": "^2.0.3", + "tap": "~0.4.8" + }, + "homepage": "https://github.com/nodejs/string_decoder", + "keywords": [ + "string", + "decoder", + "browser", + "browserify" + ], + "license": "MIT", + "main": "lib/string_decoder.js", + "name": "string_decoder", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/string_decoder.git" + }, + "scripts": { + "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js", + "test": "tap test/parallel/*.js && node test/verify-dependencies" + }, + "version": "1.1.1" +} diff --git a/js/node_modules/to-object-path/LICENSE b/js/node_modules/to-object-path/LICENSE new file mode 100644 index 0000000..1e49edf --- /dev/null +++ b/js/node_modules/to-object-path/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/to-object-path/README.md b/js/node_modules/to-object-path/README.md new file mode 100644 index 0000000..7f3cfb1 --- /dev/null +++ b/js/node_modules/to-object-path/README.md @@ -0,0 +1,71 @@ +# to-object-path [![NPM version](https://badge.fury.io/js/to-object-path.svg)](http://badge.fury.io/js/to-object-path) + +> Create an object path from a list or array of strings. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i to-object-path --save +``` + +## Usage + +```js +var toPath = require('to-object-path'); + +toPath('foo', 'bar', 'baz'); +toPath('foo', ['bar', 'baz']); +//=> 'foo.bar.baz' +``` + +Also supports passing an arguments object (without having to slice args): + +```js +function foo() + return toPath(arguments); +} + +foo('foo', 'bar', 'baz'); +foo('foo', ['bar', 'baz']); +//=> 'foo.bar.baz' +``` + +Visit the [example](./example.js) to see how this could be used in an application. + +## Related projects + +* [get-value](https://www.npmjs.com/package/get-value): Use property paths (` a.b.c`) to get a nested value from an object. | [homepage](https://github.com/jonschlinkert/get-value) +* [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://www.npmjs.com/package/has-value) | [homepage](https://github.com/jonschlinkert/has-value) +* [omit-value](https://www.npmjs.com/package/omit-value): Omit properties from an object or deeply nested property of an object using object path… [more](https://www.npmjs.com/package/omit-value) | [homepage](https://github.com/jonschlinkert/omit-value) +* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value) +* [unset-value](https://www.npmjs.com/package/unset-value): Delete nested properties from an object using dot notation. | [homepage](https://github.com/jonschlinkert/unset-value) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/to-object-path/issues/new). + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on October 28, 2015._ \ No newline at end of file diff --git a/js/node_modules/to-object-path/index.js b/js/node_modules/to-object-path/index.js new file mode 100644 index 0000000..489f8f6 --- /dev/null +++ b/js/node_modules/to-object-path/index.js @@ -0,0 +1,33 @@ +/*! + * to-object-path + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var typeOf = require('kind-of'); + +module.exports = function toPath(args) { + if (typeOf(args) !== 'arguments') { + args = arguments; + } + return filter(args).join('.'); +}; + +function filter(arr) { + var len = arr.length; + var idx = -1; + var res = []; + + while (++idx < len) { + var ele = arr[idx]; + if (typeOf(ele) === 'arguments' || Array.isArray(ele)) { + res.push.apply(res, filter(ele)); + } else if (typeof ele === 'string') { + res.push(ele); + } + } + return res; +} diff --git a/js/node_modules/to-object-path/package.json b/js/node_modules/to-object-path/package.json new file mode 100644 index 0000000..bd57ac5 --- /dev/null +++ b/js/node_modules/to-object-path/package.json @@ -0,0 +1,80 @@ +{ + "_from": "to-object-path@^0.3.0", + "_id": "to-object-path@0.3.0", + "_inBundle": false, + "_integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "_location": "/to-object-path", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "to-object-path@^0.3.0", + "name": "to-object-path", + "escapedName": "to-object-path", + "rawSpec": "^0.3.0", + "saveSpec": null, + "fetchSpec": "^0.3.0" + }, + "_requiredBy": [ + "/cache-base", + "/union-value/set-value" + ], + "_resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "_shasum": "297588b7b0e7e0ac08e04e672f85c1f4999e17af", + "_spec": "to-object-path@^0.3.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/cache-base", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/to-object-path/issues" + }, + "bundleDependencies": false, + "dependencies": { + "kind-of": "^3.0.2" + }, + "deprecated": false, + "description": "Create an object path from a list or array of strings.", + "devDependencies": { + "base": "^0.6.7", + "mocha": "*" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/to-object-path", + "keywords": [ + "dot", + "nested", + "notation", + "object", + "path", + "stringify" + ], + "license": "MIT", + "main": "index.js", + "name": "to-object-path", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/to-object-path.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "get-value", + "set-value", + "has-value", + "omit-value", + "unset-value" + ] + } + }, + "version": "0.3.0" +} diff --git a/js/node_modules/to-regex-range/LICENSE b/js/node_modules/to-regex-range/LICENSE new file mode 100644 index 0000000..83b56e7 --- /dev/null +++ b/js/node_modules/to-regex-range/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2017, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/to-regex-range/README.md b/js/node_modules/to-regex-range/README.md new file mode 100644 index 0000000..2763c5a --- /dev/null +++ b/js/node_modules/to-regex-range/README.md @@ -0,0 +1,281 @@ +# to-regex-range [![NPM version](https://img.shields.io/npm/v/to-regex-range.svg?style=flat)](https://www.npmjs.com/package/to-regex-range) [![NPM monthly downloads](https://img.shields.io/npm/dm/to-regex-range.svg?style=flat)](https://npmjs.org/package/to-regex-range) [![NPM total downloads](https://img.shields.io/npm/dt/to-regex-range.svg?style=flat)](https://npmjs.org/package/to-regex-range) [![Linux Build Status](https://img.shields.io/travis/micromatch/to-regex-range.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/to-regex-range) + +> Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save to-regex-range +``` + +Install with [yarn](https://yarnpkg.com): + +```sh +$ yarn add to-regex-range +``` + +
+What does this do? + +
+ +This libary generates the `source` string to be passed to `new RegExp()` for matching a range of numbers. + +**Example** + +```js +var toRegexRange = require('to-regex-range'); +var regex = new RegExp(toRegexRange('15', '95')); +``` + +A string is returned so that you can do whatever you need with it before passing it to `new RegExp()` (like adding `^` or `$` boundaries, defining flags, or combining it another string). + +
+ +
+ +
+Why use this library? + +
+ +### Convenience + +Creating regular expressions for matching numbers gets deceptively complicated pretty fast. + +For example, let's say you need a validation regex for matching part of a user-id, postal code, social security number, tax id, etc: + +* regex for matching `1` => `/1/` (easy enough) +* regex for matching `1` through `5` => `/[1-5]/` (not bad...) +* regex for matching `1` or `5` => `/(1|5)/` (still easy...) +* regex for matching `1` through `50` => `/([1-9]|[1-4][0-9]|50)/` (uh-oh...) +* regex for matching `1` through `55` => `/([1-9]|[1-4][0-9]|5[0-5])/` (no prob, I can do this...) +* regex for matching `1` through `555` => `/([1-9]|[1-9][0-9]|[1-4][0-9]{2}|5[0-4][0-9]|55[0-5])/` (maybe not...) +* regex for matching `0001` through `5555` => `/(0{3}[1-9]|0{2}[1-9][0-9]|0[1-9][0-9]{2}|[1-4][0-9]{3}|5[0-4][0-9]{2}|55[0-4][0-9]|555[0-5])/` (okay, I get the point!) + +The numbers are contrived, but they're also really basic. In the real world you might need to generate a regex on-the-fly for validation. + +**Learn more** + +If you're interested in learning more about [character classes](http://www.regular-expressions.info/charclass.html) and other regex features, I personally have always found [regular-expressions.info](http://www.regular-expressions.info/charclass.html) to be pretty useful. + +### Heavily tested + +As of April 27, 2017, this library runs [2,783,483 test assertions](./test/test.js) against generated regex-ranges to provide brute-force verification that results are indeed correct. + +Tests run in ~870ms on my MacBook Pro, 2.5 GHz Intel Core i7. + +### Highly optimized + +Generated regular expressions are highly optimized: + +* duplicate sequences and character classes are reduced using quantifiers +* smart enough to use `?` conditionals when number(s) or range(s) can be positive or negative +* uses fragment caching to avoid processing the same exact string more than once + +
+ +
+ +## Usage + +Add this library to your javascript application with the following line of code + +```js +var toRegexRange = require('to-regex-range'); +``` + +The main export is a function that takes two integers: the `min` value and `max` value (formatted as strings or numbers). + +```js +var source = toRegexRange('15', '95'); +//=> 1[5-9]|[2-8][0-9]|9[0-5] + +var re = new RegExp('^' + source + '$'); +console.log(re.test('14')); //=> false +console.log(re.test('50')); //=> true +console.log(re.test('94')); //=> true +console.log(re.test('96')); //=> false +``` + +## Options + +### options.capture + +**Type**: `boolean` + +**Deafault**: `undefined` + +Wrap the returned value in parentheses when there is more than one regex condition. Useful when you're dynamically generating ranges. + +```js +console.log(toRegexRange('-10', '10')); +//=> -[1-9]|-?10|[0-9] + +console.log(toRegexRange('-10', '10', {capture: true})); +//=> (-[1-9]|-?10|[0-9]) +``` + +### options.shorthand + +**Type**: `boolean` + +**Deafault**: `undefined` + +Use the regex shorthand for `[0-9]`: + +```js +console.log(toRegexRange('0', '999999')); +//=> [0-9]|[1-9][0-9]{1,5} + +console.log(toRegexRange('0', '999999', {shorthand: true})); +//=> \d|[1-9]\d{1,5} +``` + +### options.relaxZeros + +**Type**: `boolean` + +**Default**: `true` + +This option only applies to **negative zero-padded ranges**. By default, when a negative zero-padded range is defined, the number of leading zeros is relaxed using `-0*`. + +```js +console.log(toRegexRange('-001', '100')); +//=> -0*1|0{2}[0-9]|0[1-9][0-9]|100 + +console.log(toRegexRange('-001', '100', {relaxZeros: false})); +//=> -0{2}1|0{2}[0-9]|0[1-9][0-9]|100 +``` + +
+Why are zeros relaxed for negative zero-padded ranges by default? + +Consider the following. + +```js +var regex = toRegexRange('-001', '100'); +``` + +_Note that `-001` and `100` are both three digits long_. + +In most zero-padding implementations, only a single leading zero is enough to indicate that zero-padding should be applied. Thus, the leading zeros would be "corrected" on the negative range in the example to `-01`, instead of `-001`, to make total length of each string no greater than the length of the largest number in the range (in other words, `-001` is 4 digits, but `100` is only three digits). + +If zeros were not relaxed by default, you might expect the resulting regex of the above pattern to match `-001` - given that it's defined that way in the arguments - _but it wouldn't_. It would, however, match `-01`. This gets even more ambiguous with large ranges, like `-01` to `1000000`. + +Thus, we relax zeros by default to provide a more predictable experience for users. + +
+ +## Examples + +| **Range** | **Result** | **Compile time** | +| --- | --- | --- | +| `toRegexRange('5, 5')` | `5` | _33μs_ | +| `toRegexRange('5, 6')` | `5\|6` | _53μs_ | +| `toRegexRange('29, 51')` | `29\|[34][0-9]\|5[01]` | _699μs_ | +| `toRegexRange('31, 877')` | `3[1-9]\|[4-9][0-9]\|[1-7][0-9]{2}\|8[0-6][0-9]\|87[0-7]` | _711μs_ | +| `toRegexRange('111, 555')` | `11[1-9]\|1[2-9][0-9]\|[2-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _62μs_ | +| `toRegexRange('-10, 10')` | `-[1-9]\|-?10\|[0-9]` | _74μs_ | +| `toRegexRange('-100, -10')` | `-1[0-9]\|-[2-9][0-9]\|-100` | _49μs_ | +| `toRegexRange('-100, 100')` | `-[1-9]\|-?[1-9][0-9]\|-?100\|[0-9]` | _45μs_ | +| `toRegexRange('001, 100')` | `0{2}[1-9]\|0[1-9][0-9]\|100` | _158μs_ | +| `toRegexRange('0010, 1000')` | `0{2}1[0-9]\|0{2}[2-9][0-9]\|0[1-9][0-9]{2}\|1000` | _61μs_ | +| `toRegexRange('1, 2')` | `1\|2` | _10μs_ | +| `toRegexRange('1, 5')` | `[1-5]` | _24μs_ | +| `toRegexRange('1, 10')` | `[1-9]\|10` | _23μs_ | +| `toRegexRange('1, 100')` | `[1-9]\|[1-9][0-9]\|100` | _30μs_ | +| `toRegexRange('1, 1000')` | `[1-9]\|[1-9][0-9]{1,2}\|1000` | _52μs_ | +| `toRegexRange('1, 10000')` | `[1-9]\|[1-9][0-9]{1,3}\|10000` | _47μs_ | +| `toRegexRange('1, 100000')` | `[1-9]\|[1-9][0-9]{1,4}\|100000` | _44μs_ | +| `toRegexRange('1, 1000000')` | `[1-9]\|[1-9][0-9]{1,5}\|1000000` | _49μs_ | +| `toRegexRange('1, 10000000')` | `[1-9]\|[1-9][0-9]{1,6}\|10000000` | _63μs_ | + +## Heads up! + +**Order of arguments** + +When the `min` is larger than the `max`, values will be flipped to create a valid range: + +```js +toRegexRange('51', '29'); +``` + +Is effectively flipped to: + +```js +toRegexRange('29', '51'); +//=> 29|[3-4][0-9]|5[0-1] +``` + +**Steps / increments** + +This library does not support steps (increments). A pr to add support would be welcome. + +## History + +### v2.0.0 - 2017-04-21 + +**New features** + +Adds support for zero-padding! + +### v1.0.0 + +**Optimizations** + +Repeating ranges are now grouped using quantifiers. rocessing time is roughly the same, but the generated regex is much smaller, which should result in faster matching. + +## Attribution + +Inspired by the python library [range-regex](https://github.com/dimka665/range-regex). + +## About + +### Related projects + +* [expand-range](https://www.npmjs.com/package/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See… [more](https://github.com/jonschlinkert/expand-range) | [homepage](https://github.com/jonschlinkert/expand-range "Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See the benchmarks. Used by micromatch.") +* [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`") +* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/jonschlinkert/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") +* [repeat-element](https://www.npmjs.com/package/repeat-element): Create an array by repeating the given value n times. | [homepage](https://github.com/jonschlinkert/repeat-element "Create an array by repeating the given value n times.") +* [repeat-string](https://www.npmjs.com/package/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. | [homepage](https://github.com/jonschlinkert/repeat-string "Repeat the given string n times. Fastest implementation for repeating a string.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on April 27, 2017._ \ No newline at end of file diff --git a/js/node_modules/to-regex-range/index.js b/js/node_modules/to-regex-range/index.js new file mode 100644 index 0000000..7bb5a74 --- /dev/null +++ b/js/node_modules/to-regex-range/index.js @@ -0,0 +1,294 @@ +/*! + * to-regex-range + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +var repeat = require('repeat-string'); +var isNumber = require('is-number'); +var cache = {}; + +function toRegexRange(min, max, options) { + if (isNumber(min) === false) { + throw new RangeError('toRegexRange: first argument is invalid.'); + } + + if (typeof max === 'undefined' || min === max) { + return String(min); + } + + if (isNumber(max) === false) { + throw new RangeError('toRegexRange: second argument is invalid.'); + } + + options = options || {}; + var relax = String(options.relaxZeros); + var shorthand = String(options.shorthand); + var capture = String(options.capture); + var key = min + ':' + max + '=' + relax + shorthand + capture; + if (cache.hasOwnProperty(key)) { + return cache[key].result; + } + + var a = Math.min(min, max); + var b = Math.max(min, max); + + if (Math.abs(a - b) === 1) { + var result = min + '|' + max; + if (options.capture) { + return '(' + result + ')'; + } + return result; + } + + var isPadded = padding(min) || padding(max); + var positives = []; + var negatives = []; + + var tok = {min: min, max: max, a: a, b: b}; + if (isPadded) { + tok.isPadded = isPadded; + tok.maxLen = String(tok.max).length; + } + + if (a < 0) { + var newMin = b < 0 ? Math.abs(b) : 1; + var newMax = Math.abs(a); + negatives = splitToPatterns(newMin, newMax, tok, options); + a = tok.a = 0; + } + + if (b >= 0) { + positives = splitToPatterns(a, b, tok, options); + } + + tok.negatives = negatives; + tok.positives = positives; + tok.result = siftPatterns(negatives, positives, options); + + if (options.capture && (positives.length + negatives.length) > 1) { + tok.result = '(' + tok.result + ')'; + } + + cache[key] = tok; + return tok.result; +} + +function siftPatterns(neg, pos, options) { + var onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + var onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + var intersected = filterPatterns(neg, pos, '-?', true, options) || []; + var subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} + +function splitToRanges(min, max) { + min = Number(min); + max = Number(max); + + var nines = 1; + var stops = [max]; + var stop = +countNines(min, nines); + + while (min <= stop && stop <= max) { + stops = push(stops, stop); + nines += 1; + stop = +countNines(min, nines); + } + + var zeros = 1; + stop = countZeros(max + 1, zeros) - 1; + + while (min < stop && stop <= max) { + stops = push(stops, stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } + + stops.sort(compare); + return stops; +} + +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ + +function rangeToPattern(start, stop, options) { + if (start === stop) { + return {pattern: String(start), digits: []}; + } + + var zipped = zip(String(start), String(stop)); + var len = zipped.length, i = -1; + + var pattern = ''; + var digits = 0; + + while (++i < len) { + var numbers = zipped[i]; + var startDigit = numbers[0]; + var stopDigit = numbers[1]; + + if (startDigit === stopDigit) { + pattern += startDigit; + + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit); + + } else { + digits += 1; + } + } + + if (digits) { + pattern += options.shorthand ? '\\d' : '[0-9]'; + } + + return { pattern: pattern, digits: [digits] }; +} + +function splitToPatterns(min, max, tok, options) { + var ranges = splitToRanges(min, max); + var len = ranges.length; + var idx = -1; + + var tokens = []; + var start = min; + var prev; + + while (++idx < len) { + var range = ranges[idx]; + var obj = rangeToPattern(start, range, options); + var zeros = ''; + + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.digits.length > 1) { + prev.digits.pop(); + } + prev.digits.push(obj.digits[0]); + prev.string = prev.pattern + toQuantifier(prev.digits); + start = range + 1; + continue; + } + + if (tok.isPadded) { + zeros = padZeros(range, tok); + } + + obj.string = zeros + obj.pattern + toQuantifier(obj.digits); + tokens.push(obj); + start = range + 1; + prev = obj; + } + + return tokens; +} + +function filterPatterns(arr, comparison, prefix, intersection, options) { + var res = []; + + for (var i = 0; i < arr.length; i++) { + var tok = arr[i]; + var ele = tok.string; + + if (options.relaxZeros !== false) { + if (prefix === '-' && ele.charAt(0) === '0') { + if (ele.charAt(1) === '{') { + ele = '0*' + ele.replace(/^0\{\d+\}/, ''); + } else { + ele = '0*' + ele.slice(1); + } + } + } + + if (!intersection && !contains(comparison, 'string', ele)) { + res.push(prefix + ele); + } + + if (intersection && contains(comparison, 'string', ele)) { + res.push(prefix + ele); + } + } + return res; +} + +/** + * Zip strings (`for in` can be used on string characters) + */ + +function zip(a, b) { + var arr = []; + for (var ch in a) arr.push([a[ch], b[ch]]); + return arr; +} + +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} + +function push(arr, ele) { + if (arr.indexOf(ele) === -1) arr.push(ele); + return arr; +} + +function contains(arr, key, val) { + for (var i = 0; i < arr.length; i++) { + if (arr[i][key] === val) { + return true; + } + } + return false; +} + +function countNines(min, len) { + return String(min).slice(0, -len) + repeat('9', len); +} + +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} + +function toQuantifier(digits) { + var start = digits[0]; + var stop = digits[1] ? (',' + digits[1]) : ''; + if (!stop && (!start || start === 1)) { + return ''; + } + return '{' + start + stop + '}'; +} + +function toCharacterClass(a, b) { + return '[' + a + ((b - a === 1) ? '' : '-') + b + ']'; +} + +function padding(str) { + return /^-?(0+)\d/.exec(str); +} + +function padZeros(val, tok) { + if (tok.isPadded) { + var diff = Math.abs(tok.maxLen - String(val).length); + switch (diff) { + case 0: + return ''; + case 1: + return '0'; + default: { + return '0{' + diff + '}'; + } + } + } + return val; +} + +/** + * Expose `toRegexRange` + */ + +module.exports = toRegexRange; diff --git a/js/node_modules/to-regex-range/node_modules/is-number/LICENSE b/js/node_modules/to-regex-range/node_modules/is-number/LICENSE new file mode 100644 index 0000000..842218c --- /dev/null +++ b/js/node_modules/to-regex-range/node_modules/is-number/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/to-regex-range/node_modules/is-number/README.md b/js/node_modules/to-regex-range/node_modules/is-number/README.md new file mode 100644 index 0000000..281165d --- /dev/null +++ b/js/node_modules/to-regex-range/node_modules/is-number/README.md @@ -0,0 +1,115 @@ +# is-number [![NPM version](https://img.shields.io/npm/v/is-number.svg?style=flat)](https://www.npmjs.com/package/is-number) [![NPM downloads](https://img.shields.io/npm/dm/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-number.svg?style=flat)](https://travis-ci.org/jonschlinkert/is-number) + +> Returns true if the value is a number. comprehensive tests. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save is-number +``` + +## Usage + +To understand some of the rationale behind the decisions made in this library (and to learn about some oddities of number evaluation in JavaScript), [see this gist](https://gist.github.com/jonschlinkert/e30c70c713da325d0e81). + +```js +var isNumber = require('is-number'); +``` + +### true + +See the [tests](./test.js) for more examples. + +```js +isNumber(5e3) //=> 'true' +isNumber(0xff) //=> 'true' +isNumber(-1.1) //=> 'true' +isNumber(0) //=> 'true' +isNumber(1) //=> 'true' +isNumber(1.1) //=> 'true' +isNumber(10) //=> 'true' +isNumber(10.10) //=> 'true' +isNumber(100) //=> 'true' +isNumber('-1.1') //=> 'true' +isNumber('0') //=> 'true' +isNumber('012') //=> 'true' +isNumber('0xff') //=> 'true' +isNumber('1') //=> 'true' +isNumber('1.1') //=> 'true' +isNumber('10') //=> 'true' +isNumber('10.10') //=> 'true' +isNumber('100') //=> 'true' +isNumber('5e3') //=> 'true' +isNumber(parseInt('012')) //=> 'true' +isNumber(parseFloat('012')) //=> 'true' +``` + +### False + +See the [tests](./test.js) for more examples. + +```js +isNumber('foo') //=> 'false' +isNumber([1]) //=> 'false' +isNumber([]) //=> 'false' +isNumber(function () {}) //=> 'false' +isNumber(Infinity) //=> 'false' +isNumber(NaN) //=> 'false' +isNumber(new Array('abc')) //=> 'false' +isNumber(new Array(2)) //=> 'false' +isNumber(new Buffer('abc')) //=> 'false' +isNumber(null) //=> 'false' +isNumber(undefined) //=> 'false' +isNumber({abc: 'abc'}) //=> 'false' +``` + +## About + +### Related projects + +* [even](https://www.npmjs.com/package/even): Get the even numbered items from an array. | [homepage](https://github.com/jonschlinkert/even "Get the even numbered items from an array.") +* [is-even](https://www.npmjs.com/package/is-even): Return true if the given number is even. | [homepage](https://github.com/jonschlinkert/is-even "Return true if the given number is even.") +* [is-odd](https://www.npmjs.com/package/is-odd): Returns true if the given number is odd. | [homepage](https://github.com/jonschlinkert/is-odd "Returns true if the given number is odd.") +* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive. | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ") +* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.") +* [odd](https://www.npmjs.com/package/odd): Get the odd numbered items from an array. | [homepage](https://github.com/jonschlinkert/odd "Get the odd numbered items from an array.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Building docs + +_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ + +To generate the readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install -g verb verb-generate-readme && verb +``` + +### Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +### License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/is-number/blob/master/LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.30, on September 10, 2016._ \ No newline at end of file diff --git a/js/node_modules/to-regex-range/node_modules/is-number/index.js b/js/node_modules/to-regex-range/node_modules/is-number/index.js new file mode 100644 index 0000000..7a2a45b --- /dev/null +++ b/js/node_modules/to-regex-range/node_modules/is-number/index.js @@ -0,0 +1,22 @@ +/*! + * is-number + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var typeOf = require('kind-of'); + +module.exports = function isNumber(num) { + var type = typeOf(num); + + if (type === 'string') { + if (!num.trim()) return false; + } else if (type !== 'number') { + return false; + } + + return (num - num + 1) >= 0; +}; diff --git a/js/node_modules/to-regex-range/node_modules/is-number/package.json b/js/node_modules/to-regex-range/node_modules/is-number/package.json new file mode 100644 index 0000000..6e11e34 --- /dev/null +++ b/js/node_modules/to-regex-range/node_modules/is-number/package.json @@ -0,0 +1,121 @@ +{ + "_from": "is-number@^3.0.0", + "_id": "is-number@3.0.0", + "_inBundle": false, + "_integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "_location": "/to-regex-range/is-number", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "is-number@^3.0.0", + "name": "is-number", + "escapedName": "is-number", + "rawSpec": "^3.0.0", + "saveSpec": null, + "fetchSpec": "^3.0.0" + }, + "_requiredBy": [ + "/to-regex-range" + ], + "_resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "_shasum": "24fd6201a4782cf50561c810276afc7d12d71195", + "_spec": "is-number@^3.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/to-regex-range", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/is-number/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Charlike Mike Reagent", + "url": "http://www.tunnckocore.tk" + }, + { + "name": "Jon Schlinkert", + "email": "jon.schlinkert@sellside.com", + "url": "http://twitter.com/jonschlinkert" + } + ], + "dependencies": { + "kind-of": "^3.0.2" + }, + "deprecated": false, + "description": "Returns true if the value is a number. comprehensive tests.", + "devDependencies": { + "benchmarked": "^0.2.5", + "chalk": "^1.1.3", + "gulp-format-md": "^0.1.10", + "mocha": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/is-number", + "keywords": [ + "check", + "coerce", + "coercion", + "integer", + "is", + "is-nan", + "is-num", + "is-number", + "istype", + "kind", + "math", + "nan", + "num", + "number", + "numeric", + "test", + "type", + "typeof", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "is-number", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/is-number.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "even", + "is-even", + "is-odd", + "is-primitive", + "kind-of", + "odd" + ] + }, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "reflinks": [ + "verb", + "verb-generate-readme" + ] + }, + "version": "3.0.0" +} diff --git a/js/node_modules/to-regex-range/package.json b/js/node_modules/to-regex-range/package.json new file mode 100644 index 0000000..e83a1a5 --- /dev/null +++ b/js/node_modules/to-regex-range/package.json @@ -0,0 +1,119 @@ +{ + "_from": "to-regex-range@^2.1.0", + "_id": "to-regex-range@2.1.1", + "_inBundle": false, + "_integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "_location": "/to-regex-range", + "_phantomChildren": { + "kind-of": "3.2.2" + }, + "_requested": { + "type": "range", + "registry": true, + "raw": "to-regex-range@^2.1.0", + "name": "to-regex-range", + "escapedName": "to-regex-range", + "rawSpec": "^2.1.0", + "saveSpec": null, + "fetchSpec": "^2.1.0" + }, + "_requiredBy": [ + "/findup-sync/fill-range" + ], + "_resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "_shasum": "7c80c17b9dfebe599e27367e0d4dd5590141db38", + "_spec": "to-regex-range@^2.1.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/findup-sync/node_modules/fill-range", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/micromatch/to-regex-range/issues" + }, + "bundleDependencies": false, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "deprecated": false, + "description": "Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions.", + "devDependencies": { + "fill-range": "^3.1.1", + "gulp-format-md": "^0.1.12", + "mocha": "^3.2.0", + "text-table": "^0.2.0", + "time-diff": "^0.3.1" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/micromatch/to-regex-range", + "keywords": [ + "alpha", + "alphabetical", + "bash", + "brace", + "date", + "expand", + "expansion", + "glob", + "match", + "matches", + "matching", + "number", + "numerical", + "range", + "ranges", + "regex", + "sequence", + "sh", + "to", + "year" + ], + "license": "MIT", + "main": "index.js", + "name": "to-regex-range", + "repository": { + "type": "git", + "url": "git+https://github.com/micromatch/to-regex-range.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "expand-range", + "fill-range", + "micromatch", + "repeat-element", + "repeat-string" + ] + }, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "helpers": [ + "./examples.js" + ], + "reflinks": [ + "0-5", + "0-9", + "1-5", + "1-9" + ] + }, + "version": "2.1.1" +} diff --git a/js/node_modules/to-regex/LICENSE b/js/node_modules/to-regex/LICENSE new file mode 100644 index 0000000..7c9987b --- /dev/null +++ b/js/node_modules/to-regex/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2018, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/to-regex/README.md b/js/node_modules/to-regex/README.md new file mode 100644 index 0000000..5a28fc3 --- /dev/null +++ b/js/node_modules/to-regex/README.md @@ -0,0 +1,205 @@ +# to-regex [![NPM version](https://img.shields.io/npm/v/to-regex.svg?style=flat)](https://www.npmjs.com/package/to-regex) [![NPM monthly downloads](https://img.shields.io/npm/dm/to-regex.svg?style=flat)](https://npmjs.org/package/to-regex) [![NPM total downloads](https://img.shields.io/npm/dt/to-regex.svg?style=flat)](https://npmjs.org/package/to-regex) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/to-regex.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/to-regex) + +> Generate a regex from a string or array of strings. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +- [Install](#install) +- [Usage](#usage) +- [Options](#options) + * [options.contains](#optionscontains) + * [options.negate](#optionsnegate) + * [options.nocase](#optionsnocase) + * [options.flags](#optionsflags) + * [options.cache](#optionscache) + * [options.safe](#optionssafe) +- [About](#about) + * [Related projects](#related-projects) + * [Author](#author) + * [License](#license) + +_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_ + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save to-regex +``` + +## Usage + +```js +var toRegex = require('to-regex'); + +console.log(toRegex('foo')); +//=> /^(?:foo)$/ + +console.log(toRegex('foo', {negate: true})); +//=> /^(?:(?:(?!^(?:foo)$).)*)$/ + +console.log(toRegex('foo', {contains: true})); +//=> /(?:foo)/ + +console.log(toRegex(['foo', 'bar'], {negate: true})); +//=> /^(?:(?:(?!^(?:(?:foo)|(?:bar))$).)*)$/ + +console.log(toRegex(['foo', 'bar'], {negate: true, contains: true})); +//=> /^(?:(?:(?!(?:(?:foo)|(?:bar))).)*)$/ +``` + +## Options + +### options.contains + +**Type**: `Boolean` + +**Default**: `undefined` + +Generate a regex that will match any string that _contains_ the given pattern. By default, regex is strict will only return true for exact matches. + +```js +var toRegex = require('to-regex'); +console.log(toRegex('foo', {contains: true})); +//=> /(?:foo)/ +``` + +### options.negate + +**Type**: `Boolean` + +**Default**: `undefined` + +Create a regex that will match everything except the given pattern. + +```js +var toRegex = require('to-regex'); +console.log(toRegex('foo', {negate: true})); +//=> /^(?:(?:(?!^(?:foo)$).)*)$/ +``` + +### options.nocase + +**Type**: `Boolean` + +**Default**: `undefined` + +Adds the `i` flag, to enable case-insensitive matching. + +```js +var toRegex = require('to-regex'); +console.log(toRegex('foo', {nocase: true})); +//=> /^(?:foo)$/i +``` + +Alternatively you can pass the flags you want directly on [options.flags](#options.flags). + +### options.flags + +**Type**: `String` + +**Default**: `undefined` + +Define the flags you want to use on the generated regex. + +```js +var toRegex = require('to-regex'); +console.log(toRegex('foo', {flags: 'gm'})); +//=> /^(?:foo)$/gm +console.log(toRegex('foo', {flags: 'gmi', nocase: true})); //<= handles redundancy +//=> /^(?:foo)$/gmi +``` + +### options.cache + +**Type**: `Boolean` + +**Default**: `true` + +Generated regex is cached based on the provided string and options. As a result, runtime compilation only happens once per pattern (as long as options are also the same), which can result in dramatic speed improvements. + +This also helps with debugging, since adding options and pattern are added to the generated regex. + +**Disable caching** + +```js +toRegex('foo', {cache: false}); +``` + +### options.safe + +**Type**: `Boolean` + +**Default**: `undefined` + +Check the generated regular expression with [safe-regex](https://github.com/substack/safe-regex) and throw an error if the regex is potentially unsafe. + +**Examples** + +```js +console.log(toRegex('(x+x+)+y')); +//=> /^(?:(x+x+)+y)$/ + +// The following would throw an error +toRegex('(x+x+)+y', {safe: true}); +``` + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [has-glob](https://www.npmjs.com/package/has-glob): Returns `true` if an array has a glob pattern. | [homepage](https://github.com/jonschlinkert/has-glob "Returns `true` if an array has a glob pattern.") +* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet") +* [path-regex](https://www.npmjs.com/package/path-regex): Regular expression for matching the parts of a file path. | [homepage](https://github.com/regexps/path-regex "Regular expression for matching the parts of a file path.") +* [to-regex-range](https://www.npmjs.com/package/to-regex-range): Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than… [more](https://github.com/micromatch/to-regex-range) | [homepage](https://github.com/micromatch/to-regex-range "Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions.") + +### Author + +**Jon Schlinkert** + +* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert) +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on February 24, 2018._ \ No newline at end of file diff --git a/js/node_modules/to-regex/index.js b/js/node_modules/to-regex/index.js new file mode 100644 index 0000000..a87d015 --- /dev/null +++ b/js/node_modules/to-regex/index.js @@ -0,0 +1,155 @@ +'use strict'; + +var safe = require('safe-regex'); +var define = require('define-property'); +var extend = require('extend-shallow'); +var not = require('regex-not'); +var MAX_LENGTH = 1024 * 64; + +/** + * Session cache + */ + +var cache = {}; + +/** + * Create a regular expression from the given `pattern` string. + * + * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. + * @param {Object} `options` + * @return {RegExp} + * @api public + */ + +module.exports = function(patterns, options) { + if (!Array.isArray(patterns)) { + return makeRe(patterns, options); + } + return makeRe(patterns.join('|'), options); +}; + +/** + * Create a regular expression from the given `pattern` string. + * + * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. + * @param {Object} `options` + * @return {RegExp} + * @api public + */ + +function makeRe(pattern, options) { + if (pattern instanceof RegExp) { + return pattern; + } + + if (typeof pattern !== 'string') { + throw new TypeError('expected a string'); + } + + if (pattern.length > MAX_LENGTH) { + throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); + } + + var key = pattern; + // do this before shallow cloning options, it's a lot faster + if (!options || (options && options.cache !== false)) { + key = createKey(pattern, options); + + if (cache.hasOwnProperty(key)) { + return cache[key]; + } + } + + var opts = extend({}, options); + if (opts.contains === true) { + if (opts.negate === true) { + opts.strictNegate = false; + } else { + opts.strict = false; + } + } + + if (opts.strict === false) { + opts.strictOpen = false; + opts.strictClose = false; + } + + var open = opts.strictOpen !== false ? '^' : ''; + var close = opts.strictClose !== false ? '$' : ''; + var flags = opts.flags || ''; + var regex; + + if (opts.nocase === true && !/i/.test(flags)) { + flags += 'i'; + } + + try { + if (opts.negate || typeof opts.strictNegate === 'boolean') { + pattern = not.create(pattern, opts); + } + + var str = open + '(?:' + pattern + ')' + close; + regex = new RegExp(str, flags); + + if (opts.safe === true && safe(regex) === false) { + throw new Error('potentially unsafe regular expression: ' + regex.source); + } + + } catch (err) { + if (opts.strictErrors === true || opts.safe === true) { + err.key = key; + err.pattern = pattern; + err.originalOptions = options; + err.createdOptions = opts; + throw err; + } + + try { + regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$'); + } catch (err) { + regex = /.^/; //<= match nothing + } + } + + if (opts.cache !== false) { + memoize(regex, key, pattern, opts); + } + return regex; +} + +/** + * Memoize generated regex. This can result in dramatic speed improvements + * and simplify debugging by adding options and pattern to the regex. It can be + * disabled by passing setting `options.cache` to false. + */ + +function memoize(regex, key, pattern, options) { + define(regex, 'cached', true); + define(regex, 'pattern', pattern); + define(regex, 'options', options); + define(regex, 'key', key); + cache[key] = regex; +} + +/** + * Create the key to use for memoization. The key is generated + * by iterating over the options and concatenating key-value pairs + * to the pattern string. + */ + +function createKey(pattern, options) { + if (!options) return pattern; + var key = pattern; + for (var prop in options) { + if (options.hasOwnProperty(prop)) { + key += ';' + prop + '=' + String(options[prop]); + } + } + return key; +} + +/** + * Expose `makeRe` + */ + +module.exports.makeRe = makeRe; diff --git a/js/node_modules/to-regex/package.json b/js/node_modules/to-regex/package.json new file mode 100644 index 0000000..994d0e3 --- /dev/null +++ b/js/node_modules/to-regex/package.json @@ -0,0 +1,97 @@ +{ + "_from": "to-regex@^3.0.2", + "_id": "to-regex@3.0.2", + "_inBundle": false, + "_integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "_location": "/to-regex", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "to-regex@^3.0.2", + "name": "to-regex", + "escapedName": "to-regex", + "rawSpec": "^3.0.2", + "saveSpec": null, + "fetchSpec": "^3.0.2" + }, + "_requiredBy": [ + "/findup-sync/braces", + "/findup-sync/expand-brackets", + "/findup-sync/extglob", + "/findup-sync/micromatch", + "/nanomatch" + ], + "_resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "_shasum": "13cfdd9b336552f30b51f33a8ae1b42a7a7599ce", + "_spec": "to-regex@^3.0.2", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/findup-sync/node_modules/micromatch", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/to-regex/issues" + }, + "bundleDependencies": false, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "deprecated": false, + "description": "Generate a regex from a string or array of strings.", + "devDependencies": { + "gulp-format-md": "^1.0.0", + "mocha": "^3.5.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/to-regex", + "keywords": [ + "match", + "regex", + "regular expression", + "test", + "to" + ], + "license": "MIT", + "main": "index.js", + "name": "to-regex", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/to-regex.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": { + "method": "preWrite" + }, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "has-glob", + "is-glob", + "path-regex", + "to-regex-range" + ] + }, + "lint": { + "reflinks": true + } + }, + "version": "3.0.2" +} diff --git a/js/node_modules/union-value/LICENSE b/js/node_modules/union-value/LICENSE new file mode 100644 index 0000000..83b56e7 --- /dev/null +++ b/js/node_modules/union-value/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2017, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/union-value/README.md b/js/node_modules/union-value/README.md new file mode 100644 index 0000000..1a90ffb --- /dev/null +++ b/js/node_modules/union-value/README.md @@ -0,0 +1,73 @@ +# union-value [![NPM version](https://img.shields.io/npm/v/union-value.svg?style=flat)](https://www.npmjs.com/package/union-value) [![NPM monthly downloads](https://img.shields.io/npm/dm/union-value.svg?style=flat)](https://npmjs.org/package/union-value) [![NPM total downloads](https://img.shields.io/npm/dt/union-value.svg?style=flat)](https://npmjs.org/package/union-value) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/union-value.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/union-value) + +> Set an array of unique values as the property of an object. Supports setting deeply nested properties using using object-paths/dot notation. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save union-value +``` + +## Usage + +```js +var union = require('union-value'); + +var obj = {}; + +union(obj, 'a.b.c', ['one', 'two']); +union(obj, 'a.b.c', ['three']); + +console.log(obj); +//=> {a: {b: {c: [ 'one', 'two', 'three' ] }}} +``` + +## About + +### Related projects + +* [assign-value](https://www.npmjs.com/package/assign-value): Assign a value or extend a deeply nested property of an object using object path… [more](https://github.com/jonschlinkert/assign-value) | [homepage](https://github.com/jonschlinkert/assign-value "Assign a value or extend a deeply nested property of an object using object path notation.") +* [get-value](https://www.npmjs.com/package/get-value): Use property paths (`a.b.c`) to get a nested value from an object. | [homepage](https://github.com/jonschlinkert/get-value "Use property paths (`a.b.c`) to get a nested value from an object.") +* [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://github.com/jonschlinkert/has-value) | [homepage](https://github.com/jonschlinkert/has-value "Returns true if a value exists, false if empty. Works with deeply nested values using object paths.") +* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.") +* [unset-value](https://www.npmjs.com/package/unset-value): Delete nested properties from an object using dot notation. | [homepage](https://github.com/jonschlinkert/unset-value "Delete nested properties from an object using dot notation.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 25, 2017._ \ No newline at end of file diff --git a/js/node_modules/union-value/index.js b/js/node_modules/union-value/index.js new file mode 100644 index 0000000..9c5d8db --- /dev/null +++ b/js/node_modules/union-value/index.js @@ -0,0 +1,30 @@ +'use strict'; + +var isObject = require('is-extendable'); +var union = require('arr-union'); +var get = require('get-value'); +var set = require('set-value'); + +module.exports = function unionValue(obj, prop, value) { + if (!isObject(obj)) { + throw new TypeError('union-value expects the first argument to be an object.'); + } + + if (typeof prop !== 'string') { + throw new TypeError('union-value expects `prop` to be a string.'); + } + + var arr = arrayify(get(obj, prop)); + set(obj, prop, union(arr, arrayify(value))); + return obj; +}; + +function arrayify(val) { + if (val === null || typeof val === 'undefined') { + return []; + } + if (Array.isArray(val)) { + return val; + } + return [val]; +} diff --git a/js/node_modules/union-value/node_modules/extend-shallow/LICENSE b/js/node_modules/union-value/node_modules/extend-shallow/LICENSE new file mode 100644 index 0000000..fa30c4c --- /dev/null +++ b/js/node_modules/union-value/node_modules/extend-shallow/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/union-value/node_modules/extend-shallow/README.md b/js/node_modules/union-value/node_modules/extend-shallow/README.md new file mode 100644 index 0000000..cdc45d4 --- /dev/null +++ b/js/node_modules/union-value/node_modules/extend-shallow/README.md @@ -0,0 +1,61 @@ +# extend-shallow [![NPM version](https://badge.fury.io/js/extend-shallow.svg)](http://badge.fury.io/js/extend-shallow) [![Build Status](https://travis-ci.org/jonschlinkert/extend-shallow.svg)](https://travis-ci.org/jonschlinkert/extend-shallow) + +> Extend an object with the properties of additional objects. node.js/javascript util. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i extend-shallow --save +``` + +## Usage + +```js +var extend = require('extend-shallow'); + +extend({a: 'b'}, {c: 'd'}) +//=> {a: 'b', c: 'd'} +``` + +Pass an empty object to shallow clone: + +```js +var obj = {}; +extend(obj, {a: 'b'}, {c: 'd'}) +//=> {a: 'b', c: 'd'} +``` + +## Related + +* [extend-shallow](https://github.com/jonschlinkert/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. +* [for-own](https://github.com/jonschlinkert/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own) +* [for-in](https://github.com/jonschlinkert/for-in): Iterate over the own and inherited enumerable properties of an objecte, and return an object… [more](https://github.com/jonschlinkert/for-in) +* [is-plain-object](https://github.com/jonschlinkert/is-plain-object): Returns true if an object was created by the `Object` constructor. +* [isobject](https://github.com/jonschlinkert/isobject): Returns true if the value is an object and not an array or null. +* [kind-of](https://github.com/jonschlinkert/kind-of): Get the native type of a value. + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 29, 2015._ \ No newline at end of file diff --git a/js/node_modules/union-value/node_modules/extend-shallow/index.js b/js/node_modules/union-value/node_modules/extend-shallow/index.js new file mode 100644 index 0000000..92a067f --- /dev/null +++ b/js/node_modules/union-value/node_modules/extend-shallow/index.js @@ -0,0 +1,33 @@ +'use strict'; + +var isObject = require('is-extendable'); + +module.exports = function extend(o/*, objects*/) { + if (!isObject(o)) { o = {}; } + + var len = arguments.length; + for (var i = 1; i < len; i++) { + var obj = arguments[i]; + + if (isObject(obj)) { + assign(o, obj); + } + } + return o; +}; + +function assign(a, b) { + for (var key in b) { + if (hasOwn(b, key)) { + a[key] = b[key]; + } + } +} + +/** + * Returns true if the given `key` is an own property of `obj`. + */ + +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} diff --git a/js/node_modules/union-value/node_modules/extend-shallow/package.json b/js/node_modules/union-value/node_modules/extend-shallow/package.json new file mode 100644 index 0000000..d89756a --- /dev/null +++ b/js/node_modules/union-value/node_modules/extend-shallow/package.json @@ -0,0 +1,87 @@ +{ + "_from": "extend-shallow@^2.0.1", + "_id": "extend-shallow@2.0.1", + "_inBundle": false, + "_integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "_location": "/union-value/extend-shallow", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "extend-shallow@^2.0.1", + "name": "extend-shallow", + "escapedName": "extend-shallow", + "rawSpec": "^2.0.1", + "saveSpec": null, + "fetchSpec": "^2.0.1" + }, + "_requiredBy": [ + "/union-value/set-value" + ], + "_resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "_shasum": "51af7d614ad9a9f610ea1bafbb989d6b1c56890f", + "_spec": "extend-shallow@^2.0.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/union-value/node_modules/set-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/extend-shallow/issues" + }, + "bundleDependencies": false, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "deprecated": false, + "description": "Extend an object with the properties of additional objects. node.js/javascript util.", + "devDependencies": { + "array-slice": "^0.2.3", + "benchmarked": "^0.1.4", + "chalk": "^1.0.0", + "for-own": "^0.1.3", + "glob": "^5.0.12", + "is-plain-object": "^2.0.1", + "kind-of": "^2.0.0", + "minimist": "^1.1.1", + "mocha": "^2.2.5", + "should": "^7.0.1" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/extend-shallow", + "keywords": [ + "assign", + "extend", + "javascript", + "js", + "keys", + "merge", + "obj", + "object", + "prop", + "properties", + "property", + "props", + "shallow", + "util", + "utility", + "utils", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "extend-shallow", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/extend-shallow.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "2.0.1" +} diff --git a/js/node_modules/union-value/node_modules/set-value/LICENSE b/js/node_modules/union-value/node_modules/set-value/LICENSE new file mode 100644 index 0000000..d734237 --- /dev/null +++ b/js/node_modules/union-value/node_modules/set-value/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/union-value/node_modules/set-value/README.md b/js/node_modules/union-value/node_modules/set-value/README.md new file mode 100644 index 0000000..19fbdbb --- /dev/null +++ b/js/node_modules/union-value/node_modules/set-value/README.md @@ -0,0 +1,81 @@ +# set-value [![NPM version](https://img.shields.io/npm/v/set-value.svg?style=flat)](https://www.npmjs.com/package/set-value) [![NPM monthly downloads](https://img.shields.io/npm/dm/set-value.svg?style=flat)](https://npmjs.org/package/set-value) [![NPM total downloads](https://img.shields.io/npm/dt/set-value.svg?style=flat)](https://npmjs.org/package/set-value) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/set-value.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/set-value) + +> Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save set-value +``` + +## Usage + +```js +var set = require('set-value'); + +var obj = {}; +set(obj, 'a.b.c', 'd'); +console.log(obj); +//=> {a: {b: c: 'd'}} +``` + +## About + +### Related projects + +* [assign-value](https://www.npmjs.com/package/assign-value): Assign a value or extend a deeply nested property of an object using object path… [more](https://github.com/jonschlinkert/assign-value) | [homepage](https://github.com/jonschlinkert/assign-value "Assign a value or extend a deeply nested property of an object using object path notation.") +* [get-value](https://www.npmjs.com/package/get-value): Use property paths (`a.b.c`) to get a nested value from an object. | [homepage](https://github.com/jonschlinkert/get-value "Use property paths (`a.b.c`) to get a nested value from an object.") +* [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://github.com/jonschlinkert/has-value) | [homepage](https://github.com/jonschlinkert/has-value "Returns true if a value exists, false if empty. Works with deeply nested values using object paths.") +* [merge-value](https://www.npmjs.com/package/merge-value): Similar to assign-value but deeply merges object values or nested values using object path/dot notation. | [homepage](https://github.com/jonschlinkert/merge-value "Similar to assign-value but deeply merges object values or nested values using object path/dot notation.") +* [omit-value](https://www.npmjs.com/package/omit-value): Omit properties from an object or deeply nested property of an object using object path… [more](https://github.com/jonschlinkert/omit-value) | [homepage](https://github.com/jonschlinkert/omit-value "Omit properties from an object or deeply nested property of an object using object path notation.") +* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.") +* [union-value](https://www.npmjs.com/package/union-value): Set an array of unique values as the property of an object. Supports setting deeply… [more](https://github.com/jonschlinkert/union-value) | [homepage](https://github.com/jonschlinkert/union-value "Set an array of unique values as the property of an object. Supports setting deeply nested properties using using object-paths/dot notation.") +* [unset-value](https://www.npmjs.com/package/unset-value): Delete nested properties from an object using dot notation. | [homepage](https://github.com/jonschlinkert/unset-value "Delete nested properties from an object using dot notation.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 53 | [jonschlinkert](https://github.com/jonschlinkert) | +| 1 | [vadimdemedes](https://github.com/vadimdemedes) | +| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) | + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 22, 2017._ \ No newline at end of file diff --git a/js/node_modules/union-value/node_modules/set-value/index.js b/js/node_modules/union-value/node_modules/set-value/index.js new file mode 100644 index 0000000..e51ece5 --- /dev/null +++ b/js/node_modules/union-value/node_modules/set-value/index.js @@ -0,0 +1,63 @@ +/*! + * set-value + * + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +var toPath = require('to-object-path'); +var extend = require('extend-shallow'); +var isPlainObject = require('is-plain-object'); +var isObject = require('is-extendable'); + +module.exports = function(obj, path, val) { + if (!isObject(obj)) { + return obj; + } + + if (Array.isArray(path)) { + path = toPath(path); + } + + if (typeof path !== 'string') { + return obj; + } + + var segs = path.split('.'); + var len = segs.length, i = -1; + var res = obj; + var last; + + while (++i < len) { + var key = segs[i]; + + while (key[key.length - 1] === '\\') { + key = key.slice(0, -1) + '.' + segs[++i]; + } + + if (i === len - 1) { + last = key; + break; + } + + if (!isObject(obj[key])) { + obj[key] = {}; + } + obj = obj[key]; + } + + if (obj.hasOwnProperty(last) && isObject(obj[last])) { + if (isPlainObject(val)) { + extend(obj[last], val); + } else { + obj[last] = val; + } + + } else { + obj[last] = val; + } + return res; +}; + diff --git a/js/node_modules/union-value/node_modules/set-value/package.json b/js/node_modules/union-value/node_modules/set-value/package.json new file mode 100644 index 0000000..effbc98 --- /dev/null +++ b/js/node_modules/union-value/node_modules/set-value/package.json @@ -0,0 +1,121 @@ +{ + "_from": "set-value@^0.4.3", + "_id": "set-value@0.4.3", + "_inBundle": false, + "_integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "_location": "/union-value/set-value", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "set-value@^0.4.3", + "name": "set-value", + "escapedName": "set-value", + "rawSpec": "^0.4.3", + "saveSpec": null, + "fetchSpec": "^0.4.3" + }, + "_requiredBy": [ + "/union-value" + ], + "_resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "_shasum": "7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1", + "_spec": "set-value@^0.4.3", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/union-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/set-value/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "email": "wtgtybhertgeghgtwtg@gmail.com", + "url": "https://github.com/wtgtybhertgeghgtwtg" + }, + { + "name": "Jon Schlinkert", + "email": "jon.schlinkert@sellside.com", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Vadim Demedes", + "email": "vdemedes@gmail.com", + "url": "https://vadimdemedes.com" + } + ], + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + }, + "deprecated": false, + "description": "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.", + "devDependencies": { + "gulp-format-md": "^0.1.10", + "mocha": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/set-value", + "keywords": [ + "get", + "has", + "hasown", + "key", + "keys", + "nested", + "notation", + "object", + "prop", + "properties", + "property", + "props", + "set", + "value", + "values" + ], + "license": "MIT", + "main": "index.js", + "name": "set-value", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/set-value.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "assign-value", + "get-value", + "has-value", + "merge-value", + "omit-value", + "set-value", + "union-value", + "unset-value" + ] + }, + "lint": { + "reflinks": true + } + }, + "version": "0.4.3" +} diff --git a/js/node_modules/union-value/package.json b/js/node_modules/union-value/package.json new file mode 100644 index 0000000..37552bc --- /dev/null +++ b/js/node_modules/union-value/package.json @@ -0,0 +1,105 @@ +{ + "_from": "union-value@^1.0.0", + "_id": "union-value@1.0.0", + "_inBundle": false, + "_integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "_location": "/union-value", + "_phantomChildren": { + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + }, + "_requested": { + "type": "range", + "registry": true, + "raw": "union-value@^1.0.0", + "name": "union-value", + "escapedName": "union-value", + "rawSpec": "^1.0.0", + "saveSpec": null, + "fetchSpec": "^1.0.0" + }, + "_requiredBy": [ + "/cache-base" + ], + "_resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "_shasum": "5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4", + "_spec": "union-value@^1.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/cache-base", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/union-value/issues" + }, + "bundleDependencies": false, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "deprecated": false, + "description": "Set an array of unique values as the property of an object. Supports setting deeply nested properties using using object-paths/dot notation.", + "devDependencies": { + "gulp-format-md": "^0.1.11", + "mocha": "^3.2.0", + "should": "^11.2.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/union-value", + "keywords": [ + "array", + "dot", + "get", + "has", + "nested", + "notation", + "object", + "path", + "prop", + "property", + "set", + "union", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "union-value", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/union-value.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "assign-value", + "get-value", + "has-value", + "set-value", + "unset-value" + ] + }, + "lint": { + "reflinks": true + } + }, + "version": "1.0.0" +} diff --git a/js/node_modules/unset-value/LICENSE b/js/node_modules/unset-value/LICENSE new file mode 100644 index 0000000..ec85897 --- /dev/null +++ b/js/node_modules/unset-value/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, 2017, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/unset-value/README.md b/js/node_modules/unset-value/README.md new file mode 100644 index 0000000..f0fec3d --- /dev/null +++ b/js/node_modules/unset-value/README.md @@ -0,0 +1,131 @@ +# unset-value [![NPM version](https://img.shields.io/npm/v/unset-value.svg?style=flat)](https://www.npmjs.com/package/unset-value) [![NPM monthly downloads](https://img.shields.io/npm/dm/unset-value.svg?style=flat)](https://npmjs.org/package/unset-value) [![NPM total downloads](https://img.shields.io/npm/dt/unset-value.svg?style=flat)](https://npmjs.org/package/unset-value) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/unset-value.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/unset-value) + +> Delete nested properties from an object using dot notation. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save unset-value +``` + +## Usage + +```js +var unset = require('unset-value'); + +var obj = {a: {b: {c: 'd', e: 'f'}}}; +unset(obj, 'a.b.c'); +console.log(obj); +//=> {a: {b: {e: 'f'}}}; +``` + +## Examples + +### Updates the object when a property is deleted + +```js +var obj = {a: 'b'}; +unset(obj, 'a'); +console.log(obj); +//=> {} +``` + +### Returns true when a property is deleted + +```js +unset({a: 'b'}, 'a') // true +``` + +### Returns `true` when a property does not exist + +This is consistent with `delete` behavior in that it does not +throw when a property does not exist. + +```js +unset({a: {b: {c: 'd'}}}, 'd') // true +``` + +### delete nested values + +```js +var one = {a: {b: {c: 'd'}}}; +unset(one, 'a.b'); +console.log(one); +//=> {a: {}} + +var two = {a: {b: {c: 'd'}}}; +unset(two, 'a.b.c'); +console.log(two); +//=> {a: {b: {}}} + +var three = {a: {b: {c: 'd', e: 'f'}}}; +unset(three, 'a.b.c'); +console.log(three); +//=> {a: {b: {e: 'f'}}} +``` + +### throws on invalid args + +```js +unset(); +// 'expected an object.' +``` + +## About + +### Related projects + +* [get-value](https://www.npmjs.com/package/get-value): Use property paths (`a.b.c`) to get a nested value from an object. | [homepage](https://github.com/jonschlinkert/get-value "Use property paths (`a.b.c`) to get a nested value from an object.") +* [get-values](https://www.npmjs.com/package/get-values): Return an array of all values from the given object. | [homepage](https://github.com/jonschlinkert/get-values "Return an array of all values from the given object.") +* [omit-value](https://www.npmjs.com/package/omit-value): Omit properties from an object or deeply nested property of an object using object path… [more](https://github.com/jonschlinkert/omit-value) | [homepage](https://github.com/jonschlinkert/omit-value "Omit properties from an object or deeply nested property of an object using object path notation.") +* [put-value](https://www.npmjs.com/package/put-value): Update only existing values from an object, works with dot notation paths like `a.b.c` and… [more](https://github.com/tunnckocore/put-value#readme) | [homepage](https://github.com/tunnckocore/put-value#readme "Update only existing values from an object, works with dot notation paths like `a.b.c` and support deep nesting.") +* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.") +* [union-value](https://www.npmjs.com/package/union-value): Set an array of unique values as the property of an object. Supports setting deeply… [more](https://github.com/jonschlinkert/union-value) | [homepage](https://github.com/jonschlinkert/union-value "Set an array of unique values as the property of an object. Supports setting deeply nested properties using using object-paths/dot notation.") +* [upsert-value](https://www.npmjs.com/package/upsert-value): Update or set nested values and any intermediaries with dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/doowb/upsert-value "Update or set nested values and any intermediaries with dot notation (`'a.b.c'`) paths.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 6 | [jonschlinkert](https://github.com/jonschlinkert) | +| 2 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) | + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 25, 2017._ \ No newline at end of file diff --git a/js/node_modules/unset-value/index.js b/js/node_modules/unset-value/index.js new file mode 100644 index 0000000..a919010 --- /dev/null +++ b/js/node_modules/unset-value/index.js @@ -0,0 +1,32 @@ +/*! + * unset-value + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +var isObject = require('isobject'); +var has = require('has-value'); + +module.exports = function unset(obj, prop) { + if (!isObject(obj)) { + throw new TypeError('expected an object.'); + } + if (obj.hasOwnProperty(prop)) { + delete obj[prop]; + return true; + } + + if (has(obj, prop)) { + var segs = prop.split('.'); + var last = segs.pop(); + while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { + last = segs.pop().slice(0, -1) + '.' + last; + } + while (segs.length) obj = obj[prop = segs.shift()]; + return (delete obj[last]); + } + return true; +}; diff --git a/js/node_modules/unset-value/node_modules/has-value/LICENSE b/js/node_modules/unset-value/node_modules/has-value/LICENSE new file mode 100644 index 0000000..39245ac --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/unset-value/node_modules/has-value/README.md b/js/node_modules/unset-value/node_modules/has-value/README.md new file mode 100644 index 0000000..a927633 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/README.md @@ -0,0 +1,130 @@ +# has-value [![NPM version](https://img.shields.io/npm/v/has-value.svg?style=flat)](https://www.npmjs.com/package/has-value) [![NPM downloads](https://img.shields.io/npm/dm/has-value.svg?style=flat)](https://npmjs.org/package/has-value) [![Build Status](https://img.shields.io/travis/jonschlinkert/has-value.svg?style=flat)](https://travis-ci.org/jonschlinkert/has-value) + +> Returns true if a value exists, false if empty. Works with deeply nested values using object paths. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install has-value --save +``` + +**Works for:** + +* booleans +* functions +* numbers (pass `true` as the last arg to treat zero as a value instead of falsey) +* strings +* nulls +* object +* arrays + +## Usage + +Works with nested object paths or a single value: + +```js +var hasValue = require('has-value'); + +hasValue({a: {b: {c: 'foo'}}} 'a.b.c'); +//=> true + +hasValue('a'); +//=> true + +hasValue(''); +//=> false + +hasValue(1); +//=> true + +hasValue(0); +//=> false + +hasValue(0, true); // pass `true` as the last arg to treat zero as a value +//=> true + +hasValue({a: 'a'}}); +//=> true + +hasValue({}}); +//=> false + +hasValue(['a']); +//=> true + +hasValue([]); +//=> false + +hasValue(function(foo) {}); // function length/arity +//=> true + +hasValue(function() {}); +//=> false + +hasValue(true); +hasValue(false); +//=> true +``` + +## isEmpty + +To do the opposite and test for empty values, do: + +```js +function isEmpty(o, isZero) { + return !hasValue.apply(hasValue, arguments); +} +``` + +## Related projects + +You might also be interested in these projects: + +* [get-object](https://www.npmjs.com/package/get-object): Get a property from an object using dot (object path) notation. | [homepage](https://github.com/jonschlinkert/get-object) +* [get-property](https://www.npmjs.com/package/get-property): Get a nested property or its value from an object using simple `a.b.c` paths. | [homepage](https://github.com/jonschlinkert/get-property) +* [get-value](https://www.npmjs.com/package/get-value): Use property paths (`a.b.c`) to get a nested value from an object. | [homepage](https://github.com/jonschlinkert/get-value) +* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/has-value/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/has-value/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v, on March 27, 2016._ \ No newline at end of file diff --git a/js/node_modules/unset-value/node_modules/has-value/index.js b/js/node_modules/unset-value/node_modules/has-value/index.js new file mode 100644 index 0000000..90687c8 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/index.js @@ -0,0 +1,19 @@ +/*! + * has-value + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var isObject = require('isobject'); +var hasValues = require('has-values'); +var get = require('get-value'); + +module.exports = function(obj, prop, noZero) { + if (isObject(obj)) { + return hasValues(get(obj, prop), noZero); + } + return hasValues(obj, prop); +}; diff --git a/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/LICENSE b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/LICENSE new file mode 100644 index 0000000..39245ac --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/README.md b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/README.md new file mode 100644 index 0000000..9dd897a --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/README.md @@ -0,0 +1,112 @@ +# isobject [![NPM version](https://img.shields.io/npm/v/isobject.svg?style=flat)](https://www.npmjs.com/package/isobject) [![NPM downloads](https://img.shields.io/npm/dm/isobject.svg?style=flat)](https://npmjs.org/package/isobject) [![Build Status](https://img.shields.io/travis/jonschlinkert/isobject.svg?style=flat)](https://travis-ci.org/jonschlinkert/isobject) + +Returns true if the value is an object and not an array or null. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install isobject --save +``` + +Use [is-plain-object](https://github.com/jonschlinkert/is-plain-object) if you want only objects that are created by the `Object` constructor. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install isobject +``` + +Install with [bower](http://bower.io/) + +```sh +$ bower install isobject +``` + +## Usage + +```js +var isObject = require('isobject'); +``` + +**True** + +All of the following return `true`: + +```js +isObject({}); +isObject(Object.create({})); +isObject(Object.create(Object.prototype)); +isObject(Object.create(null)); +isObject({}); +isObject(new Foo); +isObject(/foo/); +``` + +**False** + +All of the following return `false`: + +```js +isObject(); +isObject(function () {}); +isObject(1); +isObject([]); +isObject(undefined); +isObject(null); +``` + +## Related projects + +You might also be interested in these projects: + +[merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep) + +* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow) +* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object) +* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/isobject/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/isobject/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on April 25, 2016._ \ No newline at end of file diff --git a/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/index.js b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/index.js new file mode 100644 index 0000000..aa0dce0 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/index.js @@ -0,0 +1,14 @@ +/*! + * isobject + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var isArray = require('isarray'); + +module.exports = function isObject(val) { + return val != null && typeof val === 'object' && isArray(val) === false; +}; diff --git a/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/package.json b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/package.json new file mode 100644 index 0000000..3bb152b --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/node_modules/isobject/package.json @@ -0,0 +1,98 @@ +{ + "_from": "isobject@^2.0.0", + "_id": "isobject@2.1.0", + "_inBundle": false, + "_integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "_location": "/unset-value/has-value/isobject", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "isobject@^2.0.0", + "name": "isobject", + "escapedName": "isobject", + "rawSpec": "^2.0.0", + "saveSpec": null, + "fetchSpec": "^2.0.0" + }, + "_requiredBy": [ + "/unset-value/has-value" + ], + "_resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "_shasum": "f065561096a3f1da2ef46272f815c840d87e0c89", + "_spec": "isobject@^2.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/unset-value/node_modules/has-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/isobject/issues" + }, + "bundleDependencies": false, + "dependencies": { + "isarray": "1.0.0" + }, + "deprecated": false, + "description": "Returns true if the value is an object and not an array or null.", + "devDependencies": { + "gulp-format-md": "^0.1.9", + "mocha": "^2.4.5" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/isobject", + "keywords": [ + "check", + "is", + "is-object", + "isobject", + "kind", + "kind-of", + "kindof", + "native", + "object", + "type", + "typeof", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "isobject", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/isobject.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "merge-deep", + "extend-shallow", + "is-plain-object", + "kind-of" + ] + }, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "reflinks": [ + "verb" + ] + }, + "version": "2.1.0" +} diff --git a/js/node_modules/unset-value/node_modules/has-value/package.json b/js/node_modules/unset-value/node_modules/has-value/package.json new file mode 100644 index 0000000..43f4e3b --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-value/package.json @@ -0,0 +1,114 @@ +{ + "_from": "has-value@^0.3.1", + "_id": "has-value@0.3.1", + "_inBundle": false, + "_integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "_location": "/unset-value/has-value", + "_phantomChildren": { + "isarray": "1.0.0" + }, + "_requested": { + "type": "range", + "registry": true, + "raw": "has-value@^0.3.1", + "name": "has-value", + "escapedName": "has-value", + "rawSpec": "^0.3.1", + "saveSpec": null, + "fetchSpec": "^0.3.1" + }, + "_requiredBy": [ + "/unset-value" + ], + "_resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "_shasum": "7b1f58bada62ca827ec0a2078025654845995e1f", + "_spec": "has-value@^0.3.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/unset-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/has-value/issues" + }, + "bundleDependencies": false, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "deprecated": false, + "description": "Returns true if a value exists, false if empty. Works with deeply nested values using object paths.", + "devDependencies": { + "gulp-format-md": "^0.1.7", + "mocha": "^2.4.5" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/has-value", + "keywords": [ + "array", + "boolean", + "empty", + "find", + "function", + "has", + "hasOwn", + "javascript", + "js", + "key", + "keys", + "node.js", + "null", + "number", + "object", + "properties", + "property", + "string", + "type", + "util", + "utilities", + "utility", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "has-value", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/has-value.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "run": true, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "get-object", + "get-property", + "get-value", + "set-value" + ] + }, + "reflinks": [ + "verb" + ], + "lint": { + "reflinks": true + } + }, + "version": "0.3.1" +} diff --git a/js/node_modules/unset-value/node_modules/has-values/LICENSE b/js/node_modules/unset-value/node_modules/has-values/LICENSE new file mode 100644 index 0000000..39245ac --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-values/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/unset-value/node_modules/has-values/README.md b/js/node_modules/unset-value/node_modules/has-values/README.md new file mode 100644 index 0000000..13319c5 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-values/README.md @@ -0,0 +1,114 @@ +# has-values [![NPM version](https://img.shields.io/npm/v/has-values.svg?style=flat)](https://www.npmjs.com/package/has-values) [![NPM downloads](https://img.shields.io/npm/dm/has-values.svg?style=flat)](https://npmjs.org/package/has-values) [![Build Status](https://img.shields.io/travis/jonschlinkert/has-values.svg?style=flat)](https://travis-ci.org/jonschlinkert/has-values) + +> Returns true if any values exist, false if empty. Works for booleans, functions, numbers, strings, nulls, objects and arrays. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install has-values --save +``` + +## Usage + +```js +var hasValue = require('has-values'); + +hasValue('a'); +//=> true + +hasValue(''); +//=> false + +hasValue(1); +//=> true + +hasValue(0); +//=> false + +hasValue(0, true); // treat zero as a value +//=> true + +hasValue({a: 'a'}}); +//=> true + +hasValue({}}); +//=> false + +hasValue(['a']); +//=> true + +hasValue([]); +//=> false + +hasValue(function(foo) {}); // function length/arity +//=> true + +hasValue(function() {}); +//=> false + +hasValue(true); +hasValue(false); +//=> true +``` + +## isEmpty + +To test for empty values, do: + +```js +function isEmpty(o, isZero) { + return !hasValue(o, isZero); +} +``` + +## Related projects + +You might also be interested in these projects: + +* [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://www.npmjs.com/package/has-value) | [homepage](https://github.com/jonschlinkert/has-value) +* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object) +* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/has-values/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/has-values/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v, on March 27, 2016._ \ No newline at end of file diff --git a/js/node_modules/unset-value/node_modules/has-values/index.js b/js/node_modules/unset-value/node_modules/has-values/index.js new file mode 100644 index 0000000..6d04ba1 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-values/index.js @@ -0,0 +1,36 @@ +/*! + * has-values + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +module.exports = function hasValue(o, noZero) { + if (o === null || o === undefined) { + return false; + } + + if (typeof o === 'boolean') { + return true; + } + + if (typeof o === 'number') { + if (o === 0 && noZero === true) { + return false; + } + return true; + } + + if (o.length !== undefined) { + return o.length !== 0; + } + + for (var key in o) { + if (o.hasOwnProperty(key)) { + return true; + } + } + return false; +}; diff --git a/js/node_modules/unset-value/node_modules/has-values/package.json b/js/node_modules/unset-value/node_modules/has-values/package.json new file mode 100644 index 0000000..67ec76b --- /dev/null +++ b/js/node_modules/unset-value/node_modules/has-values/package.json @@ -0,0 +1,106 @@ +{ + "_from": "has-values@^0.1.4", + "_id": "has-values@0.1.4", + "_inBundle": false, + "_integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "_location": "/unset-value/has-values", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "has-values@^0.1.4", + "name": "has-values", + "escapedName": "has-values", + "rawSpec": "^0.1.4", + "saveSpec": null, + "fetchSpec": "^0.1.4" + }, + "_requiredBy": [ + "/unset-value/has-value" + ], + "_resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "_shasum": "6d61de95d91dfca9b9a02089ad384bff8f62b771", + "_spec": "has-values@^0.1.4", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/unset-value/node_modules/has-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/has-values/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Returns true if any values exist, false if empty. Works for booleans, functions, numbers, strings, nulls, objects and arrays. ", + "devDependencies": { + "gulp-format-md": "^0.1.7", + "mocha": "^2.4.5" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/has-values", + "keywords": [ + "array", + "boolean", + "empty", + "find", + "function", + "has", + "hasOwn", + "javascript", + "js", + "key", + "keys", + "node.js", + "null", + "number", + "object", + "properties", + "property", + "string", + "type", + "util", + "utilities", + "utility", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "has-values", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/has-values.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "run": true, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "has-value", + "isobject", + "is-plain-object" + ] + }, + "reflinks": [ + "verb" + ], + "lint": { + "reflinks": true + } + }, + "version": "0.1.4" +} diff --git a/js/node_modules/unset-value/node_modules/isobject/LICENSE b/js/node_modules/unset-value/node_modules/isobject/LICENSE new file mode 100644 index 0000000..943e71d --- /dev/null +++ b/js/node_modules/unset-value/node_modules/isobject/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/js/node_modules/unset-value/node_modules/isobject/README.md b/js/node_modules/unset-value/node_modules/isobject/README.md new file mode 100644 index 0000000..d01feaa --- /dev/null +++ b/js/node_modules/unset-value/node_modules/isobject/README.md @@ -0,0 +1,122 @@ +# isobject [![NPM version](https://img.shields.io/npm/v/isobject.svg?style=flat)](https://www.npmjs.com/package/isobject) [![NPM monthly downloads](https://img.shields.io/npm/dm/isobject.svg?style=flat)](https://npmjs.org/package/isobject) [![NPM total downloads](https://img.shields.io/npm/dt/isobject.svg?style=flat)](https://npmjs.org/package/isobject) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/isobject.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/isobject) + +> Returns true if the value is an object and not an array or null. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save isobject +``` + +Install with [yarn](https://yarnpkg.com): + +```sh +$ yarn add isobject +``` + +Use [is-plain-object](https://github.com/jonschlinkert/is-plain-object) if you want only objects that are created by the `Object` constructor. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install isobject +``` +Install with [bower](https://bower.io/) + +```sh +$ bower install isobject +``` + +## Usage + +```js +var isObject = require('isobject'); +``` + +**True** + +All of the following return `true`: + +```js +isObject({}); +isObject(Object.create({})); +isObject(Object.create(Object.prototype)); +isObject(Object.create(null)); +isObject({}); +isObject(new Foo); +isObject(/foo/); +``` + +**False** + +All of the following return `false`: + +```js +isObject(); +isObject(function () {}); +isObject(1); +isObject([]); +isObject(undefined); +isObject(null); +``` + +## About + +### Related projects + +* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow "Extend an object with the properties of additional objects. node.js/javascript util.") +* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.") +* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.") +* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep "Recursively merge values in a javascript object.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 29 | [jonschlinkert](https://github.com/jonschlinkert) | +| 4 | [doowb](https://github.com/doowb) | +| 1 | [magnudae](https://github.com/magnudae) | +| 1 | [LeSuisse](https://github.com/LeSuisse) | +| 1 | [tmcw](https://github.com/tmcw) | + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 30, 2017._ \ No newline at end of file diff --git a/js/node_modules/unset-value/node_modules/isobject/index.d.ts b/js/node_modules/unset-value/node_modules/isobject/index.d.ts new file mode 100644 index 0000000..55f81c2 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/isobject/index.d.ts @@ -0,0 +1,5 @@ +export = isObject; + +declare function isObject(val: any): boolean; + +declare namespace isObject {} diff --git a/js/node_modules/unset-value/node_modules/isobject/index.js b/js/node_modules/unset-value/node_modules/isobject/index.js new file mode 100644 index 0000000..2d59958 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/isobject/index.js @@ -0,0 +1,12 @@ +/*! + * isobject + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +module.exports = function isObject(val) { + return val != null && typeof val === 'object' && Array.isArray(val) === false; +}; diff --git a/js/node_modules/unset-value/node_modules/isobject/package.json b/js/node_modules/unset-value/node_modules/isobject/package.json new file mode 100644 index 0000000..3a52419 --- /dev/null +++ b/js/node_modules/unset-value/node_modules/isobject/package.json @@ -0,0 +1,119 @@ +{ + "_from": "isobject@^3.0.0", + "_id": "isobject@3.0.1", + "_inBundle": false, + "_integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "_location": "/unset-value/isobject", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "isobject@^3.0.0", + "name": "isobject", + "escapedName": "isobject", + "rawSpec": "^3.0.0", + "saveSpec": null, + "fetchSpec": "^3.0.0" + }, + "_requiredBy": [ + "/unset-value" + ], + "_resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "_shasum": "4e431e92b11a9731636aa1f9c8d1ccbcfdab78df", + "_spec": "isobject@^3.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/unset-value", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/isobject/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "url": "https://github.com/LeSuisse" + }, + { + "name": "Brian Woodward", + "url": "https://twitter.com/doowb" + }, + { + "name": "Jon Schlinkert", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Magnús Dæhlen", + "url": "https://github.com/magnudae" + }, + { + "name": "Tom MacWright", + "url": "https://macwright.org" + } + ], + "dependencies": {}, + "deprecated": false, + "description": "Returns true if the value is an object and not an array or null.", + "devDependencies": { + "gulp-format-md": "^0.1.9", + "mocha": "^2.4.5" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.d.ts", + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/isobject", + "keywords": [ + "check", + "is", + "is-object", + "isobject", + "kind", + "kind-of", + "kindof", + "native", + "object", + "type", + "typeof", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "isobject", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/isobject.git" + }, + "scripts": { + "test": "mocha" + }, + "types": "index.d.ts", + "verb": { + "related": { + "list": [ + "extend-shallow", + "is-plain-object", + "kind-of", + "merge-deep" + ] + }, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "reflinks": [ + "verb" + ] + }, + "version": "3.0.1" +} diff --git a/js/node_modules/unset-value/package.json b/js/node_modules/unset-value/package.json new file mode 100644 index 0000000..60fe808 --- /dev/null +++ b/js/node_modules/unset-value/package.json @@ -0,0 +1,112 @@ +{ + "_from": "unset-value@^1.0.0", + "_id": "unset-value@1.0.0", + "_inBundle": false, + "_integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "_location": "/unset-value", + "_phantomChildren": { + "get-value": "2.0.6", + "isarray": "1.0.0" + }, + "_requested": { + "type": "range", + "registry": true, + "raw": "unset-value@^1.0.0", + "name": "unset-value", + "escapedName": "unset-value", + "rawSpec": "^1.0.0", + "saveSpec": null, + "fetchSpec": "^1.0.0" + }, + "_requiredBy": [ + "/cache-base" + ], + "_resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "_shasum": "8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559", + "_spec": "unset-value@^1.0.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/cache-base", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/unset-value/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "email": "wtgtybhertgeghgtwtg@gmail.com", + "url": "https://github.com/wtgtybhertgeghgtwtg" + }, + { + "name": "Jon Schlinkert", + "email": "jon.schlinkert@sellside.com", + "url": "http://twitter.com/jonschlinkert" + } + ], + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "deprecated": false, + "description": "Delete nested properties from an object using dot notation.", + "devDependencies": { + "gulp-format-md": "^0.1.11", + "mocha": "*", + "should": "*" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/unset-value", + "keywords": [ + "del", + "delete", + "key", + "object", + "omit", + "prop", + "property", + "remove", + "unset", + "value" + ], + "license": "MIT", + "main": "index.js", + "name": "unset-value", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/unset-value.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "get-value", + "get-values", + "omit-value", + "put-value", + "set-value", + "union-value", + "upsert-value" + ] + }, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + } + }, + "version": "1.0.0" +} diff --git a/js/node_modules/urix/.jshintrc b/js/node_modules/urix/.jshintrc new file mode 100644 index 0000000..9d1a618 --- /dev/null +++ b/js/node_modules/urix/.jshintrc @@ -0,0 +1,42 @@ +{ + "bitwise": true, + "camelcase": true, + "curly": false, + "eqeqeq": true, + "es3": false, + "forin": true, + "immed": false, + "indent": false, + "latedef": "nofunc", + "newcap": false, + "noarg": true, + "noempty": true, + "nonew": false, + "plusplus": false, + "quotmark": true, + "undef": true, + "unused": "vars", + "strict": false, + "trailing": true, + "maxparams": 5, + "maxdepth": false, + "maxstatements": false, + "maxcomplexity": false, + "maxlen": 100, + + "asi": true, + "expr": true, + "globalstrict": true, + "smarttabs": true, + "sub": true, + + "node": true, + "globals": { + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false + } +} diff --git a/js/node_modules/urix/LICENSE b/js/node_modules/urix/LICENSE new file mode 100644 index 0000000..0595be3 --- /dev/null +++ b/js/node_modules/urix/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/urix/index.js b/js/node_modules/urix/index.js new file mode 100644 index 0000000..dc6ef27 --- /dev/null +++ b/js/node_modules/urix/index.js @@ -0,0 +1,17 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = require("path") + +"use strict" + +function urix(aPath) { + if (path.sep === "\\") { + return aPath + .replace(/\\/g, "/") + .replace(/^[a-z]:\/?/i, "/") + } + return aPath +} + +module.exports = urix diff --git a/js/node_modules/urix/package.json b/js/node_modules/urix/package.json new file mode 100644 index 0000000..a3efa96 --- /dev/null +++ b/js/node_modules/urix/package.json @@ -0,0 +1,59 @@ +{ + "_from": "urix@^0.1.0", + "_id": "urix@0.1.0", + "_inBundle": false, + "_integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "_location": "/urix", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "urix@^0.1.0", + "name": "urix", + "escapedName": "urix", + "rawSpec": "^0.1.0", + "saveSpec": null, + "fetchSpec": "^0.1.0" + }, + "_requiredBy": [ + "/source-map-resolve" + ], + "_resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "_shasum": "da937f7a62e21fec1fd18d49b35c2935067a6c72", + "_spec": "urix@^0.1.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/source-map-resolve", + "author": { + "name": "Simon Lydell" + }, + "bugs": { + "url": "https://github.com/lydell/urix/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Makes Windows-style paths more unix and URI friendly.", + "devDependencies": { + "jshint": "^2.4.4", + "mocha": "^1.17.1" + }, + "homepage": "https://github.com/lydell/urix#readme", + "keywords": [ + "path", + "url", + "uri", + "unix", + "windows", + "backslash", + "slash" + ], + "license": "MIT", + "main": "index.js", + "name": "urix", + "repository": { + "type": "git", + "url": "git+https://github.com/lydell/urix.git" + }, + "scripts": { + "test": "jshint index.js test/ && mocha" + }, + "version": "0.1.0" +} diff --git a/js/node_modules/urix/readme.md b/js/node_modules/urix/readme.md new file mode 100644 index 0000000..b258b98 --- /dev/null +++ b/js/node_modules/urix/readme.md @@ -0,0 +1,46 @@ +[![Build Status](https://travis-ci.org/lydell/urix.png?branch=master)](https://travis-ci.org/lydell/urix) + +Overview +======== + +Makes Windows-style paths more unix and URI friendly. Useful if you work with +paths that eventually will be used in URLs. + +```js +var urix = require("urix") + +// On Windows: +urix("c:\\users\\you\\foo") +// /users/you/foo + +// On unix-like systems: +urix("c:\\users\\you\\foo") +// c:\users\you\foo +``` + + +Installation +============ + +`npm install urix` + +```js +var urix = require("urix") +``` + + +Usage +===== + +### `urix(path)` ### + +On Windows, replaces all backslashes with slashes and uses a slash instead of a +drive letter and a colon for absolute paths. + +On unix-like systems it is a no-op. + + +License +======= + +[The X11 (“MIT”) License](LICENSE). diff --git a/js/node_modules/urix/test/index.js b/js/node_modules/urix/test/index.js new file mode 100644 index 0000000..5333f24 --- /dev/null +++ b/js/node_modules/urix/test/index.js @@ -0,0 +1,43 @@ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = require("path") +var assert = require("assert") +var urix = require("../") + +"use stict" + +function test(testPath, expected) { + path.sep = "\\" + assert.equal(urix(testPath), expected) + path.sep = "/" + assert.equal(urix(testPath), testPath) +} + +describe("urix", function() { + + it("is a function", function() { + assert.equal(typeof urix, "function") + }) + + + it("converts backslashes to slashes", function() { + test("a\\b\\c", "a/b/c") + test("\\a\\b\\c", "/a/b/c") + test("a/b\\c", "a/b/c") + test("\\\\a\\\\\\b///c", "//a///b///c") + }) + + + it("changes the drive letter to a slash", function() { + test("c:\\a", "/a") + test("C:\\a", "/a") + test("z:\\a", "/a") + test("c:a", "/a") + test("c:/a", "/a") + test("c:\\\\a", "//a") + test("c://a", "//a") + test("c:\\//a", "///a") + }) + +}) diff --git a/js/node_modules/use/LICENSE b/js/node_modules/use/LICENSE new file mode 100644 index 0000000..e33d14b --- /dev/null +++ b/js/node_modules/use/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2017, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/use/README.md b/js/node_modules/use/README.md new file mode 100644 index 0000000..bd4e325 --- /dev/null +++ b/js/node_modules/use/README.md @@ -0,0 +1,90 @@ +# use [![NPM version](https://img.shields.io/npm/v/use.svg?style=flat)](https://www.npmjs.com/package/use) [![NPM monthly downloads](https://img.shields.io/npm/dm/use.svg?style=flat)](https://npmjs.org/package/use) [![NPM total downloads](https://img.shields.io/npm/dt/use.svg?style=flat)](https://npmjs.org/package/use) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/use.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/use) + +> Easily add plugin support to your node.js application. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save use +``` + +A different take on plugin handling! This is not a middleware system, if you need something that handles async middleware, [ware](https://github.com/segmentio/ware) is great for that. + +## Usage + +```js +var use = require('use'); +``` + +See the [examples folder](./examples) for usage examples. + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [base-plugins](https://www.npmjs.com/package/base-plugins): Adds 'smart plugin' support to your base application. | [homepage](https://github.com/node-base/base-plugins "Adds 'smart plugin' support to your base application.") +* [base](https://www.npmjs.com/package/base): Framework for rapidly creating high quality, server-side node.js applications, using plugins like building blocks | [homepage](https://github.com/node-base/base "Framework for rapidly creating high quality, server-side node.js applications, using plugins like building blocks") +* [ware](https://www.npmjs.com/package/ware): Easily create your own middleware layer. | [homepage](https://github.com/segmentio/ware "Easily create your own middleware layer.") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 33 | [jonschlinkert](https://github.com/jonschlinkert) | +| 7 | [charlike-old](https://github.com/charlike-old) | +| 2 | [doowb](https://github.com/doowb) | +| 2 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) | + +### Author + +**Jon Schlinkert** + +* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert) +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 03, 2017._ \ No newline at end of file diff --git a/js/node_modules/use/index.js b/js/node_modules/use/index.js new file mode 100644 index 0000000..11edc71 --- /dev/null +++ b/js/node_modules/use/index.js @@ -0,0 +1,153 @@ +/*! + * use + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +var typeOf = require('kind-of'); + +module.exports = function base(app, options) { + if (typeOf(app) !== 'object' && typeof app !== 'function') { + throw new TypeError('expected an object or function'); + } + + var opts = typeOf(options) === 'object' ? options : {}; + var prop = typeof opts.prop === 'string' ? opts.prop : 'fns'; + if (!Array.isArray(app[prop])) { + define(app, prop, []); + } + + /** + * Define a plugin function to be passed to use. The only + * parameter exposed to the plugin is `app`, the object or function. + * passed to `use(app)`. `app` is also exposed as `this` in plugins. + * + * Additionally, **if a plugin returns a function, the function will + * be pushed onto the `fns` array**, allowing the plugin to be + * called at a later point by the `run` method. + * + * ```js + * var use = require('use'); + * + * // define a plugin + * function foo(app) { + * // do stuff + * } + * + * var app = function(){}; + * use(app); + * + * // register plugins + * app.use(foo); + * app.use(bar); + * app.use(baz); + * ``` + * @name .use + * @param {Function} `fn` plugin function to call + * @api public + */ + + define(app, 'use', use); + + /** + * Run all plugins on `fns`. Any plugin that returns a function + * when called by `use` is pushed onto the `fns` array. + * + * ```js + * var config = {}; + * app.run(config); + * ``` + * @name .run + * @param {Object} `value` Object to be modified by plugins. + * @return {Object} Returns the object passed to `run` + * @api public + */ + + define(app, 'run', function(val) { + if (typeOf(val) !== 'object') return; + + if (!val.use || !val.run) { + define(val, prop, val[prop] || []); + define(val, 'use', use); + } + + if (!val[prop] || val[prop].indexOf(base) === -1) { + val.use(base); + } + + var self = this || app; + var fns = self[prop]; + var len = fns.length; + var idx = -1; + + while (++idx < len) { + val.use(fns[idx]); + } + return val; + }); + + /** + * Call plugin `fn`. If a function is returned push it into the + * `fns` array to be called by the `run` method. + */ + + function use(type, fn, options) { + var offset = 1; + + if (typeof type === 'string' || Array.isArray(type)) { + fn = wrap(type, fn); + offset++; + } else { + options = fn; + fn = type; + } + + if (typeof fn !== 'function') { + throw new TypeError('expected a function'); + } + + var self = this || app; + var fns = self[prop]; + + var args = [].slice.call(arguments, offset); + args.unshift(self); + + if (typeof opts.hook === 'function') { + opts.hook.apply(self, args); + } + + var val = fn.apply(self, args); + if (typeof val === 'function' && fns.indexOf(val) === -1) { + fns.push(val); + } + return self; + } + + /** + * Wrap a named plugin function so that it's only called on objects of the + * given `type` + * + * @param {String} `type` + * @param {Function} `fn` Plugin function + * @return {Function} + */ + + function wrap(type, fn) { + return function plugin() { + return this.type === type ? fn.apply(this, arguments) : plugin; + }; + } + + return app; +}; + +function define(obj, key, val) { + Object.defineProperty(obj, key, { + configurable: true, + writable: true, + value: val + }); +} diff --git a/js/node_modules/use/node_modules/kind-of/CHANGELOG.md b/js/node_modules/use/node_modules/kind-of/CHANGELOG.md new file mode 100644 index 0000000..fb30b06 --- /dev/null +++ b/js/node_modules/use/node_modules/kind-of/CHANGELOG.md @@ -0,0 +1,157 @@ +# Release history + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +
+ Guiding Principles + +- Changelogs are for humans, not machines. +- There should be an entry for every single version. +- The same types of changes should be grouped. +- Versions and sections should be linkable. +- The latest version comes first. +- The release date of each versions is displayed. +- Mention whether you follow Semantic Versioning. + +
+ +
+ Types of changes + +Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_): + +- `Added` for new features. +- `Changed` for changes in existing functionality. +- `Deprecated` for soon-to-be removed features. +- `Removed` for now removed features. +- `Fixed` for any bug fixes. +- `Security` in case of vulnerabilities. + +
+ +## [6.0.0] - 2017-10-13 + +- refactor code to be more performant +- refactor benchmarks + +## [5.1.0] - 2017-10-13 + +**Added** + +- Merge pull request #15 from aretecode/patch-1 +- adds support and tests for string & array iterators + +**Changed** + +- updates benchmarks + +## [5.0.2] - 2017-08-02 + +- Merge pull request #14 from struct78/master +- Added `undefined` check + +## [5.0.0] - 2017-06-21 + +- Merge pull request #12 from aretecode/iterator +- Set Iterator + Map Iterator +- streamline `isbuffer`, minor edits + +## [4.0.0] - 2017-05-19 + +- Merge pull request #8 from tunnckoCore/master +- update deps + +## [3.2.2] - 2017-05-16 + +- fix version + +## [3.2.1] - 2017-05-16 + +- add browserify + +## [3.2.0] - 2017-04-25 + +- Merge pull request #10 from ksheedlo/unrequire-buffer +- add `promise` support and tests +- Remove unnecessary `Buffer` check + +## [3.1.0] - 2016-12-07 + +- Merge pull request #7 from laggingreflex/err +- add support for `error` and tests +- run update + +## [3.0.4] - 2016-07-29 + +- move tests +- run update + +## [3.0.3] - 2016-05-03 + +- fix prepublish script +- remove unused dep + +## [3.0.0] - 2015-11-17 + +- add typed array support +- Merge pull request #5 from miguelmota/typed-arrays +- adds new tests + +## [2.0.1] - 2015-08-21 + +- use `is-buffer` module + +## [2.0.0] - 2015-05-31 + +- Create fallback for `Array.isArray` if used as a browser package +- Merge pull request #2 from dtothefp/patch-1 +- Merge pull request #3 from pdehaan/patch-1 +- Merge branch 'master' of https://github.com/chorks/kind-of into chorks-master +- optimizations, mostly date and regex + +## [1.1.0] - 2015-02-09 + +- adds `buffer` support +- adds tests for `buffer` + +## [1.0.0] - 2015-01-19 + +- update benchmarks +- optimizations based on benchmarks + +## [0.1.2] - 2014-10-26 + +- return `typeof` value if it's not an object. very slight speed improvement +- use `.slice` +- adds benchmarks + +## [0.1.0] - 2014-9-26 + +- first commit + +[6.0.0]: https://github.com/jonschlinkert/kind-of/compare/5.1.0...6.0.0 +[5.1.0]: https://github.com/jonschlinkert/kind-of/compare/5.0.2...5.1.0 +[5.0.2]: https://github.com/jonschlinkert/kind-of/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/jonschlinkert/kind-of/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/jonschlinkert/kind-of/compare/4.0.0...5.0.0 +[4.0.0]: https://github.com/jonschlinkert/kind-of/compare/3.2.2...4.0.0 +[3.2.2]: https://github.com/jonschlinkert/kind-of/compare/3.2.1...3.2.2 +[3.2.1]: https://github.com/jonschlinkert/kind-of/compare/3.2.0...3.2.1 +[3.2.0]: https://github.com/jonschlinkert/kind-of/compare/3.1.0...3.2.0 +[3.1.0]: https://github.com/jonschlinkert/kind-of/compare/3.0.4...3.1.0 +[3.0.4]: https://github.com/jonschlinkert/kind-of/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/jonschlinkert/kind-of/compare/3.0.0...3.0.3 +[3.0.0]: https://github.com/jonschlinkert/kind-of/compare/2.0.1...3.0.0 +[2.0.1]: https://github.com/jonschlinkert/kind-of/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/jonschlinkert/kind-of/compare/1.1.0...2.0.0 +[1.1.0]: https://github.com/jonschlinkert/kind-of/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...1.0.0 +[0.1.2]: https://github.com/jonschlinkert/kind-of/compare/0.1.0...0.1.2 +[0.1.0]: https://github.com/jonschlinkert/kind-of/commit/2fae09b0b19b1aadb558e9be39f0c3ef6034eb87 + +[Unreleased]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...HEAD +[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog + diff --git a/js/node_modules/use/node_modules/kind-of/LICENSE b/js/node_modules/use/node_modules/kind-of/LICENSE new file mode 100644 index 0000000..3f2eca1 --- /dev/null +++ b/js/node_modules/use/node_modules/kind-of/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/use/node_modules/kind-of/README.md b/js/node_modules/use/node_modules/kind-of/README.md new file mode 100644 index 0000000..4b0d4a8 --- /dev/null +++ b/js/node_modules/use/node_modules/kind-of/README.md @@ -0,0 +1,365 @@ +# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of) + +> Get the native type of a value. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save kind-of +``` + +Install with [bower](https://bower.io/) + +```sh +$ bower install kind-of --save +``` + +## Why use this? + +1. [it's fast](#benchmarks) | [optimizations](#optimizations) +2. [better type checking](#better-type-checking) + +## Usage + +> es5, es6, and browser ready + +```js +var kindOf = require('kind-of'); + +kindOf(undefined); +//=> 'undefined' + +kindOf(null); +//=> 'null' + +kindOf(true); +//=> 'boolean' + +kindOf(false); +//=> 'boolean' + +kindOf(new Buffer('')); +//=> 'buffer' + +kindOf(42); +//=> 'number' + +kindOf('str'); +//=> 'string' + +kindOf(arguments); +//=> 'arguments' + +kindOf({}); +//=> 'object' + +kindOf(Object.create(null)); +//=> 'object' + +kindOf(new Test()); +//=> 'object' + +kindOf(new Date()); +//=> 'date' + +kindOf([1, 2, 3]); +//=> 'array' + +kindOf(/foo/); +//=> 'regexp' + +kindOf(new RegExp('foo')); +//=> 'regexp' + +kindOf(new Error('error')); +//=> 'error' + +kindOf(function () {}); +//=> 'function' + +kindOf(function * () {}); +//=> 'generatorfunction' + +kindOf(Symbol('str')); +//=> 'symbol' + +kindOf(new Map()); +//=> 'map' + +kindOf(new WeakMap()); +//=> 'weakmap' + +kindOf(new Set()); +//=> 'set' + +kindOf(new WeakSet()); +//=> 'weakset' + +kindOf(new Int8Array()); +//=> 'int8array' + +kindOf(new Uint8Array()); +//=> 'uint8array' + +kindOf(new Uint8ClampedArray()); +//=> 'uint8clampedarray' + +kindOf(new Int16Array()); +//=> 'int16array' + +kindOf(new Uint16Array()); +//=> 'uint16array' + +kindOf(new Int32Array()); +//=> 'int32array' + +kindOf(new Uint32Array()); +//=> 'uint32array' + +kindOf(new Float32Array()); +//=> 'float32array' + +kindOf(new Float64Array()); +//=> 'float64array' +``` + +## Benchmarks + +Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of). + +```bash +# arguments (32 bytes) + kind-of x 17,024,098 ops/sec ±1.90% (86 runs sampled) + lib-type-of x 11,926,235 ops/sec ±1.34% (83 runs sampled) + lib-typeof x 9,245,257 ops/sec ±1.22% (87 runs sampled) + + fastest is kind-of (by 161% avg) + +# array (22 bytes) + kind-of x 17,196,492 ops/sec ±1.07% (88 runs sampled) + lib-type-of x 8,838,283 ops/sec ±1.02% (87 runs sampled) + lib-typeof x 8,677,848 ops/sec ±0.87% (87 runs sampled) + + fastest is kind-of (by 196% avg) + +# boolean (24 bytes) + kind-of x 16,841,600 ops/sec ±1.10% (86 runs sampled) + lib-type-of x 8,096,787 ops/sec ±0.95% (87 runs sampled) + lib-typeof x 8,423,345 ops/sec ±1.15% (86 runs sampled) + + fastest is kind-of (by 204% avg) + +# buffer (38 bytes) + kind-of x 14,848,060 ops/sec ±1.05% (86 runs sampled) + lib-type-of x 3,671,577 ops/sec ±1.49% (87 runs sampled) + lib-typeof x 8,360,236 ops/sec ±1.24% (86 runs sampled) + + fastest is kind-of (by 247% avg) + +# date (30 bytes) + kind-of x 16,067,761 ops/sec ±1.58% (86 runs sampled) + lib-type-of x 8,954,436 ops/sec ±1.40% (87 runs sampled) + lib-typeof x 8,488,307 ops/sec ±1.51% (84 runs sampled) + + fastest is kind-of (by 184% avg) + +# error (36 bytes) + kind-of x 9,634,090 ops/sec ±1.12% (89 runs sampled) + lib-type-of x 7,735,624 ops/sec ±1.32% (86 runs sampled) + lib-typeof x 7,442,160 ops/sec ±1.11% (90 runs sampled) + + fastest is kind-of (by 127% avg) + +# function (34 bytes) + kind-of x 10,031,494 ops/sec ±1.27% (86 runs sampled) + lib-type-of x 9,502,757 ops/sec ±1.17% (89 runs sampled) + lib-typeof x 8,278,985 ops/sec ±1.08% (88 runs sampled) + + fastest is kind-of (by 113% avg) + +# null (24 bytes) + kind-of x 18,159,808 ops/sec ±1.92% (86 runs sampled) + lib-type-of x 12,927,635 ops/sec ±1.01% (88 runs sampled) + lib-typeof x 7,958,234 ops/sec ±1.21% (89 runs sampled) + + fastest is kind-of (by 174% avg) + +# number (22 bytes) + kind-of x 17,846,779 ops/sec ±0.91% (85 runs sampled) + lib-type-of x 3,316,636 ops/sec ±1.19% (86 runs sampled) + lib-typeof x 2,329,477 ops/sec ±2.21% (85 runs sampled) + + fastest is kind-of (by 632% avg) + +# object-plain (47 bytes) + kind-of x 7,085,155 ops/sec ±1.05% (88 runs sampled) + lib-type-of x 8,870,930 ops/sec ±1.06% (83 runs sampled) + lib-typeof x 8,716,024 ops/sec ±1.05% (87 runs sampled) + + fastest is lib-type-of (by 112% avg) + +# regex (25 bytes) + kind-of x 14,196,052 ops/sec ±1.65% (84 runs sampled) + lib-type-of x 9,554,164 ops/sec ±1.25% (88 runs sampled) + lib-typeof x 8,359,691 ops/sec ±1.07% (87 runs sampled) + + fastest is kind-of (by 158% avg) + +# string (33 bytes) + kind-of x 16,131,428 ops/sec ±1.41% (85 runs sampled) + lib-type-of x 7,273,172 ops/sec ±1.05% (87 runs sampled) + lib-typeof x 7,382,635 ops/sec ±1.17% (85 runs sampled) + + fastest is kind-of (by 220% avg) + +# symbol (34 bytes) + kind-of x 17,011,537 ops/sec ±1.24% (86 runs sampled) + lib-type-of x 3,492,454 ops/sec ±1.23% (89 runs sampled) + lib-typeof x 7,471,235 ops/sec ±2.48% (87 runs sampled) + + fastest is kind-of (by 310% avg) + +# template-strings (36 bytes) + kind-of x 15,434,250 ops/sec ±1.46% (83 runs sampled) + lib-type-of x 7,157,907 ops/sec ±0.97% (87 runs sampled) + lib-typeof x 7,517,986 ops/sec ±0.92% (86 runs sampled) + + fastest is kind-of (by 210% avg) + +# undefined (29 bytes) + kind-of x 19,167,115 ops/sec ±1.71% (87 runs sampled) + lib-type-of x 15,477,740 ops/sec ±1.63% (85 runs sampled) + lib-typeof x 19,075,495 ops/sec ±1.17% (83 runs sampled) + + fastest is lib-typeof,kind-of + +``` + +## Optimizations + +In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library: + +1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot. +2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it. +3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'` +4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written. + +## Better type checking + +kind-of seems to be more consistently "correct" than other type checking libs I've looked at. For example, here are some differing results from other popular libs: + +### [typeof](https://github.com/CodingFu/typeof) lib + +Incorrectly identifies instances of custom constructors (pretty common): + +```js +var typeOf = require('typeof'); +function Test() {} +console.log(typeOf(new Test())); +//=> 'test' +``` + +Returns `object` instead of `arguments`: + +```js +function foo() { + console.log(typeOf(arguments)) //=> 'object' +} +foo(); +``` + +### [type-of](https://github.com/ForbesLindesay/type-of) lib + +Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`: + +```js +function * foo() {} +console.log(typeOf(foo)); +//=> 'object' +console.log(typeOf(new Buffer(''))); +//=> 'object' +console.log(typeOf(new Map())); +//=> 'object' +console.log(typeOf(new Set())); +//=> 'object' +console.log(typeOf(new WeakMap())); +//=> 'object' +console.log(typeOf(new WeakSet())); +//=> 'object' +``` + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet") +* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.") +* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive. | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 98 | [jonschlinkert](https://github.com/jonschlinkert) | +| 3 | [aretecode](https://github.com/aretecode) | +| 2 | [miguelmota](https://github.com/miguelmota) | +| 1 | [dtothefp](https://github.com/dtothefp) | +| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) | +| 1 | [ksheedlo](https://github.com/ksheedlo) | +| 1 | [pdehaan](https://github.com/pdehaan) | +| 1 | [laggingreflex](https://github.com/laggingreflex) | +| 1 | [charlike-old](https://github.com/charlike-old) | + +### Author + +**Jon Schlinkert** + +* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert) +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 01, 2017._ \ No newline at end of file diff --git a/js/node_modules/use/node_modules/kind-of/index.js b/js/node_modules/use/node_modules/kind-of/index.js new file mode 100644 index 0000000..aa2bb39 --- /dev/null +++ b/js/node_modules/use/node_modules/kind-of/index.js @@ -0,0 +1,129 @@ +var toString = Object.prototype.toString; + +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; + + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + } + + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; + + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; + + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; + + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; + + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; + + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; + } + + if (isGeneratorObj(val)) { + return 'generator'; + } + + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } + + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); +}; + +function ctorName(val) { + return val.constructor ? val.constructor.name : null; +} + +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; +} + +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); +} + +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; +} + +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; +} + +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; +} + +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; +} + +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; + } + } + return false; +} + +/** + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer + */ + +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); + } + return false; +} diff --git a/js/node_modules/use/node_modules/kind-of/package.json b/js/node_modules/use/node_modules/kind-of/package.json new file mode 100644 index 0000000..691e85a --- /dev/null +++ b/js/node_modules/use/node_modules/kind-of/package.json @@ -0,0 +1,143 @@ +{ + "_from": "kind-of@^6.0.2", + "_id": "kind-of@6.0.2", + "_inBundle": false, + "_integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "_location": "/use/kind-of", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "kind-of@^6.0.2", + "name": "kind-of", + "escapedName": "kind-of", + "rawSpec": "^6.0.2", + "saveSpec": null, + "fetchSpec": "^6.0.2" + }, + "_requiredBy": [ + "/use" + ], + "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "_shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051", + "_spec": "kind-of@^6.0.2", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/use", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/kind-of/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "David Fox-Powell", + "url": "https://dtothefp.github.io/me" + }, + { + "name": "James", + "url": "https://twitter.com/aretecode" + }, + { + "name": "Jon Schlinkert", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Ken Sheedlo", + "url": "kensheedlo.com" + }, + { + "name": "laggingreflex", + "url": "https://github.com/laggingreflex" + }, + { + "name": "Miguel Mota", + "url": "https://miguelmota.com" + }, + { + "name": "Peter deHaan", + "url": "http://about.me/peterdehaan" + }, + { + "name": "tunnckoCore", + "url": "https://i.am.charlike.online" + } + ], + "deprecated": false, + "description": "Get the native type of a value.", + "devDependencies": { + "benchmarked": "^2.0.0", + "browserify": "^14.4.0", + "gulp-format-md": "^1.0.0", + "mocha": "^4.0.1", + "write": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/kind-of", + "keywords": [ + "arguments", + "array", + "boolean", + "check", + "date", + "function", + "is", + "is-type", + "is-type-of", + "kind", + "kind-of", + "number", + "object", + "of", + "regexp", + "string", + "test", + "type", + "type-of", + "typeof", + "types" + ], + "license": "MIT", + "main": "index.js", + "name": "kind-of", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/kind-of.git" + }, + "scripts": { + "prepublish": "browserify -o browser.js -e index.js -s index --bare", + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "related": { + "list": [ + "is-glob", + "is-number", + "is-primitive" + ] + }, + "reflinks": [ + "type-of", + "typeof", + "verb" + ] + }, + "version": "6.0.2" +} diff --git a/js/node_modules/use/package.json b/js/node_modules/use/package.json new file mode 100644 index 0000000..d081097 --- /dev/null +++ b/js/node_modules/use/package.json @@ -0,0 +1,111 @@ +{ + "_from": "use@^3.1.0", + "_id": "use@3.1.0", + "_inBundle": false, + "_integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "_location": "/use", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "use@^3.1.0", + "name": "use", + "escapedName": "use", + "rawSpec": "^3.1.0", + "saveSpec": null, + "fetchSpec": "^3.1.0" + }, + "_requiredBy": [ + "/snapdragon" + ], + "_resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "_shasum": "14716bf03fdfefd03040aef58d8b4b85f3a7c544", + "_spec": "use@^3.1.0", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/snapdragon", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/use/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Brian Woodward", + "url": "https://twitter.com/doowb" + }, + { + "name": "Jon Schlinkert", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Olsten Larck", + "url": "https://i.am.charlike.online" + }, + { + "url": "https://github.com/wtgtybhertgeghgtwtg" + } + ], + "dependencies": { + "kind-of": "^6.0.2" + }, + "deprecated": false, + "description": "Easily add plugin support to your node.js application.", + "devDependencies": { + "base-plugins": "^1.0.0", + "define-property": "^2.0.0", + "extend-shallow": "^3.0.1", + "gulp": "^3.9.1", + "gulp-eslint": "^4.0.0", + "gulp-format-md": "^1.0.0", + "gulp-istanbul": "^1.1.2", + "gulp-mocha": "^3.0.1", + "mocha": "^4.0.1" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/jonschlinkert/use", + "keywords": [ + "use" + ], + "license": "MIT", + "main": "index.js", + "name": "use", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/use.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "base", + "base-plugins", + "ware" + ] + }, + "reflinks": [ + "verb", + "ware" + ], + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + } + }, + "version": "3.1.0" +} diff --git a/js/node_modules/util-deprecate/History.md b/js/node_modules/util-deprecate/History.md new file mode 100644 index 0000000..acc8675 --- /dev/null +++ b/js/node_modules/util-deprecate/History.md @@ -0,0 +1,16 @@ + +1.0.2 / 2015-10-07 +================== + + * use try/catch when checking `localStorage` (#3, @kumavis) + +1.0.1 / 2014-11-25 +================== + + * browser: use `console.warn()` for deprecation calls + * browser: more jsdocs + +1.0.0 / 2014-04-30 +================== + + * initial commit diff --git a/js/node_modules/util-deprecate/LICENSE b/js/node_modules/util-deprecate/LICENSE new file mode 100644 index 0000000..6a60e8c --- /dev/null +++ b/js/node_modules/util-deprecate/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/js/node_modules/util-deprecate/README.md b/js/node_modules/util-deprecate/README.md new file mode 100644 index 0000000..75622fa --- /dev/null +++ b/js/node_modules/util-deprecate/README.md @@ -0,0 +1,53 @@ +util-deprecate +============== +### The Node.js `util.deprecate()` function with browser support + +In Node.js, this module simply re-exports the `util.deprecate()` function. + +In the web browser (i.e. via browserify), a browser-specific implementation +of the `util.deprecate()` function is used. + + +## API + +A `deprecate()` function is the only thing exposed by this module. + +``` javascript +// setup: +exports.foo = deprecate(foo, 'foo() is deprecated, use bar() instead'); + + +// users see: +foo(); +// foo() is deprecated, use bar() instead +foo(); +foo(); +``` + + +## License + +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/js/node_modules/util-deprecate/browser.js b/js/node_modules/util-deprecate/browser.js new file mode 100644 index 0000000..549ae2f --- /dev/null +++ b/js/node_modules/util-deprecate/browser.js @@ -0,0 +1,67 @@ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} diff --git a/js/node_modules/util-deprecate/node.js b/js/node_modules/util-deprecate/node.js new file mode 100644 index 0000000..5e6fcff --- /dev/null +++ b/js/node_modules/util-deprecate/node.js @@ -0,0 +1,6 @@ + +/** + * For Node.js, simply re-export the core `util.deprecate` function. + */ + +module.exports = require('util').deprecate; diff --git a/js/node_modules/util-deprecate/package.json b/js/node_modules/util-deprecate/package.json new file mode 100644 index 0000000..e43cd31 --- /dev/null +++ b/js/node_modules/util-deprecate/package.json @@ -0,0 +1,56 @@ +{ + "_from": "util-deprecate@~1.0.1", + "_id": "util-deprecate@1.0.2", + "_inBundle": false, + "_integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "_location": "/util-deprecate", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "util-deprecate@~1.0.1", + "name": "util-deprecate", + "escapedName": "util-deprecate", + "rawSpec": "~1.0.1", + "saveSpec": null, + "fetchSpec": "~1.0.1" + }, + "_requiredBy": [ + "/readable-stream" + ], + "_resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "_shasum": "450d4dc9fa70de732762fbd2d4a28981419a0ccf", + "_spec": "util-deprecate@~1.0.1", + "_where": "/Users/patrick.jackson/workspace/kotlin-multiplatform-recipes/js/node_modules/readable-stream", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io/" + }, + "browser": "browser.js", + "bugs": { + "url": "https://github.com/TooTallNate/util-deprecate/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "The Node.js `util.deprecate()` function with browser support", + "homepage": "https://github.com/TooTallNate/util-deprecate", + "keywords": [ + "util", + "deprecate", + "browserify", + "browser", + "node" + ], + "license": "MIT", + "main": "node.js", + "name": "util-deprecate", + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/util-deprecate.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.0.2" +} diff --git a/js/node_modules/walk-sync/CHANGELOG.md b/js/node_modules/walk-sync/CHANGELOG.md new file mode 100644 index 0000000..7a4591a --- /dev/null +++ b/js/node_modules/walk-sync/CHANGELOG.md @@ -0,0 +1,64 @@ +# master + +# 0.3.1 + +* whitelist index.js for publish (don't publish uneeded files) + +# 0.3.0 + +* add ignore globs + +# 0.2.7 + +* [BUGFIX] Previously `walkSync` returned entries sorted by `relativePath` + almost, but not quite, lexicographically. This now sorts lexicographically in + all cases. + +# 0.2.6 + +* On Windows, normalize backslashes in root path to forward slashes + +# 0.2.5 + +* Exclude all non-essential files from npm + +# 0.2.4 + +* Fix file entries to have a numeric timestamp rather than a `Date` + +# 0.2.3 + +* Extract matcher-collection into separate package + +# 0.2.2 + +* Add `walkSync.entries`, which returns objects instead of files + +# 0.2.1 + +* Add `directories` flag +* Allow passing the globs array as a `globs` option + +# 0.2.0 + +* Add optional `globArray` parameter + +# 0.1.3 + +* Switch to `fs.statSync` (instead of `fs.lstatSync`) to follow symlinks. + +# 0.1.2 + +* Sort readdir entries for deterministic behavior + +# 0.1.1 + +* Do not follow symlinks (as advertised) + +# 0.1.0 + +* Bump version without change, to allow for caret/tilde dependencies + +# 0.0.1 + +* Initial release diff --git a/js/node_modules/walk-sync/LICENSE b/js/node_modules/walk-sync/LICENSE new file mode 100644 index 0000000..6d4eaea --- /dev/null +++ b/js/node_modules/walk-sync/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jo Liss + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/node_modules/walk-sync/README.md b/js/node_modules/walk-sync/README.md new file mode 100644 index 0000000..dfd33a8 --- /dev/null +++ b/js/node_modules/walk-sync/README.md @@ -0,0 +1,101 @@ +# node-walk-sync + +[![Build Status](https://travis-ci.org/joliss/node-walk-sync.png?branch=master)](https://travis-ci.org/joliss/node-walk-sync) +[![Build status](https://ci.appveyor.com/api/projects/status/sqe785gqb2qfmxbx/branch/master?svg=true)](https://ci.appveyor.com/project/joliss/node-walk-sync/branch/master) + +Return an array containing all recursive files and directories under a given +directory, similar to Unix `find`. Follows symlinks. Bare-bones, but +very fast. + +Similar to [`wrench.readdirSyncRecursive`](https://github.com/ryanmcgrath/wrench-js#synchronous-operations), +but adds trailing slashes to directories. + +Not to be confused with [node-walk](https://github.com/coolaj86/node-walk), +which has both an asynchronous and a synchronous API. + +## Installation + +```bash +npm install --save walk-sync +``` + +## Usage + +```js +var walkSync = require('walk-sync'); +var paths = walkSync('project') +``` + +Given `project/one.txt` and `project/subdir/two.txt`, `paths` will be the following +array: + +```js +['one.txt', 'subdir/', 'subdir/two.txt'] +``` + +Directories come before their contents, and have a trailing forward-slash (on +all platforms). + +Symlinks are followed. + +### Entries + +Sometimes, it is important to get additional information from a walk of a +directory; for instance if the downstream consumer needs to stat the files we +can leverage the stats from the walk. + +To accommodate, `walkSync.entries(path [, options])` is also provided, instead +of returning a list of files and/or directories it returns an array of objects +which correspond to a given file or directory, except with more data. + +``` +entry.relativePath +entry.mode // => fs.statSync(fullPath).mode +entry.size // => fs.statSync(fullPath).size +entry.mtime // => fs.statSync(fullPath).mtime.getTime() + +entry.isDirectory() // => true if directory +``` + +### Options + +* `globs`: An array of globs. Only files and directories that match at least + one of the provided globs will be returned. + + ```js + var paths = walkSync('project', { globs: ['subdir/**/*.txt'] }); + // => ['subdir/two.txt'] + ``` + + As an alternative to string globs, you can pass an array of precompiled + [`minimatch.Minimatch`](https://github.com/isaacs/minimatch#minimatch-class) + instances. This is faster and allows to specify your own globbing options. + +* `directories` (default: true): Pass `false` to only return files, not + directories: + + ```js + var paths = walkSync('project', { directories: false }) + // => ['one.txt', 'subdir/two.txt'] + ``` + +* `ignore`: An array of globs. Files and directories that match at least one + of the provided globs will be pruned while searching. + + ```js + var paths = walkSync('project', { ignore: ['subdir'] }) + // => ['one.txt'] + ``` + +## Background + +`walkSync(baseDir)` is a faster substitute for + +```js +glob.sync('**', { + cwd: baseDir, + dot: true, + mark: true, + strict: true +}) +``` diff --git a/js/node_modules/walk-sync/index.js b/js/node_modules/walk-sync/index.js new file mode 100644 index 0000000..44c2ab7 --- /dev/null +++ b/js/node_modules/walk-sync/index.js @@ -0,0 +1,153 @@ +'use strict'; + +var fs = require('fs'); +var MatcherCollection = require('matcher-collection'); +var ensurePosix = require('ensure-posix-path'); +var path = require('path'); + +function handleOptions(_options) { + var options = {}; + if (Array.isArray(_options)) { + options.globs = _options; + } else if (_options) { + options = _options; + } + + return options; +} + +function handleRelativePath(_relativePath) { + if (_relativePath == null) { + return ''; + } else if (_relativePath.slice(-1) !== '/') { + return _relativePath + '/'; + } else { + return _relativePath; + } +} + +module.exports = walkSync; +function walkSync(baseDir, _options) { + var options = handleOptions(_options); + + var mapFunct; + if (options.includeBasePath) { + mapFunct = function (entry) { + return entry.basePath.split(path.sep).join('/') + '/' + entry.relativePath; + }; + } else { + mapFunct = function (entry) { + return entry.relativePath; + }; + } + + return _walkSync(baseDir, options).map(mapFunct); +} + +module.exports.entries = function entries(baseDir, _options) { + var options = handleOptions(_options); + + return _walkSync(ensurePosix(baseDir), options); +}; + +function _walkSync(baseDir, options, _relativePath) { + // Inside this function, prefer string concatenation to the slower path.join + // https://github.com/joyent/node/pull/6929 + var relativePath = handleRelativePath(_relativePath); + var globs = options.globs; + var ignorePatterns = options.ignore; + var globMatcher, ignoreMatcher; + var results = []; + + if (ignorePatterns) { + ignoreMatcher = new MatcherCollection(ignorePatterns); + } + + if (globs) { + globMatcher = new MatcherCollection(globs); + } + + if (globMatcher && !globMatcher.mayContain(relativePath)) { + return results; + } + + var names = fs.readdirSync(baseDir + '/' + relativePath); + var entries = names.map(function (name) { + var entryRelativePath = relativePath + name; + + if (ignoreMatcher && ignoreMatcher.match(entryRelativePath)) { + return; + } + + var fullPath = baseDir + '/' + entryRelativePath; + var stats = getStat(fullPath); + + if (stats && stats.isDirectory()) { + return new Entry(entryRelativePath + '/', baseDir, stats.mode, stats.size, stats.mtime.getTime()); + } else { + return new Entry(entryRelativePath, baseDir, stats && stats.mode, stats && stats.size, stats && stats.mtime.getTime()); + } + }).filter(Boolean); + + var sortedEntries = entries.sort(function (a, b) { + var aPath = a.relativePath; + var bPath = b.relativePath; + + if (aPath === bPath) { + return 0; + } else if (aPath < bPath) { + return -1; + } else { + return 1; + } + }); + + for (var i=0; i: Frameworks() { + /** + * Plug and play web framework support for express using body-parser + * @public + */ +// var express: Express + + /** + * Plug and play web framework support for lambda API gateway + * @public + */ +// var lambda: Lambda +} \ No newline at end of file diff --git a/js/src/main/kotlin/actions/expected/Expected.kt b/js/src/main/kotlin/actions/expected/Expected.kt new file mode 100644 index 0000000..62089b7 --- /dev/null +++ b/js/src/main/kotlin/actions/expected/Expected.kt @@ -0,0 +1,8 @@ +package actions.expected + +actual class GoogleAuthLib { + actual fun asyncVerify() { + + } + +} \ No newline at end of file diff --git a/js/src/main/kotlin/actions/expected/OAuth2Client.kt b/js/src/main/kotlin/actions/expected/OAuth2Client.kt new file mode 100644 index 0000000..6f5fb99 --- /dev/null +++ b/js/src/main/kotlin/actions/expected/OAuth2Client.kt @@ -0,0 +1,26 @@ +package actions.expected + +import actions.service.actionssdk.api.GoogleActionsV2Location + +actual class OAuth2Client actual constructor(clientId: String) { + actual fun verifyIdToken(idToken: IdToken): LoginTicket { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} + +actual class Date actual constructor(timeStamp: String?) { + actual fun toISOString(): String? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} + +actual val MutableMap.deliveryAddress: GoogleActionsV2Location? + get() { + val address = get("deliveryAddress") + return if (address != null) { + null + } else { + null + } + } \ No newline at end of file diff --git a/js/src/main/kotlin/actions/expected/Serializer.kt b/js/src/main/kotlin/actions/expected/Serializer.kt new file mode 100644 index 0000000..e5f87cc --- /dev/null +++ b/js/src/main/kotlin/actions/expected/Serializer.kt @@ -0,0 +1,16 @@ +package actions.expected + +actual object Serializer { + actual fun stringifyConversationToken(data: Any?): ConversationTokenData { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + actual fun serialize(any: Any?): String? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + actual fun deserializeMap(json: String): MutableMap { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} \ No newline at end of file diff --git a/js/src/main/kotlin/actions/expected/deserialize.kt b/js/src/main/kotlin/actions/expected/deserialize.kt new file mode 100644 index 0000000..69bff07 --- /dev/null +++ b/js/src/main/kotlin/actions/expected/deserialize.kt @@ -0,0 +1,5 @@ +package actions.expected + +actual fun deserialize(json: String?): T? { + return null +} diff --git a/js/src/main/kotlin/actions/expected/log.kt b/js/src/main/kotlin/actions/expected/log.kt new file mode 100644 index 0000000..9fc01e4 --- /dev/null +++ b/js/src/main/kotlin/actions/expected/log.kt @@ -0,0 +1,5 @@ +package actions.expected + +actual fun log(message: String, vararg optionalParameters: Any?) { + console.log(message) +} \ No newline at end of file diff --git a/jvm-app/build.gradle b/jvm-app/build.gradle new file mode 100644 index 0000000..6c21865 --- /dev/null +++ b/jvm-app/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'kotlin' + + + +dependencies { + compile project(':jvm') + compile group: 'org.mockito', name: 'mockito-core', version: '2.18.3' + compile libraries.kotlin_stdlib + compile('javax.servlet:javax.servlet-api:3.1.0', //todo pull into separate module + "com.google.code.gson:gson:2.8.1") +// compileProject(":common", configuration: "testArtifacts") +// compile files(project(':common').configurations.test.output.classesDir) +} +compileTestJava.dependsOn tasks.getByPath(':common:testClasses') + +task run(dependsOn: classes, type: JavaExec) { + main = 'jvm.JvmAppKt' + classpath = sourceSets.main.runtimeClasspath + ignoreExitValue(true) +} diff --git a/jvm-app/src/main/kotlin/jvm/ActionsSdkSample.kt b/jvm-app/src/main/kotlin/jvm/ActionsSdkSample.kt new file mode 100644 index 0000000..691f7c1 --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/ActionsSdkSample.kt @@ -0,0 +1,359 @@ +package jvm + +import actions.expected.logger +import actions.service.actionssdk.conversation.response.List +import actions.service.actionssdk.actionssdk +import actions.service.actionssdk.conversation.Conversation +import actions.service.actionssdk.conversation.ConversationApp +import actions.service.actionssdk.conversation.question.option.OptionItem +import actions.service.actionssdk.conversation.question.option.item +import actions.service.actionssdk.conversation.response.* +import actions.service.actionssdk.conversation.response.card.Button +import actions.service.dialogflow.dialogflow +import javax.swing.text.html.Option + + +// const valants for list and carousel selection +const val SELECTION_KEY_GOOGLE_ALLO = "googleAllo" +const val SELECTION_KEY_GOOGLE_HOME = "googleHome" +const val SELECTION_KEY_GOOGLE_PIXEL = "googlePixel" +const val SELECTION_KEY_ONE = "title" + +// const valants for image URLs +const val IMG_URL_AOG = "https://developers.google.com/actions/images/badges" + + "/XPM_BADGING_GoogleAssistant_VER.png" +const val IMG_URL_GOOGLE_ALLO = "https://allo.google.com/images/allo-logo.png" +const val IMG_URL_GOOGLE_HOME = "https://lh3.googleusercontent.com" + + "/Nu3a6F80WfixUqf_ec_vgXy_c0-0r4VLJRXjVFF_X_CIilEu8B9fT35qyTEj_PEsKw" +const val IMG_URL_GOOGLE_PIXEL = "https://storage.googleapis.com/madebygoog/v1" + + "/Pixel/Pixel_ColorPicker/Pixel_Device_Angled_Black-720w.png" + +// const valants for selected item responses +val SELECTED_ITEM_RESPONSES = mapOf( + SELECTION_KEY_ONE to "You selected the first item in the list or carousel", + SELECTION_KEY_GOOGLE_HOME to "You selected the Google Home!", + SELECTION_KEY_GOOGLE_PIXEL to "You selected the Google Home!", + SELECTION_KEY_GOOGLE_PIXEL to "You selected the Google Pixel!", + SELECTION_KEY_GOOGLE_ALLO to "You selected Google Allo!") + +private val intentSuggestions = arrayOf( + "Basic Card", + "Browse Carousel", + "Carousel", + "List", + "Media", + "Suggestions") + +val app = actionssdk({ debug = true }) + +data class MyConversation(val temp: String? = null) +data class MyArgument(val temp: String? = null, + var resultType: String? = null, + var userDescision: String? = null) + + +fun initActionsApp() { +// app.middleware((conv) => { +// conv.hasScreen = +// conv.surface.capabilities.has("actions.capability.SCREEN_OUTPUT") +// conv.hasAudioPlayback = +// conv.surface.capabilities.has("actions.capability.AUDIO_OUTPUT") +// }) + +// Welcome + app.intent("actions.intent.MAIN", "input.unknown") { conv -> + conv.ask(SimpleResponse { + speech = "Hi there!" + text = "Hello there!" + }) + conv.ask(SimpleResponse { + speech = "I can show you basic cards, lists and carousels " + + "as well as suggestions on your phone." + text = "I can show you basic cards, lists and carousels as " + + "well as suggestions." + }) + conv.ask(Suggestions(*intentSuggestions)) + } + +// React to a text intent + app.intent("actions.intent.TEXT") { conv, input -> + val rawInput = (input as String).toLowerCase() + logger.info("USER SAID " + rawInput) + when (rawInput) { + "basic card" -> basicCard(conv) + "list" -> list(conv) + "carousel" -> carousel(conv) + "normal ask" -> normalAsk(conv) + "normal bye" -> normalBye(conv) + "bye card" -> byeCard(conv) + "bye response" -> byeResponse(conv) + "suggestions", "suggestion chips" -> suggestions(conv) + "test" -> test(conv) + else -> normalAsk(conv) + + } + + +// React to list or carousel selection + app.intent("actions.intent.OPTION") { conv, params, option -> + val response = if (option != null && SELECTED_ITEM_RESPONSES.containsKey(option.textValue)) { + SELECTED_ITEM_RESPONSES[option.textValue] ?: "" + } else { + "You selected an unknown item from the list or carousel" + } + conv.ask(response) + } + } +} + +/** + * Test + */ +fun test(conv: Conversation) { +// conv.data.lastResponse = "This was the last response" +// conv.user.storage.name = "fred" + conv.ask("Can you hear me?") +} + +/** + * Normal Ask + * @param {object} conv - The conversation object. + */ +fun normalAsk(conv: Conversation) { + conv.ask("Ask me to show you a list, carousel, or basic card.") +} + +/** + * Suggestions + * @param {object} conv - The conversation object. + */ +fun suggestions(conv: Conversation) { + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + return + } + conv.ask("This is a simple response for suggestions.") + conv.ask(Suggestions("Suggestion Chips")) + conv.ask(Suggestions(*intentSuggestions)) + conv.ask(LinkOutSuggestion { + name = "Suggestion Link" + url = "https://assistant.google.com/" + }) +} + +/** + * Basic Card + * @param {object} conv - The conversation object. + */ +fun basicCard(conv: Conversation) { + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + return + } + conv.ask("This is the first simple response for a basic card.") + conv.ask(Suggestions(*intentSuggestions)) + // Create a basic card + conv.ask(BasicCard { + text = """This is a basic card. Text in a basic card can include "quotes" and + most other unicode characters including emoji 📱. Basic cards also support + some markdown formatting like * emphasis * or _italics_, **strong** or + __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other + things like line \nbreaks""" // Note the two spaces before "\n" required for + // a line break to be rendered in the card. + subtitle = "This is a subtitle" + title = "Title: this is a title" + buttons = mutableListOf(Button { + title = "This is a button" + url = "https://assistant.google.com/" + }) + image = Image { + url = IMG_URL_AOG + alt = "Image alternate text" + } + }) + conv.ask(SimpleResponse { + speech = "This is the second simple response." + text = "This is the 2nd simple response." + }) +} + +/** + * List + * @param {object} conv - The conversation object. + */ +fun list(conv: Conversation) { + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + return + } + conv.ask("This is a simple response for a list.") + conv.ask(Suggestions(*intentSuggestions)) + // Create a list + conv.ask(List { + title = "List Title" + items = mutableMapOf( + // Add the first item to the list + SELECTION_KEY_ONE to OptionItem( + synonyms = mutableListOf( + "synonym of title 1", + "synonym of title 2", + "synonym of title 3"), + + title = "Title of First List Item", + description = "This is a description of a list item.", + image = Image { + url = IMG_URL_AOG + alt = "Image alternate text" + }), + + // Add the second item to the list + SELECTION_KEY_GOOGLE_HOME to OptionItem( + synonyms = mutableListOf( + "Google Home Assistant", + "Assistant on the Google Home"), + + title = "Google Home", + description = "Google Home is a voice-activated speaker powered by " + + "the Google Assistant.", + image = Image { + url = IMG_URL_GOOGLE_HOME + alt = "Google Home" + }), + // Add the third item to the list + SELECTION_KEY_GOOGLE_PIXEL to OptionItem( + synonyms = mutableListOf( + "Google Pixel XL", + "Pixel", + "Pixel XL"), + title = "Google Pixel", + description = "Pixel. Phone by Google.", + image = Image { + url = IMG_URL_GOOGLE_PIXEL + alt = "Google Pixel" + }), + // Add the last item to the list + SELECTION_KEY_GOOGLE_ALLO to OptionItem( + title = "Google Allo", + synonyms = mutableListOf("Allo"), + description = "Introducing Google Allo, a smart messaging app that " + + "helps you say more and do more.", + image = Image { + url = IMG_URL_GOOGLE_ALLO + alt = "Google Allo Logo" + }) + ) + + }) +} + +/** + * Carousel + * @param {object} conv - The conversation object. + */ +fun carousel(conv: Conversation) { + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + return + } + conv.ask("This is a simple response for a carousel.") + conv.ask(Suggestions(*intentSuggestions)) + // Create a carousel + conv.ask(Carousel { + items = mutableMapOf( + // Add the first item to the carousel + SELECTION_KEY_ONE to OptionItem( + synonyms = mutableListOf( + "synonym of title 1", + "synonym of title 2", + "synonym of title 3"), + + title = "Title of First Carousel Item", + description = "This is a description of a carousel item.", + image = Image { + url = IMG_URL_AOG + alt = "Image alternate text" + }), + // Add the second item to the carousel + SELECTION_KEY_GOOGLE_HOME to OptionItem( + synonyms = mutableListOf( + "Google Home Assistant", + "Assistant on the Google Home"), + title = "Google Home", + description = "Google Home is a voice-activated speaker powered by " + + "the Google Assistant.", + image = Image { + url = IMG_URL_GOOGLE_HOME + alt = "Google Home" + }), + // Add third item to the carousel + SELECTION_KEY_GOOGLE_PIXEL to OptionItem( + synonyms = mutableListOf( + "Google Pixel XL", + "Pixel", + "Pixel XL"), + title = "Google Pixel", + description = "Pixel. Phone by Google.", + image = Image { + url = IMG_URL_GOOGLE_PIXEL + alt = "Google Pixel" + }), + // Add last item of the carousel + SELECTION_KEY_GOOGLE_ALLO to OptionItem( + title = "Google Allo", + synonyms = mutableListOf( + "Allo"), + description = "Introducing Google Allo, a smart messaging app that " + + "helps you say more and do more.", + image = Image { + url = IMG_URL_GOOGLE_ALLO + alt = "Google Allo Logo" + }) + ) + }) +} + +/** + * Leave conversation with card + * @param {object} conv - The conversation object. + */ +fun byeCard(conv: Conversation) { + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the phone " + + "surface in the simulator.") + return + } + conv.ask("Goodbye, World!") + conv.close(BasicCard { + text = "This is a goodbye card." + }) +} + +/** + * Leave conversation with SimpleResponse + * @param {object} conv - The conversation object. + */ +fun byeResponse(conv: Conversation) { + conv.close(SimpleResponse { + speech = "Okay see you later" + text = "OK see you later!" + }) +} + +/** + * Leave conversation + * @param {object} conv - The conversation object. + */ +fun normalBye(conv: Conversation) { + conv.close("Okay see you later!") +} + +//fun wrapper(arg1, arg2) { +// console.log("arg1: ", JSON.stringify(arg1.body)) +// app(arg1, arg2) +// console.log("arg2: ", arg2) +// logResponseBody(arg1, arg2) +//} diff --git a/jvm-app/src/main/kotlin/jvm/AogMockFactory.kt b/jvm-app/src/main/kotlin/jvm/AogMockFactory.kt new file mode 100644 index 0000000..aafe803 --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/AogMockFactory.kt @@ -0,0 +1,7 @@ +package actions + +object AogMockFactory { + fun mockWelcome() { + + } +} \ No newline at end of file diff --git a/jvm-app/src/main/kotlin/jvm/AogSample.kt b/jvm-app/src/main/kotlin/jvm/AogSample.kt new file mode 100644 index 0000000..f6e9c83 --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/AogSample.kt @@ -0,0 +1,84 @@ +package jvm + +import actions.AogMockFactory +import actions.MockResponses +import actions.expected.ServletFramework +import actions.expected.logger +import actions.service.actionssdk.actionssdk +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.Conversation +import actions.service.actionssdk.conversation.SurfaceCapability +import org.mockito.Mockito.`when` +import org.mockito.Mockito.mock +import java.io.ByteArrayInputStream +import java.io.PrintWriter +import java.io.StringWriter +import java.util.* +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +data class UserStorage(var name: String? = null) + +fun Conversation.hasScreen(): Boolean = surface.capabilities?.has(SurfaceCapability.ACTIONS_CAPABILITY_SCREEN_OUTPUT) + ?: false + +fun Conversation.hasAudioPlayback(): Boolean = surface.capabilities?.has(SurfaceCapability.ACTIONS_CAPABILITY_AUDIO_OUTPUT) + ?: false + +fun servlet() { + val app = actionssdk() {} + app.frameworks.add(ServletFramework()) + + app.intent("actions.intent.MAIN", "actions.intent.TEXT") { conv -> + conv.data["lastResponse"] = "This was the last response" + conv.user.storage = UserStorage(name = "fred") + conv.ask("Can you hear me?") + + } + + app.intent("actions.intent.TEXT") { conv, input -> + val rawInput = (input as String).toLowerCase() + logger.info("USER SAID $rawInput") + when (rawInput) { + "basic card" -> basicCard(conv) + else -> normalAsk(conv) + } + + } + + AogMockFactory.mockWelcome() + val req: HttpServletRequest = getMockHttpReq(MockResponses.basicCard) + val resp: HttpServletResponse = getMockHttpResp() + app(req, resp) +} + +fun getMockHttpReq(body: String): HttpServletRequest { + val headers = mutableMapOf("Content-Type" to "json/application") + val iterator = headers.keys.iterator() + val headerNames = object : Enumeration { + override fun hasMoreElements(): Boolean = iterator.hasNext() + override fun nextElement(): String = iterator.next() + } + + val req = mock(HttpServletRequest::class.java) + `when`(req.headerNames).thenReturn(headerNames) + + `when`(req.inputStream).thenReturn(DelegatingServletInputStream(ByteArrayInputStream(body.toByteArray()))) + + return req +} + +fun getMockHttpResp(): HttpServletResponse { + val resp = mock(HttpServletResponse::class.java) + `when`(resp.writer).thenReturn(PrintWriter(StringWriter())) + + return resp +} + +fun testBody(): GoogleActionsV2AppRequest { + val user = GoogleActionsV2User(userId = "test1234") + val req = GoogleActionsV2AppRequest() + return req +} + + diff --git a/jvm-app/src/main/kotlin/jvm/DelegationServletInputStream.kt b/jvm-app/src/main/kotlin/jvm/DelegationServletInputStream.kt new file mode 100644 index 0000000..9e1286d --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/DelegationServletInputStream.kt @@ -0,0 +1,60 @@ +package jvm + +import java.io.InputStream +import javax.servlet.ReadListener +import javax.servlet.ServletInputStream + + +class DelegatingServletInputStream(val inputStream: InputStream) : ServletInputStream() { + + override fun isFinished(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setReadListener(readListener: ReadListener?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isReady(): Boolean = true + + override fun read(): Int { + return inputStream.read() + } + + override fun read(p0: ByteArray?): Int { + return inputStream.read(p0) + } + + override fun read(p0: ByteArray?, p1: Int, p2: Int): Int { + return inputStream.read(p0, p1, p2) + } + + override fun skip(p0: Long): Long { + return inputStream.skip(p0) + } + + override fun readLine(b: ByteArray?, off: Int, len: Int): Int { + TODO("NOT IMPLEMENTED") + } + + override fun available(): Int { + return inputStream.available() + } + + override fun reset() { + inputStream.reset() + } + + override fun mark(p0: Int) { + inputStream.mark(p0) + } + + override fun markSupported(): Boolean { + return inputStream.markSupported() + } + + override fun close() { + super.close() + inputStream.close() + } +} diff --git a/jvm-app/src/main/kotlin/jvm/DfSampleTransactions.kt b/jvm-app/src/main/kotlin/jvm/DfSampleTransactions.kt new file mode 100644 index 0000000..a0a2c7c --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/DfSampleTransactions.kt @@ -0,0 +1,297 @@ +package jvm + +import actions.ApiClientObjectMap +import actions.expected.deliveryAddress +import actions.expected.log +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.question.transaction.DeliveryAddress +import actions.service.actionssdk.conversation.question.transaction.TransactionDecision +import actions.service.actionssdk.conversation.question.transaction.TransactionRequirements +import actions.service.actionssdk.conversation.response.OrderUpdate +import actions.service.dialogflow.DialogflowApp + + +const val GENERIC_EXTENSION_TYPE = + "type.googleapis.com/google.actions.v2.orders.GenericExtension" +const val UNIQUE_ORDER_ID = "" + +fun initTransactionSample(dfApp: DialogflowApp<*, *, *>) { + + dfApp.intent("transaction.check.action") { conv -> + conv.hasScreen() + conv.ask(TransactionRequirements { + orderOptions = GoogleActionsV2OrdersOrderOptions( + requestDeliveryAddress = false) + paymentOptions = GoogleActionsV2OrdersPaymentOptions( + actionProvidedOptions = GoogleActionsV2OrdersActionProvidedPaymentOptions( + displayName = "VISA-1234", + paymentType = GoogleActionsV2OrdersActionProvidedPaymentOptionsPaymentType.PAYMENT_CARD) + ) + }) + } + + dfApp.intent("transaction.check.google") { conv -> + conv.ask(TransactionRequirements { + orderOptions = GoogleActionsV2OrdersOrderOptions(requestDeliveryAddress = false) + paymentOptions = GoogleActionsV2OrdersPaymentOptions( + googleProvidedOptions = GoogleActionsV2OrdersGoogleProvidedPaymentOptions( + prepaidCardDisallowed = false, + supportedCardNetworks = mutableListOf(GoogleActionsV2OrdersGoogleProvidedPaymentOptionsSupportedCardNetworks.VISA, GoogleActionsV2OrdersGoogleProvidedPaymentOptionsSupportedCardNetworks.AMEX), + // These will be provided by payment processor, + // like Stripe, Braintree, or Vantiv. + tokenizationParameters = GoogleActionsV2OrdersPaymentMethodTokenizationParameters())) + }) + } + + dfApp.intent("transaction.check.complete") { conv -> + val arg = conv.arguments.get("TRANSACTION_REQUIREMENTS_CHECK_RESULT") + if (arg != null && arg.resultType == GoogleActionsV2TransactionRequirementsCheckResultResultType.OK) { + // Normally take the user through cart building flow + conv.ask("""Looks like you're good to go! + Try saying "Get Delivery Address".""") + } else { + conv.close("Transaction failed.") + } + } + + dfApp.intent("delivery.address") { conv -> + conv.ask(DeliveryAddress { + addressOptions = GoogleActionsV2DeliveryAddressValueSpecAddressOptions( + reason = "To know where to send the order") + }) + } + + dfApp.intent("delivery.address.complete") { conv -> + val arg = conv.arguments.get("DELIVERY_ADDRESS_VALUE") + if (arg?.userDecision == "ACCEPTED") { + log("DELIVERY ADDRESS: " + + arg.location?.postalAddress?.addressLines?.get(0)) + conv.data["deliveryAddress"] = arg.location + conv.ask("""Great, got your address! Now say " confirm transaction".""") + } else { + conv.close("I failed to get your delivery address.") + } + } + + dfApp.intent("transaction.decision.action") { conv -> + val order = order { + id = UNIQUE_ORDER_ID + cart { + merchant { + id = "book_store_1" + name = "Book Store" + } + lineItems({ + name = "My Memoirs" + id = "memoirs_1" + price { + amount { + currencyCode = "USD" + nanos = 990000000 + units = 3 + } + type = GoogleActionsV2OrdersPriceType.ACTUAL + } + quantity = 1 + subLines({ + note = "Note from the author" + }) + type = GoogleActionsV2OrdersLineItemType.REGULAR + }, { + name = "Memoirs of a person" + id = "memoirs_2" + price { + amount { + currencyCode = "USD" + nanos = 990000000 + units = 5 + } + type = GoogleActionsV2OrdersPriceType.ACTUAL + } + quantity = 1 + subLines({ + note = "Special introduction by author" + }) + type = GoogleActionsV2OrdersLineItemType.REGULAR + }, { + name = "Their memoirs" + id = "memoirs_3" + price { + amount { + currencyCode = "USD" + nanos = 750000000 + units = 15 + } + type = GoogleActionsV2OrdersPriceType.ACTUAL + } + quantity = 1 + subLines({ + lineItem { + name = "Special memoir epilogue" + id = "memoirs_epilogue" + price { + amount { + currencyCode = "USD" + nanos = 990000000 + units = 3 + } + type = GoogleActionsV2OrdersPriceType.ACTUAL + } + quantity = 1 + type = GoogleActionsV2OrdersLineItemType.REGULAR + } + }) + type = GoogleActionsV2OrdersLineItemType.REGULAR + }, { + name = "Our memoirs" + id = "memoirs_4" + price { + amount { + currencyCode = "USD" + nanos = 490000000 + units = 6 + } + type = GoogleActionsV2OrdersPriceType.ACTUAL + } + quantity = 1 + subLines({ + note = "Special introduction by author" + }) + type = GoogleActionsV2OrdersLineItemType.REGULAR + }) + notes = "The Memoir collection" + otherItems({ + name = "Subtotal" + id = "subtotal" + price { + amount { + currencyCode = "USD" + nanos = 220000000 + units = 32 + } + type = GoogleActionsV2OrdersPriceType.ESTIMATE + } + type = GoogleActionsV2OrdersLineItemType.SUBTOTAL + }, { + name = "Tax" + id = "tax" + price { + amount { + currencyCode = "USD" + nanos = 780000000 + units = 2 + } + type = GoogleActionsV2OrdersPriceType.ESTIMATE + } + type = GoogleActionsV2OrdersLineItemType.TAX + }) + } + otherItems = mutableListOf() + totalPrice { + amount { + currencyCode = "USD" + nanos = 0 + units = 35 + } + type = GoogleActionsV2OrdersPriceType.ESTIMATE + } + } + + if (conv.data["deliveryAddress"] != null) { + order.extension { + `@type` = GENERIC_EXTENSION_TYPE + locations({ + type = GoogleActionsV2OrdersOrderLocationType.DELIVERY + location { + postalAddress = conv.data.deliveryAddress?.postalAddress + } + }) + } + } + + // To test payment w/ sample, + // uncheck the "Testing in Sandbox Mode" box in the + // Actions console simulator + conv.ask(TransactionDecision { + orderOptions { + requestDeliveryAddress = true + } + paymentOptions { + actionProvidedOptions { + paymentType = GoogleActionsV2OrdersActionProvidedPaymentOptionsPaymentType.PAYMENT_CARD + displayName = "VISA-1234" + } + proposedOrder = order + } + }) + + /* + // If using Google provided payment instrument instead + conv.ask(new TransactionDecision({ + orderOptions: { + requestDeliveryAddress: false, + }, + paymentOptions: { + googleProvidedOptions: { + prepaidCardDisallowed: false, + supportedCardNetworks: ["VISA", "AMEX"], + // These will be provided by payment processor, + // like Stripe, Braintree, or Vantiv. + tokenizationParameters: {}, + }, + }, + proposedOrder: order, + })) + */ + } + + dfApp.intent("transaction.decision.complete") { conv -> + log("Transaction decision complete") + val arg = conv.arguments.get("TRANSACTION_DECISION_VALUE") + if (arg != null && arg.userDecision == "ORDER_ACCEPTED") { + val finalOrderId = arg.order?.finalOrder?.id + + // Confirm order and make any charges in order processing backend + // If using Google provided payment instrument: + // val paymentDisplayName = arg.order.paymentInfo.displayName + conv.ask(OrderUpdate { + actionOrderId = finalOrderId + orderState { + label = "Order created" + state = "CREATED" + } + lineItemUpdates = ApiClientObjectMap() + //TODO make setting updatetime easier + updateTime = GoogleTypeTimeOfDay() + receipt { + confirmedActionOrderId = UNIQUE_ORDER_ID + } + // Replace the URL with your own customer service page + orderManagementActions({ + button { + openUrlAction { + url = "http://example.com/customer-service" + } + title = "Customer Service" + } + type = GoogleActionsV2OrdersOrderUpdateActionType.CUSTOMER_SERVICE + }) + userNotification { + text = "Notification text." + title = "Notification Title" + } + }) + conv.ask("Transaction completed! You're all set!") + } else if (arg != null && arg.userDecision == "DELIVERY_ADDRESS_UPDATED") { + conv.ask(DeliveryAddress { + addressOptions { + reason = "To know where to send the order" + } + }) + } else { + conv.close("Transaction failed.") + } + } + +} + diff --git a/jvm-app/src/main/kotlin/jvm/DialogflowSample.kt b/jvm-app/src/main/kotlin/jvm/DialogflowSample.kt new file mode 100644 index 0000000..e32e34b --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/DialogflowSample.kt @@ -0,0 +1,392 @@ +package jvm + +import actions.service.actionssdk.conversation.question.option.OptionItem +import actions.service.actionssdk.conversation.response.List +import actions.service.actionssdk.conversation.response.* +import actions.service.actionssdk.conversation.response.card.Button +import actions.service.dialogflow.dialogflow + + +// Constant for image URLs +val IMG_URL_MEDIA = "http://storage.googleapis.com/automotive-media/album_art.jpg" +val MEDIA_SOURCE = "http://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3" + +private val intentSuggestions = arrayOf( + "Basic Card", + "Browse Carousel", + "Carousel", + "List", + "Media", + "Suggestions", + "Table", + "Test") + +val dfApp = dialogflow({ debug = true }) + +fun initDf() { + +// app.middleware {(conv) -> { +// conv.hasScreen = +// conv.surface.capabilities.has("actions.capability.SCREEN_OUTPUT") +// conv.hasAudioPlayback = +// conv.surface.capabilities.has("actions.capability.AUDIO_OUTPUT") +// } } + +// Test + dfApp.intent("test") { conv -> + conv.ask("Can you hear me?") + } + +// Welcome + dfApp.intent("input.welcome") { conv -> + conv.ask(SimpleResponse { + speech = "Hi there!" + text = "Hello there!" + }) + conv.ask(SimpleResponse { + speech = "I can show you basic cards, lists and carousels " + + "as well as suggestions on your phone." + text = "I can show you basic cards, lists and carousels as " + + "well as suggestions." + }) + conv.ask(Suggestions(*intentSuggestions)) + } + + dfApp.intent("normal.ask") { conv -> + conv.ask("Ask me to show you a list, carousel, or basic card.") + } + +// Suggestions + dfApp.intent("suggestions") { conv -> + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + conv.ask("This is a simple response for suggestions.") + conv.ask(Suggestions("Suggestion Chips")) + conv.ask(Suggestions(*intentSuggestions)) + conv.ask(LinkOutSuggestion { + name = "Suggestion Link" + url = "https://assistant.google.com/" + }) + } + } + +// Basic card + dfApp.intent("basic.card") { conv -> + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + conv.ask("This is the first simple response for a basic card.") + conv.ask(Suggestions(*intentSuggestions)) + // Create a basic card + conv.ask(BasicCard { + text = """This is a basic card. Text in a basic card can include "quotes" and + most other unicode characters including emoji 📱. Basic cards also support + some markdown formatting like * emphasis * or _italics_, **strong** or + __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other + things like line \nbreaks""" // Note the two spaces before "\n" required for + // a line break to be rendered in the card. + subtitle = "This is a subtitle" + title = "Title: this is a title" + buttons = mutableListOf(Button { + title = "This is a button" + url = "https://assistant.google.com/" + }) + image = Image { + url = IMG_URL_AOG + alt = "Image alternate text" + } + }) + conv.ask(SimpleResponse { + speech = "This is the second simple response." + text = "This is the 2nd simple response." + }) + } + } + +// List + dfApp.intent("list") { conv -> + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + conv.ask("This is a simple response for a list.") + conv.ask(Suggestions(*intentSuggestions)) + // Create a list + conv.ask(List { + title = "List Title" + items = mutableMapOf( + // Add the first item to the list + SELECTION_KEY_ONE to OptionItem( + synonyms = mutableListOf( + "synonym of title 1", + "synonym of title 2", + "synonym of title 3" + ), + title = "Title of First List Item", + description = "This is a description of a list item.", + image = Image { + url = IMG_URL_AOG + alt = "Image alternate text" + }), + // Add the second item to the list + SELECTION_KEY_GOOGLE_HOME to OptionItem( + synonyms = mutableListOf( + "Google Home Assistant", + "Assistant on the Google Home" + ), + title = "Google Home", + description = "Google Home is a voice-activated speaker powered by " + + "the Google Assistant.", + image = Image { + url = IMG_URL_GOOGLE_HOME + alt = "Google Home" + }), + // Add the third item to the list + SELECTION_KEY_GOOGLE_PIXEL to OptionItem( + synonyms = mutableListOf( + "Google Pixel XL", + "Pixel", + "Pixel XL" + ), + title = "Google Pixel", + description = "Pixel. Phone by Google.", + image = Image { + url = IMG_URL_GOOGLE_PIXEL + alt = "Google Pixel" + }), + // Add the last item to the list + SELECTION_KEY_GOOGLE_ALLO to OptionItem( + title = "Google Allo", + synonyms = mutableListOf( + "Allo" + ), + description = "Introducing Google Allo, a smart messaging app that " + + "helps you say more and do more.", + image = Image { + url = IMG_URL_GOOGLE_ALLO + alt = "Google Allo Logo" + })) + }) + } + } + +// Carousel + dfApp.intent("carousel") { conv -> + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + conv.ask("This is a simple response for a carousel.") + conv.ask(Suggestions(*intentSuggestions)) + // Create a carousel + conv.ask(Carousel { + items = mutableMapOf( + // Add the first item to the carousel + SELECTION_KEY_ONE to OptionItem( + synonyms = mutableListOf( + "synonym of title 1", + "synonym of title 2", + "synonym of title 3" + ), + title = "Title of First Carousel Item", + description = "This is a description of a carousel item.", + image = Image { + url = IMG_URL_AOG + alt = "Image alternate text" + }), + // Add the second item to the carousel + SELECTION_KEY_GOOGLE_HOME to OptionItem( + synonyms = mutableListOf( + "Google Home Assistant", + "Assistant on the Google Home" + ), + title = "Google Home", + description = "Google Home is a voice-activated speaker powered by " + + "the Google Assistant.", + image = Image { + url = IMG_URL_GOOGLE_HOME + alt = "Google Home" + }), + // Add third item to the carousel + SELECTION_KEY_GOOGLE_PIXEL to OptionItem( + synonyms = mutableListOf( + "Google Pixel XL", + "Pixel", + "Pixel XL"), + title = "Google Pixel", + description = "Pixel. Phone by Google.", + image = Image { + url = IMG_URL_GOOGLE_PIXEL + alt = "Google Pixel" + }), + // Add last item of the carousel + SELECTION_KEY_GOOGLE_ALLO to OptionItem( + title = "Google Allo", + synonyms = mutableListOf( + "Allo" + ), + description = "Introducing Google Allo, a smart messaging app that " + + "helps you say more and do more.", + image = Image { + url = IMG_URL_GOOGLE_ALLO + alt = "Google Allo Logo" + })) + }) + } + } + +// Browse Carousel + dfApp.intent("browse.carousel") { conv -> + val a11yText = "Google Assistant Bubbles" + val googleUrl = "https://google.com" + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + conv.ask("""This is an example of a "Browse Carousel"""") + // Create a browse carousel + conv.ask(BrowseCarousel { + items = mutableListOf( + BrowseCarouselItem { + title = "Title of item 1" + url = googleUrl + description = "Description of item 1" + image = Image { + url = IMG_URL_AOG + alt = a11yText + } + footer = "Item 1 footer" + }, + BrowseCarouselItem { + title = "Title of item 2" + url = googleUrl + description = "Description of item 2" + image = Image { + url = IMG_URL_AOG + alt = a11yText + } + footer = "Item 2 footer" + }) + }) + conv.ask(Suggestions(*intentSuggestions)) + } + } + +// Media response + dfApp.intent("media.response") { conv -> + if (!conv.hasAudioPlayback()) { + conv.ask("Sorry, this device does not support audio playback.") + } else { + conv.ask("This is the first simple response for a media response") + conv.ask(MediaObject { + name = "Jazz in Paris" + url = MEDIA_SOURCE + description = "A funky Jazz tune" + icon = Image { + url = IMG_URL_MEDIA + alt = "Media icon" + } + }) + conv.ask(Suggestions(*intentSuggestions)) + } + } + +// Handle a media status event + dfApp.intent("media.status") { conv -> + val mediaStatus = conv.arguments.get("MEDIA_STATUS") + var response = "Unknown media status received." + if (mediaStatus != null && mediaStatus.status?.message == "FINISHED") { + response = "Hope you enjoyed the tunes!" + } + conv.ask(response) + conv.ask(Suggestions(*intentSuggestions)) + } + +// React to list or carousel selection + dfApp.intent("item.selected") { conv, params, option -> + { + var response = "You did not select any item from the list or carousel" + response = if (option != null && SELECTED_ITEM_RESPONSES.containsKey(option.textValue)) { + SELECTED_ITEM_RESPONSES[option.textValue]!! + } else { + "You selected an unknown item from the list or carousel" + } + conv.ask(response) + } + } + + dfApp.intent("card.builder") { conv -> + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + //TODO implement incoming +// conv.ask(conv.incoming) + + conv.ask(BasicCard { + text = """Actions on Google let you build for + the Google Assistant.Reach users right when they need you . Users don’t + need to pre - enable skills or install new apps . \n \nThis was written + in the fulfillment webhook!""" + subtitle = "Engage users through the Google Assistant" + title = "Actions on Google" + buttons = mutableListOf(Button { + title = "Developer Site" + url = "https://developers.google.com/actions/" + }) + image = Image { + url = IMG_URL_AOG + alt = "Actions on Google" + } + }) + } + } + + dfApp.intent("table.builder") { conv -> + { + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the " + + "phone surface in the simulator.") + } else { + conv.ask("You can include table data like this") + conv.ask(Table { + dividers = true +// columns = mutableListOf(TableColumn("header 1", "header 2", "header 3")) +// rows = mutableListOf( +// mutableListOf("row 1 item 1", "row 1 item 2", "row 1 item 3"), +// mutableListOf("row 2 item 1", "row 2 item 2", "row 2 item 3") +// ) + }) + } + } + } + +// Leave conversation with card + app.intent("bye.card") { conv -> + if (!conv.hasScreen()) { + conv.ask("Sorry, try this on a screen device or select the phone " + + "surface in the simulator.") + } + conv.ask("Goodbye, World!") + conv.close(BasicCard { + text = "This is a goodbye card." + }) + } + +// Leave conversation with SimpleResponse + app.intent("bye.response") { conv -> + conv.close(SimpleResponse { + speech = "Okay see you later" + text = "OK see you later!" + }) + } + +// Leave conversation + app.intent("normal.bye") { conv -> + conv.close("Okay see you later!") + } + +} diff --git a/jvm-app/src/main/kotlin/jvm/JvmApp.kt b/jvm-app/src/main/kotlin/jvm/JvmApp.kt new file mode 100644 index 0000000..a1a07bb --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/JvmApp.kt @@ -0,0 +1,6 @@ +package jvm + +fun main(arguments: Array) { + System.out.println("HERE!") + servlet() +} diff --git a/jvm-app/src/main/kotlin/jvm/Requests.kt b/jvm-app/src/main/kotlin/jvm/Requests.kt new file mode 100644 index 0000000..1083425 --- /dev/null +++ b/jvm-app/src/main/kotlin/jvm/Requests.kt @@ -0,0 +1,131 @@ +package actions + +object MockResponses { + const val welcome = """{ +"user":{ +"userId":"APhe68EmFG8L689xcinHdNbpSadP", +"locale":"en-US", +"lastSeen":"2018-05-22T01:38:28Z", +"userStorage":"{\"data\":{}}" +}, +"conversation":{ +"conversationId":"1526953174329", +"type":"ACTIVE", +"conversationToken":"{\"data\":{}}" +}, +"inputs":[ +{ +"intent":"actions.intent.TEXT", +"rawInputs":[ +{ +"inputType":"TOUCH", +"query":"Basic Card" +} +], +"arguments":[ +{ +"name":"text", +"rawText":"Basic Card", +"textValue":"Basic Card" +} +] +} +], +"surface":{ +"capabilities":[ +{ +"name":"actions.capability.MEDIA_RESPONSE_AUDIO" +}, +{ +"name":"actions.capability.WEB_BROWSER" +}, +{ +"name":"actions.capability.AUDIO_OUTPUT" +}, +{ +"name":"actions.capability.SCREEN_OUTPUT" +} +] +}, +"isInSandbox":true, +"availableSurfaces":[ +{ +"capabilities":[ +{ +"name":"actions.capability.WEB_BROWSER" +}, +{ +"name":"actions.capability.AUDIO_OUTPUT" +}, +{ +"name":"actions.capability.SCREEN_OUTPUT" +} +] +} +] +}""" + + const val basicCard = """{ + "user":{ + "userId":"APhe68EmFG8L689xcinHdNbpSadP", + "locale":"en-US", + "lastSeen":"2018-05-22T01:38:28Z", + "userStorage":"{\"data\":{}}" + }, + "conversation":{ + "conversationId":"1526953174329", + "type":"ACTIVE", + "conversationToken":"{\"data\":{}}" + }, + "inputs":[ + { + "intent":"actions.intent.TEXT", + "rawInputs":[ + { + "inputType":"TOUCH", + "query":"Basic Card" + } + ], + "arguments":[ + { + "name":"text", + "rawText":"Basic Card", + "textValue":"Basic Card" + } + ] + } + ], + "surface":{ + "capabilities":[ + { + "name":"actions.capability.MEDIA_RESPONSE_AUDIO" + }, + { + "name":"actions.capability.WEB_BROWSER" + }, + { + "name":"actions.capability.AUDIO_OUTPUT" + }, + { + "name":"actions.capability.SCREEN_OUTPUT" + } + ] + }, + "isInSandbox":true, + "availableSurfaces":[ + { + "capabilities":[ + { + "name":"actions.capability.WEB_BROWSER" + }, + { + "name":"actions.capability.AUDIO_OUTPUT" + }, + { + "name":"actions.capability.SCREEN_OUTPUT" + } + ] + } + ] +}""" +} diff --git a/sdk-gson-servlet/build.gradle b/jvm/build.gradle similarity index 77% rename from sdk-gson-servlet/build.gradle rename to jvm/build.gradle index c14507a..9092836 100644 --- a/sdk-gson-servlet/build.gradle +++ b/jvm/build.gradle @@ -1,23 +1,37 @@ buildscript { + repositories { jcenter() + maven { url "https://plugins.gradle.org/m2/" } } dependencies { - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$project.ext.kotlinVersion" + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' } } -repositories { - mavenCentral() -} -apply plugin: 'idea' -apply plugin: 'kotlin' -apply plugin: 'java' -apply plugin: 'war' -apply plugin: 'com.jfrog.bintray' +apply plugin: 'kotlin-platform-jvm' apply plugin: 'maven-publish' +apply plugin: 'com.jfrog.bintray' +archivesBaseName = 'actions-on-google-kotlin' + +dependencies { + expectedBy project(':common') + compile libraries.kotlin_stdlib + testCompile libraries.kotlin_test_junit + + compile('javax.servlet:javax.servlet-api:3.1.0', //todo pull into separate module + "com.google.code.gson:gson:2.8.1") +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +artifacts { + archives sourcesJar +} bintray { user = JCENTER_USERNAME @@ -29,9 +43,9 @@ bintray { licenses = ['Apache-2.0'] vcsUrl = 'https://github.com/TicketmasterMobileStudio/actions-on-google-kotlin' version { - name = project.ext.sdkVersion + name = sdkVersion desc = 'Actions on Google SDK for java - Servlet & Gson' - vcsTag = project.ext.sdkVersion + vcsTag = sdkVersion released = new Date() } } @@ -39,11 +53,6 @@ bintray { } -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource -} - task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir @@ -84,7 +93,7 @@ publishing { artifact javadocJar groupId 'com.tmsdurham.actions' artifactId 'actions-on-google' - version project.ext.sdkVersion + version sdkVersion pom.withXml { def root = asNode() root.appendNode('description', 'Unofficial Actions on Google Client Library for Kolin/Java') @@ -94,16 +103,4 @@ publishing { } } } -} - -dependencies { - compile('javax.servlet:javax.servlet-api:3.1.0', - "com.google.code.gson:gson:$project.ext.gsonVersion", - "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$project.ext.kotlinVersion") - compile project(':sdk') -} - - -sourceCompatibility = "1.8" -targetCompatibility = "1.8" - +} \ No newline at end of file diff --git a/jvm/src/main/java/actions/expected/BuiltinFrameworks.kt b/jvm/src/main/java/actions/expected/BuiltinFrameworks.kt new file mode 100644 index 0000000..4557404 --- /dev/null +++ b/jvm/src/main/java/actions/expected/BuiltinFrameworks.kt @@ -0,0 +1,87 @@ +package actions.expected + +import actions.framework.* +import actions.service.actionssdk.api.GoogleActionsV2AppRequest +import actions.service.dialogflow.api.DialogflowV1WebhookRequest +import actions.service.dialogflow.api.GoogleCloudDialogflowV2WebhookRequest +import actions.service.dialogflow.api.GoogleCloudDialogflowV2WebhookResponse +import java.io.InputStream +import java.io.InputStreamReader +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +actual class BuiltinFrameworks : Frameworks() { + init { +// add(ServletFramework()) + //add frameworks + } +} + + +class ServletHandler(val standardHandler: StandardHandler) : OmniHandler { + + override fun handle(vararg args: Any): Any { + log("Servlet Handler: handle $args") + val req = args[0] as HttpServletRequest + val headers = req.getAoGHeaders() + //TODO check for debug flag for logging + val copies = ServletUtils.copyBuffer(req.inputStream) + logger.info(ServletUtils.getBody(copies[0], null)) + log(headers.toString()) + val body: GoogleCloudDialogflowV2WebhookRequest = requestToDialogflowV2Request(copies[1]) + log("Request: $body") + val resp = args[1] as HttpServletResponse + + + val standardResponse = standardHandler.handle(body, headers) + resp.status = standardResponse.status!! + standardResponse.headers?.forEach { + val name = it.key + it.value.forEach { + resp.setHeader(name, it) + } + } + + val respJson = standardResponse.serialize() + log("Response: $respJson") + resp.writer.write(respJson) + return this + } + + fun requestToActionsSdkRequest(inputStream: InputStream): GoogleActionsV2AppRequest { +// val options = ActionsSdkConversationOptions(body = GoogleActionsV2AppRequest(), headers = null) + return Serializer.aogGson.fromJson(InputStreamReader(inputStream), GoogleActionsV2AppRequest::class.java) + } + + fun requestToDialogflowV1Request(inputStream: InputStream): DialogflowV1WebhookRequest { +// val options = ActionsSdkConversationOptions(body = GoogleActionsV2AppRequest(), headers = null) + return Serializer.aogGson.fromJson(InputStreamReader(inputStream), DialogflowV1WebhookRequest::class.java) + } + + fun requestToDialogflowV2Request(inputStream: InputStream): GoogleCloudDialogflowV2WebhookRequest { +// val options = ActionsSdkConversationOptions(body = GoogleActionsV2AppRequest(), headers = null) + return Serializer.aogGson.fromJson(InputStreamReader(inputStream), GoogleCloudDialogflowV2WebhookRequest::class.java) + } + + fun StandardResponse.serialize(): String? { + return Serializer.aogGson.toJson(this.body, GoogleCloudDialogflowV2WebhookResponse::class.java) + } + + fun HttpServletRequest.getAoGHeaders(): Headers = + headerNames.asSequence().associate { it to getHeaders(it) }.toMutableMap() as Headers +} +//typealias ServletHandler = (HttpServletRequest, HttpServletResponse) -> Unit + +class ServletFramework : Framework { + + override fun handle(base: StandardHandler): OmniHandler { +// base.handle(body = , +// headers = ) + return ServletHandler(base) + } + + override fun check(vararg args: Any): Boolean = (args.size > 1 && args.first() is HttpServletRequest) + + +} + diff --git a/jvm/src/main/java/actions/expected/Expected.kt b/jvm/src/main/java/actions/expected/Expected.kt new file mode 100644 index 0000000..debfe21 --- /dev/null +++ b/jvm/src/main/java/actions/expected/Expected.kt @@ -0,0 +1,10 @@ +package actions.expected + +import actions.expected.GoogleAuthLib + +actual class GoogleAuthLib { + actual fun asyncVerify() { + + } + +} \ No newline at end of file diff --git a/jvm/src/main/java/actions/expected/OAuth2Client.kt b/jvm/src/main/java/actions/expected/OAuth2Client.kt new file mode 100644 index 0000000..c4de266 --- /dev/null +++ b/jvm/src/main/java/actions/expected/OAuth2Client.kt @@ -0,0 +1,30 @@ +package actions.expected + +import actions.service.actionssdk.api.GoogleActionsV2Location + +actual class OAuth2Client actual constructor(clientId: String) { + actual fun verifyIdToken(idToken: IdToken): LoginTicket { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} + +actual class Date actual constructor(var timeStamp: String?) { + + actual fun toISOString(): String? { + return "" + } + +} + +fun MutableMap.deserializeValue(key: String, clazz: Class): T? { + val value = get(key) + return if (value != null) { + val jsonElement = Serializer.aogGson.toJsonTree(value) + Serializer.aogGson.fromJson(jsonElement, clazz) + } else { + null + } +} + +actual val MutableMap.deliveryAddress: GoogleActionsV2Location? + get() = deserializeValue("deliveryAddress", GoogleActionsV2Location::class.java) diff --git a/jvm/src/main/java/actions/expected/Serializer.kt b/jvm/src/main/java/actions/expected/Serializer.kt new file mode 100644 index 0000000..3cdc7c4 --- /dev/null +++ b/jvm/src/main/java/actions/expected/Serializer.kt @@ -0,0 +1,47 @@ +package actions.expected + +import com.google.gson.Gson +import com.google.gson.TypeAdapter +import com.google.gson.reflect.TypeToken +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonWriter + + +actual object Serializer { + private val mapType by lazy { object : TypeToken>() {}.type } + lateinit var aogGson: Gson + + actual fun stringifyConversationToken(data: Any?): ConversationTokenData { + val token = if (data == null) + ConversationTokenData(data = Object()) + else + ConversationTokenData(data) + return token + } + + actual fun serialize(any: Any?): String? { + if (any == null) return "{}" + return aogGson.toJson(any) + } + + + actual fun deserializeMap(json: String): MutableMap { + return aogGson.fromJson(json, mapType) + } + +} + +class MapTypeAdapter(val gson: Gson): TypeAdapter>() { + override fun write(out: JsonWriter, value: Map) { + value.forEach { + out.beginObject() + out.name(it.key) + out.jsonValue(gson.toJson(it.value)) + } + } + + override fun read(`in`: JsonReader): Map { + return mapOf() + } + +} \ No newline at end of file diff --git a/jvm/src/main/java/actions/expected/ServletUtils.java b/jvm/src/main/java/actions/expected/ServletUtils.java new file mode 100644 index 0000000..1c6a6a3 --- /dev/null +++ b/jvm/src/main/java/actions/expected/ServletUtils.java @@ -0,0 +1,93 @@ +package actions.expected; + + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.logging.Logger; + + +public class ServletUtils { + static Logger logger = Logger.getAnonymousLogger(); + + + //Copies inputstream so it can be logged and reused. Super inefficient and should not be production + public static String getBody(InputStream inputStream, String charsetName) throws IOException { + String body = null; + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + + try { + if (inputStream != null) { + if (charsetName == null) { + charsetName = "UTF-8"; + } + bufferedReader = new BufferedReader(new BufferedReader(new InputStreamReader(inputStream, charsetName))); + char[] charBuffer = new char[128]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + logger.warning("bytes read: " + bytesRead); + } else { + logger.warning("input stream is null"); + stringBuilder.append(""); + } + } catch (IOException ex) { + throw ex; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ex) { + throw ex; + } + } + } + + body = stringBuilder.toString(); + return body; + } + + //creates 2 copies of the InputStream. + public static ByteArrayInputStream[] copyBuffer(InputStream input) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + byte[] buffer = new byte[1024]; + int len; + while ((len = input.read(buffer)) > -1) { + baos.write(buffer, 0, len); + } + baos.flush(); + } catch (IOException e) { + logger.warning("Exception copying inputstream: " + e.getMessage()); + } + + return new ByteArrayInputStream[]{new ByteArrayInputStream(baos.toByteArray()), + new ByteArrayInputStream(baos.toByteArray())}; + } + + public static byte[] toByteArray(InputStream is) { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[16384]; + + try { + while ((nRead = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + buffer.flush(); + } catch (IOException e) { + return null; + } + + + return buffer.toByteArray(); + } + + +} diff --git a/sdk-gson-servlet/src/main/java/com/tmsdurham/actions/OrderUpdateSerializer.kt b/jvm/src/main/java/actions/expected/TypeAdapters.kt similarity index 50% rename from sdk-gson-servlet/src/main/java/com/tmsdurham/actions/OrderUpdateSerializer.kt rename to jvm/src/main/java/actions/expected/TypeAdapters.kt index ace5ab4..a5cc8c5 100644 --- a/sdk-gson-servlet/src/main/java/com/tmsdurham/actions/OrderUpdateSerializer.kt +++ b/jvm/src/main/java/actions/expected/TypeAdapters.kt @@ -1,51 +1,21 @@ -package com.tmsdurham.actions +package actions.expected -import com.google.gson.* +import actions.service.actionssdk.api.* +import actions.service.actionssdk.conversation.response.OrderUpdate +import com.google.gson.TypeAdapter import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter -import com.tmsdurham.dialogflow.Data -import com.tmsdurham.dialogflow.google.GoogleData +import com.google.gson.Gson -class DataTypeAdapter(val gson: Gson) : TypeAdapter() { - override fun write(out: JsonWriter, value: Data) { - value.forEach { - out.beginObject() - out.name(it.key) - if (it.value is GoogleData) { - out.jsonValue(gson.toJson(it.value)) - } - } - - } - - override fun read(reader: JsonReader): Data { - var token = reader.peek() - val data = Data() - if (token == JsonToken.BEGIN_OBJECT) { - reader.beginObject() - while (!reader.peek().equals(JsonToken.END_OBJECT)) { - if (reader.nextName() == "google") { - data.google = gson.fromJson(reader, GoogleData::class.java) - } else { - reader.skipValue() - } - - } - reader.endObject() - } - return data - } - -} class OrderUpdateTypeAdapter(val gson: Gson) : TypeAdapter() { override fun write(out: JsonWriter?, value: OrderUpdate?) { } override fun read(reader: JsonReader): OrderUpdate { - var token = reader.peek() + val token = reader.peek() val orderUpdate = OrderUpdate() if (token == JsonToken.BEGIN_OBJECT) { reader.beginObject() @@ -55,20 +25,26 @@ class OrderUpdateTypeAdapter(val gson: Gson) : TypeAdapter() { when (name) { "googleOrderId" -> orderUpdate.googleOrderId = reader.nextString() "actionOrderId" -> orderUpdate.actionOrderId = reader.nextString() - "orderState" -> orderUpdate.orderState = gson.fromJson(reader, OrderState::class.java) + "orderDate" -> orderUpdate.orderDate = reader.nextString() + "locale" -> orderUpdate.locale = reader.nextString() + "orderState" -> orderUpdate.orderState = gson.fromJson(reader, GoogleActionsV2OrdersOrderState::class.java) "lineItemUpdates" -> { - val type = object: TypeToken>(){}.type + val type = object : TypeToken>() {}.type orderUpdate.lineItemUpdates = gson.fromJson(reader, type) } - "updateTime" -> orderUpdate.updateTime = gson.fromJson(reader, OrderUpdate.UpdateTime::class.java) + "updateTime" -> orderUpdate.updateTime = gson.fromJson(reader, GoogleTypeTimeOfDay::class.java) "orderManagementActions" -> { - val type = object: TypeToken>() {}.type + val type = object : TypeToken>() {}.type orderUpdate.orderManagementActions = gson.fromJson(reader, type) } - "userNotification" -> orderUpdate.userNotification = gson.fromJson(reader, OrderUpdate.UserNotification::class.java) - "totalPrice" -> orderUpdate.totalPrice = gson.fromJson(reader, GoogleData.TotalPrice::class.java) + "userNotification" -> orderUpdate.userNotification = gson.fromJson(reader, GoogleActionsV2OrdersOrderUpdateUserNotification::class.java) + "totalPrice" -> orderUpdate.totalPrice = gson.fromJson(reader, GoogleActionsV2OrdersPrice::class.java) else -> { - orderUpdate.put(name, gson.fromJson(reader, HashMap()::class.java)) + if (reader.peek().equals(JsonToken.STRING)) { + orderUpdate.put(name, reader.nextString()) + } else if (reader.peek().equals(JsonToken.BEGIN_OBJECT)) { + orderUpdate.put(name, gson.fromJson(reader, HashMap()::class.java)) + } } } } @@ -77,4 +53,4 @@ class OrderUpdateTypeAdapter(val gson: Gson) : TypeAdapter() { } return orderUpdate } -} +} \ No newline at end of file diff --git a/jvm/src/main/java/actions/expected/deserialize.kt b/jvm/src/main/java/actions/expected/deserialize.kt new file mode 100644 index 0000000..d012947 --- /dev/null +++ b/jvm/src/main/java/actions/expected/deserialize.kt @@ -0,0 +1,5 @@ +package actions.expected + +actual fun deserialize(json: String?): T? { + return null +} \ No newline at end of file diff --git a/jvm/src/main/java/actions/expected/framework/ServletFramework.kt b/jvm/src/main/java/actions/expected/framework/ServletFramework.kt new file mode 100644 index 0000000..1380e27 --- /dev/null +++ b/jvm/src/main/java/actions/expected/framework/ServletFramework.kt @@ -0,0 +1,2 @@ +package actions.expected.framework + diff --git a/jvm/src/main/java/actions/expected/framework/TestHttpServlet.kt b/jvm/src/main/java/actions/expected/framework/TestHttpServlet.kt new file mode 100644 index 0000000..ec284b5 --- /dev/null +++ b/jvm/src/main/java/actions/expected/framework/TestHttpServlet.kt @@ -0,0 +1,438 @@ +package actions.expected.framework + +import java.io.BufferedReader +import java.io.PrintWriter +import java.security.Principal +import java.util.* +import javax.servlet.* +import javax.servlet.http.* + +class TestHttpServletRequest: HttpServletRequest { + override fun isUserInRole(role: String?): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun startAsync(): AsyncContext { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun startAsync(servletRequest: ServletRequest?, servletResponse: ServletResponse?): AsyncContext { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getPathInfo(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getProtocol(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getCookies(): Array { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getParameterMap(): MutableMap> { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRequestURL(): StringBuffer { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getAttributeNames(): Enumeration { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setCharacterEncoding(env: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getParameterValues(name: String?): Array { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRemoteAddr(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isAsyncStarted(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getContentLengthLong(): Long { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getLocales(): Enumeration { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRealPath(path: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun login(username: String?, password: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getContextPath(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isRequestedSessionIdValid(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getServerPort(): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getAttribute(name: String?): Any { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getDateHeader(name: String?): Long { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRemoteHost(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRequestedSessionId(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getServletPath(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getSession(create: Boolean): HttpSession { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getSession(): HttpSession { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getServerName(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getLocalAddr(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isSecure(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun upgrade(handlerClass: Class?): T { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isRequestedSessionIdFromCookie(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getPart(name: String?): Part { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRemoteUser(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getLocale(): Locale { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getMethod(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isRequestedSessionIdFromURL(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getLocalPort(): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isRequestedSessionIdFromUrl(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getServletContext(): ServletContext { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getQueryString(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getDispatcherType(): DispatcherType { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getHeaders(name: String?): Enumeration { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getUserPrincipal(): Principal { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getParts(): MutableCollection { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getReader(): BufferedReader { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getScheme(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun logout() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getInputStream(): ServletInputStream { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getLocalName(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isAsyncSupported(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getAuthType(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getCharacterEncoding(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getParameterNames(): Enumeration { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun authenticate(response: HttpServletResponse?): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun removeAttribute(name: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getPathTranslated(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getContentLength(): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getHeader(name: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getIntHeader(name: String?): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun changeSessionId(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getContentType(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getAsyncContext(): AsyncContext { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRequestURI(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRequestDispatcher(path: String?): RequestDispatcher { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getHeaderNames(): Enumeration { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setAttribute(name: String?, o: Any?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getParameter(name: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getRemotePort(): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} + +class TestHttpServletResponse: HttpServletResponse { + override fun encodeURL(url: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun encodeUrl(url: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun addIntHeader(name: String?, value: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun addCookie(cookie: Cookie?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun encodeRedirectUrl(url: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun flushBuffer() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun encodeRedirectURL(url: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun sendRedirect(location: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setBufferSize(size: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getLocale(): Locale { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun sendError(sc: Int, msg: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun sendError(sc: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setContentLengthLong(len: Long) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setCharacterEncoding(charset: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun addDateHeader(name: String?, date: Long) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setLocale(loc: Locale?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getHeaders(name: String?): MutableCollection { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun addHeader(name: String?, value: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setContentLength(len: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getBufferSize(): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun resetBuffer() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun reset() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setDateHeader(name: String?, date: Long) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getStatus(): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getCharacterEncoding(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun isCommitted(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setStatus(sc: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setStatus(sc: Int, sm: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getHeader(name: String?): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getContentType(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getWriter(): PrintWriter { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun containsHeader(name: String?): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setIntHeader(name: String?, value: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getHeaderNames(): MutableCollection { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setHeader(name: String?, value: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getOutputStream(): ServletOutputStream { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun setContentType(type: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} diff --git a/jvm/src/main/java/actions/expected/log.kt b/jvm/src/main/java/actions/expected/log.kt new file mode 100644 index 0000000..d24e05f --- /dev/null +++ b/jvm/src/main/java/actions/expected/log.kt @@ -0,0 +1,10 @@ +package actions.expected + +import java.util.logging.Logger + +val logger = Logger.getAnonymousLogger() + +actual fun log(message: String, vararg optionalParameters: Any?) { + System.out.println(message) + logger.info(message + if (optionalParameters != null) " :$optionalParameters" else "") +} \ No newline at end of file diff --git a/sample-gae-jvm/build.gradle b/sample-gae-jvm/build.gradle new file mode 100644 index 0000000..9f20cbe --- /dev/null +++ b/sample-gae-jvm/build.gradle @@ -0,0 +1,40 @@ +buildscript { // Configuration for building + repositories { + jcenter() // Bintray's repository - a fast Maven Central mirror & more + mavenCentral() + } + dependencies { + classpath 'com.google.cloud.tools:appengine-gradle-plugin:+' // latest App Engine Gradle tasks + } +} + +apply plugin: 'kotlin' +apply plugin: 'java' +apply plugin: 'war' +apply plugin: 'com.google.cloud.tools.appengine' + + + +dependencies { + compile project(':jvm-app') + compile group: 'org.mockito', name: 'mockito-core', version: '2.18.3' + compile('com.google.appengine:appengine-api-1.0-sdk:1.9.64', + 'com.google.code.gson:gson:2.8.0') + + providedCompile('javax.servlet:javax.servlet-api:3.1.0') + + compile libraries.kotlin_stdlib + +// compileProject(":common", configuration: "testArtifacts") +// compile files(project(':common').configurations.test.output.classesDir) +} +compileTestJava.dependsOn tasks.getByPath(':common:testClasses') + +task run(dependsOn: classes, type: JavaExec) { + main = 'jvm.JvmAppKt' + classpath = sourceSets.main.runtimeClasspath + ignoreExitValue(true) +} + +sourceCompatibility = "1.8" +targetCompatibility = "1.8" \ No newline at end of file diff --git a/sample-gae-jvm/src/main/java/jvm/DfTransactionsWebhook.kt b/sample-gae-jvm/src/main/java/jvm/DfTransactionsWebhook.kt new file mode 100644 index 0000000..3bc9ba7 --- /dev/null +++ b/sample-gae-jvm/src/main/java/jvm/DfTransactionsWebhook.kt @@ -0,0 +1,37 @@ +package jvm + +import actions.expected.ServletFramework +import actions.expected.logger +import actions.service.dialogflow.dialogflow +import javax.servlet.annotation.WebServlet +import javax.servlet.http.HttpServlet +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +@WebServlet("/df/transactions") +class DfTransactionsWebhook : HttpServlet() { + + override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { + resp.writer.println("Working") + } + + private val dfApp = dialogflow({ debug = true }) + + var hasAddedFramework = false + + override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { + logger.info("here") + if (!hasAddedFramework) { + dfApp.frameworks.add(ServletFramework()) + hasAddedFramework = true + } + + initTransactionSample(dfApp) + + dfApp(req, resp) + } + + +} + + diff --git a/sample-gae-jvm/src/main/java/jvm/DialogflowWebhook.kt b/sample-gae-jvm/src/main/java/jvm/DialogflowWebhook.kt new file mode 100644 index 0000000..5d49c31 --- /dev/null +++ b/sample-gae-jvm/src/main/java/jvm/DialogflowWebhook.kt @@ -0,0 +1,34 @@ +package jvm + +import actions.expected.ServletFramework +import actions.expected.logger +import javax.servlet.annotation.WebServlet +import javax.servlet.http.HttpServlet +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +@WebServlet("/df") +class DialogflowWebhook : HttpServlet() { + + override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { + resp.writer.println("Working") + } + + var hasAddedFramework = false + + override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { + logger.info("here") + if (!hasAddedFramework) { + dfApp.frameworks.add(ServletFramework()) + hasAddedFramework = true + } + + initDf() + + dfApp(req, resp) + } + + +} + + diff --git a/sample-gae-jvm/src/main/java/jvm/SampleWebhook.kt b/sample-gae-jvm/src/main/java/jvm/SampleWebhook.kt new file mode 100644 index 0000000..47b80d4 --- /dev/null +++ b/sample-gae-jvm/src/main/java/jvm/SampleWebhook.kt @@ -0,0 +1,34 @@ +package jvm + +import actions.expected.ServletFramework +import actions.expected.logger +import javax.servlet.annotation.WebServlet +import javax.servlet.http.HttpServlet +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +@WebServlet("/aog") +class SampleWebhook : HttpServlet() { + + override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { + resp.writer.println("Working") + } + + var hasAddedFramework = false + + override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { + logger.info("here") + if (!hasAddedFramework) { + app.frameworks.add(ServletFramework()) + hasAddedFramework = true + } + + initActionsApp() + + app(req, resp) + } + + +} + + diff --git a/dialogflow-samples/src/main/webapp/WEB-INF/appengine-web.xml b/sample-gae-jvm/src/main/webapp/WEB-INF/appengine-web.xml similarity index 51% rename from dialogflow-samples/src/main/webapp/WEB-INF/appengine-web.xml rename to sample-gae-jvm/src/main/webapp/WEB-INF/appengine-web.xml index e58d6f3..d1f5f99 100644 --- a/dialogflow-samples/src/main/webapp/WEB-INF/appengine-web.xml +++ b/sample-gae-jvm/src/main/webapp/WEB-INF/appengine-web.xml @@ -1,16 +1,19 @@ + kotlin-actions-sdk - dev - + v2 java8 + true + + + true - - 100ms - 500ms - 30 - + + + + diff --git a/action-sdk-samples/src/main/webapp/WEB-INF/logging.properties b/sample-gae-jvm/src/main/webapp/WEB-INF/logging.properties similarity index 100% rename from action-sdk-samples/src/main/webapp/WEB-INF/logging.properties rename to sample-gae-jvm/src/main/webapp/WEB-INF/logging.properties diff --git a/sample-gae-jvm/src/main/webapp/WEB-INF/web.xml b/sample-gae-jvm/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..af2cc30 --- /dev/null +++ b/sample-gae-jvm/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk-gson-servlet/README.md b/sdk-gson-servlet/README.md deleted file mode 100644 index 82e20d0..0000000 --- a/sdk-gson-servlet/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# SDK-GSON-SERVLET - -This module is a wrapper around the sdk module which can be used with Java servlets and Gson for serialization. - -Published to Maven Central as: - -__Gradle:__ - - repositories { - jCenter() - } - } - - dependencies { - compile 'com.tmsdurham.actions:actions-on-google:1.2.1' - } -__Maven:__ - - - com.tmsdurham.actions - actions-on-google - 1.2.1 - pom - diff --git a/sdk-gson-servlet/src/main/java/com/tmsdurham/actions/Actions.kt b/sdk-gson-servlet/src/main/java/com/tmsdurham/actions/Actions.kt deleted file mode 100644 index db883a0..0000000 --- a/sdk-gson-servlet/src/main/java/com/tmsdurham/actions/Actions.kt +++ /dev/null @@ -1,103 +0,0 @@ -package main.java.com.tmsdurham.dialogflow.sample - -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import com.tmsdurham.dialogflow.DialogflowRequest -import com.tmsdurham.dialogflow.DialogflowResponse -import com.tmsdurham.actions.* -import com.tmsdurham.actions.actions.ActionRequest -import com.tmsdurham.actions.actions.ActionResponse -import java.util.logging.Logger -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - - -/** - * Gson & Servlet Action for Dialogflow - * Intentionally not in sdk module so gson & servlet are not a dependency of the SDK. - */ -class DialogflowAction(req: HttpServletRequest, - resp: HttpServletResponse, - val gson: Gson, - val beforeSending: ((DialogflowResponse, String) -> Unit)? = null) { - val app: DialogflowApp - - //needed for 2 arg constructor from Java - constructor(req: HttpServletRequest, resp: HttpServletResponse) : this(req, resp, Gson()) - - init { - val jsonStr = convertStreamToString(req.inputStream) - Logger.getAnonymousLogger().info(jsonStr) - val request = gson.fromJson(jsonStr, DialogflowRequest::class.java) - val headers = resp.headerNames.associate { it to resp.getHeader(it) } - app = DialogflowApp(RequestWrapper(body = request, headers = headers), ResponseWrapper(sendAction = { - val bodyStr = gson.toJson(body) - headers.forEach { - resp.addHeader(it.key, it.value) - } - beforeSending?.invoke(this.body ?: DialogflowResponse(), bodyStr) - debug(bodyStr) - resp.contentType = "application/json" - resp.characterEncoding = "UTF-8" - resp.writer.write(bodyStr) - })) - } - - fun convertStreamToString(input: java.io.InputStream): String { - val s = java.util.Scanner(input).useDelimiter("\\A") - return if (s.hasNext()) s.next() else "" - } - - fun handleRequest(handler: Map<*, *>) { - app.handleRequest(handler) - } -} - -/** - * Gson & Servlet Action for Actions SDK (direct integration) - * Intentionally not in sdk module so gson & servlet are not a dependency of the SDK. - */ -class ActionsSdkAction(req: HttpServletRequest, - resp: HttpServletResponse, - val gson: Gson = GsonBuilder() - .registerTypeAdapter(OrderUpdate::class.java, OrderUpdateTypeAdapter(Gson())) - .create(), - val gsonWithNulls: Gson = GsonBuilder() - .serializeNulls() - .create(), - val beforeSending: ((ActionResponse, String) -> Unit)? = null) { - val app: ActionsSdkApp - - init { - val jsonStr = convertStreamToString(req.inputStream) - Logger.getAnonymousLogger().info(jsonStr) - val request = gson.fromJson(jsonStr, ActionRequest::class.java) - val headers = resp.headerNames.associate { it to resp.getHeader(it) } - - app = ActionsSdkApp(RequestWrapper(body = request, headers = headers), ResponseWrapper(sendAction = { - val bodyStr = gson.toJson(body) - headers.forEach { - resp.addHeader(it.key, it.value) - } - beforeSending?.invoke(this.body ?: ActionResponse(), bodyStr) - debug(bodyStr) - resp.contentType = "application/json" - resp.characterEncoding = "UTF-8" - resp.writer.write(bodyStr) - }), serializer = object : Serializer { - override fun serialize(obj: T) = gsonWithNulls.toJson(obj) - - override fun deserialize(str: String, clazz: Class) = gsonWithNulls.fromJson(str, clazz) - - }) - } - - fun convertStreamToString(input: java.io.InputStream): String { - val s = java.util.Scanner(input).useDelimiter("\\A") - return if (s.hasNext()) s.next() else "" - } - - fun handleRequest(handler: Map<*, *>) { - app.handleRequest(handler) - } -} \ No newline at end of file diff --git a/sdk/.gitignore b/sdk/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/sdk/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/sdk/build.gradle b/sdk/build.gradle deleted file mode 100644 index 049b102..0000000 --- a/sdk/build.gradle +++ /dev/null @@ -1,124 +0,0 @@ -buildscript { - - repositories { - jcenter() - maven { url "https://plugins.gradle.org/m2/" } - } - dependencies { - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$project.ext.kotlinVersion" - } -} - - -apply plugin: 'org.junit.platform.gradle.plugin' -apply plugin: 'idea' -apply plugin: 'kotlin' -apply plugin: 'java' -apply plugin: 'com.jfrog.bintray' -apply plugin: 'maven-publish' - - -bintray { - user = JCENTER_USERNAME - key = JCENTER_API_KEY - publications = ['ActionsMavenPublication'] - pkg { - repo = 'maven' - name = 'com.tmsdurham.actions' - licenses = ['Apache-2.0'] - vcsUrl = 'https://github.com/TicketmasterMobileStudio/actions-on-google-kotlin' - version { - name = project.ext.sdkVersion - desc = 'Actions on Google SDK - core' - vcsTag = project.ext.sdkVersion - released = new Date() - } - } - override = true - -} - -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -artifacts { - archives sourcesJar - archives javadocJar -} - -// Create the pom configuration: -def pomConfig = { - licenses { - license { - name "The Apache Software License, Version 2.0" - url "http://www.apache.org/licenses/LICENSE-2.0.txt" - distribution "repo" - } - } - developers { - developer { - name "Patrick Jackson" - email "patrick.jackson@ticketmaster.com" - } - } - - scm { - url "https://github.com/TicketmasterMobileStudio/actions-on-google-kotlin" - } -} - - -publishing { - publications { - ActionsMavenPublication(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - groupId 'com.tmsdurham.actions' - artifactId 'actions-on-google-core' - version project.ext.sdkVersion - pom.withXml { - def root = asNode() - root.appendNode('description', 'Unofficial Actions on Google Client Library for Kolin/Java - core lib') - root.appendNode('name', 'Google Actions Kolin/Java SDK - core lib') - root.appendNode('url', 'https://github.com/TicketmasterMobileStudio/actions-on-google-kotlin') - root.children().last() + pomConfig - } - } - } -} - - -junitPlatform { - filters { - engines { - include 'spek' - } - } -} - -dependencies { - compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$project.ext.kotlinVersion") - - testCompile('org.jetbrains.spek:spek-api:1.1.2', - "com.winterbe:expekt:0.5.0", - 'com.nhaarman:mockito-kotlin:1.5.0') - - testCompile "org.jetbrains.spek:spek-api:$project.ext.spekVersion" - testRuntime "org.jetbrains.spek:spek-junit-platform-engine:$project.ext.spekVersion" - - testCompile "com.google.code.gson:gson:$project.ext.gsonVersion" - testCompile project(':sdk-gson-servlet') -} - -repositories { - mavenCentral() -} \ No newline at end of file diff --git a/sdk/build.gradle.kts.bak b/sdk/build.gradle.kts.bak deleted file mode 100644 index 00dd5be..0000000 --- a/sdk/build.gradle.kts.bak +++ /dev/null @@ -1,38 +0,0 @@ -repositories { - mavenCentral() -} - -buildscript { - repositories { - jcenter() - mavenCentral() - dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.3") - classpath("org.junit.platform:junit-platform-gradle-plugin:1.0.0-M4") - } - } -} - -apply { - plugin("kotlin") - plugin("idea") - plugin("java") - plugin("org.junit.platform.gradle.plugin") -} - -plugins { - java -} -java.sourceSets = {} -configure { -} - -dependencies { - compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:1.1.3") - - testCompile("junit:junit:4.12") - testCompile("org.assertj:assertj-core:3.6.1") - testCompile("org.mockito:mockito-all:2.0.2-beta") - testCompile("org.jetbrains.spek:spek-api:1.1.2") - testRuntime("org.jetbrains.spek:spek-junit-platform-engine:1.1.2") -} diff --git a/sdk/src/main/java/com/tmsdurham/actions/ActionsApp.kt b/sdk/src/main/java/com/tmsdurham/actions/ActionsApp.kt deleted file mode 100644 index a21fcf5..0000000 --- a/sdk/src/main/java/com/tmsdurham/actions/ActionsApp.kt +++ /dev/null @@ -1,1137 +0,0 @@ -package com.tmsdurham.actions - -import com.tmsdurham.dialogflow.google.GoogleData -import com.tmsdurham.actions.actions.* -import com.tmsdurham.dialogflow.DialogflowResponse - - -// Constants -val CONVERSATION_API_AGENT_VERSION_HEADER = "Agent-Version-Label" -val INPUTS_MAX = 3 - -// --------------------------------------------------------------------------- -// Actions SDK support -// --------------------------------------------------------------------------- - -/** - * Completes serialization/deserialization of response, request, dialogState - */ -interface Serializer { - fun serialize(obj: T): String - fun deserialize(str: String, clazz: Class): T -} - -/** - * This is the class that handles the conversation API directly from Assistant, - * providing implementation for all the methods available in the API. - */ -class ActionsSdkApp : AssistantApp { - - val serializer: Serializer - - /** - * Constructor for ActionsSdkApp object. - * To be used in the Actions SDK HTTP endpoint logic. - * - * @example - * val ActionsSdkApp = require("actions-on-google").ActionsSdkApp - * val app = new ActionsSdkApp({request: request, response: response, - * sessionStarted:sessionStarted}) - * - * @param {Object} options JSON configuration. - * @param {Object} options.request Express HTTP request object. - * @param {Object} options.response Express HTTP response object. - * @param {fun=} options.sessionStarted fun callback when session starts. - * @actionssdk - */ - constructor(request: RequestWrapper, - response: ResponseWrapper, - sessionStarted: (() -> Unit)? = null, - serializer: Serializer) : - super(request, response, sessionStarted) { - debug("ActionsSdkApp constructor") - this.serializer = serializer - response.body = ActionResponse() - - // If request is AoG and in Proto2 format, convert to Proto3. - //TODO -// if (!isNotApiVersionOne()) { -// request.body.transformToCamelCase() -// } - - if (request.body.conversation?.type == CONVERSATION_STAGES.NEW && - sessionStarted != null) { - sessionStarted() - } - } - - /* - * Gets the request Conversation API version. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * val apiVersion = app.getApiVersion() - * - * @return {String} Version value or null if no value. - * @actionssdk - */ - fun getApiVersion(): String { - debug("getApiVersion") - return if (apiVersion_ != null) apiVersion_ else actionsApiVersion - } - - /** - * Gets the user"s raw input query. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * app.tell("You said " + app.getRawInput()) - * - * @return {String} User"s raw query or null if no value. - * @actionssdk - */ - fun getRawInput(): String? { - debug("getRawInput") - val input = getTopInput() - if (input == null) { - handleError("Failed to get top Input.") - return null - } - if (input?.rawInputs?.size ?: 0 == 0) { - handleError("Missing user raw input") - return null - } - val rawInput = input.rawInputs?.get(0) - if (rawInput?.query == null) { - handleError("Missing query for user raw input") - return null - } - return rawInput.query - } - - /** - * Gets previous JSON dialog state that the app sent to Assistant. - * Alternatively, use the app.data field to store JSON values between requests. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * val dialogState = app.getDialogState() - * - * @return {String|DialogState} JSON object provided to the Assistant in the previous - * user turn or {} if no value. - * @actionssdk - */ - fun getDialogState(): Any? { - debug("getDialogState") - if (this.request.body.conversation?.conversationToken?.isNotBlank() ?: false) { - var token = request.body.conversation?.conversationToken - var dialogState: MutableMap? = null - try { - dialogState = serializer.deserialize(token!!, mutableMapOf()::class.java) - } catch (e: Exception) { - debug("Error deserializing conversationToken: " + e.message) - } - - return dialogState - } - return mutableMapOf() - } - - /** - * Gets the "versionLabel" specified inside the Action Package. - * Used by app to do version control. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * val actionVersionLabel = app.getActionVersionLabel() - * - * @return {String} The specified version label or null if unspecified. - * @actionssdk - */ - fun getActionVersionLabel(): String? { - debug("getActionVersionLabel") - val versionLabel = request.get(CONVERSATION_API_AGENT_VERSION_HEADER) - if (versionLabel != null) { - return versionLabel - } else { - return null - } - } - - /** - * Gets the unique conversation ID. It"s a new ID for the initial query, - * and stays the same until the end of the conversation. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * val conversationId = app.getConversationId() - * - * @return {String} Conversation ID or null if no value. - * @actionssdk - */ - fun getConversationId(): String? { - debug("getConversationId") - if (request.body.conversation?.conversationId == null) { - this.handleError("No conversation ID") - return null - } - return request.body.conversation.conversationId - } - - /** - * Get the current intent. Alternatively, using a handler Map with - * {@link AssistantApp#handleRequest|handleRequest}, the client library will - * automatically handle the incoming intents. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * - * fun responseHandler (app: ActionSdkApp) { - * val intent = app.getIntent() - * when (intent) { - * app.StandardIntents.MAIN -> { - * val inputPrompt = app.buildInputPrompt(false, "Welcome to action snippets! Say anything.") - * app.ask(inputPrompt) - * } - * - * app.StandardIntents.TEXT -> - * app.tell("You said " + app.getRawInput()) - * } - * } - * - * app.handleRequest(responseHandler) - * - * @return {String} Intent id or null if no value. - * @actionssdk - */ - override fun getIntent(): String? { - debug("getIntent") - val input = getTopInput() - if (input == null) { - handleError("Missing intent from request body") - return null - } - return input.intent - } - - /** - * Get the argument value by name from the current intent. If the argument - * is not a text argument, the entire argument object is returned. - * - * Note: If incoming request is using an API version under 2 (e.g. "v1"), - * the argument object will be in Proto2 format (snake_case, etc). - * - * @param {String} argName Name of the argument. - * @return {String} Argument value matching argName - * or null if no matching argument. - * @actionssdk - */ - fun getArgument(argName: String): Any? { - return getArgumentCommon(argName) - } - - /** - * Returns the option key user chose from options response. - * - * @example - * val app = App(request = req, response = res) - * - * fun pickOption (app: ActionSdkApp) { - * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * app.askWithCarousel("Which of these looks good?", - * app.buildCarousel().addItems( - * app.buildOptionItem("another_choice", ["Another choice"]). - * setTitle("Another choice").setDescription("Choose me!"))) - * } else { - * app.ask("What would you like?") - * } - * } - * - * fun optionPicked (app: ActionsSdkApp) { - * app.ask("You picked " + app.getSelectedOption()) - * } - * - * val actionMap = mapOf( - * app.StandardIntents.TEXT to pickOption, - * app.StandardIntents.OPTION to optionPicked) - * - * app.handleRequest(actionMap) - * - * @return {String} Option key of selected item. Null if no option selected or - * if current intent is not OPTION intent. - * @actionssdk - */ - fun getSelectedOption(): Any? { - debug("getSelectedOption") - if (getArgument(BUILT_IN_ARG_NAMES.OPTION) != null) { - return getArgument(BUILT_IN_ARG_NAMES.OPTION) - } - debug("Failed to get selected option") - return null - } - - /** - * Asks to collect user"s input all user"s queries need to be sent to - * the app. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * - * fun mainIntent (app: ActionSdkApp) { - * val inputPrompt = app.buildInputPrompt(true, "Hi! " + - * "I can read out an ordinal like " + - * "123. Say a number.", - * ["I didn\"t hear a number", "If you\"re still there, what\"s the number?", "What is the number?"]) - * app.ask(inputPrompt) - * } - * - * fun rawInput (app: ActionSdkApp) { - * if (app.getRawInput() == "bye") { - * app.tell("Goodbye!") - * } else { - * val inputPrompt = app.buildInputPrompt(true, "You said, " + - * app.getRawInput() + "", - * ["I didn\"t hear a number", "If you\"re still there, what\"s the number?", "What is the number?"]) - * app.ask(inputPrompt) - * } - * } - * - * val actionMap = mapOf( - * app.StandardIntents.MAIN to ::mainIntent, - * app.StandardIntents.TEXT to ::rawInput) - * - * app.handleRequest(actionMap) - * - * @param {Object|SimpleResponse|RichResponse} inputPrompt Holding initial and - * no-input prompts. - * @param {Object=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by App. - * @return The response that is sent to Assistant to ask user to provide input. - * @actionssdk - */ - fun ask(inputPrompt: SimpleResponse, dialogState: MutableMap? = null): ResponseWrapper? { - debug("ask: inputPrompt=$inputPrompt, dialogState=$dialogState") - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.TEXT) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - } - - fun ask(speech: String, displayText: String?): ResponseWrapper? { - debug("tell: speech=$speech displayText=$displayText") - val simpleResponse = SimpleResponse() - val finalResponse = FinalResponse() - if (isSsml(speech)) { - simpleResponse.ssml = speech - } else { - simpleResponse.textToSpeech = speech - } - simpleResponse.displayText = displayText - if (displayText.isNullOrBlank()) { - finalResponse.speechResponse = simpleResponse - } else { - finalResponse.richResponse = buildRichResponse().addSimpleResponse(simpleResponse) - } - - val response = buildResponseHelper(null, true, null, finalResponse) - return this.doResponse(response, RESPONSE_CODE_OK) - } - - fun ask(init: SimpleResponse.() -> Unit): ResponseWrapper? { - var simpleResponse = SimpleResponse() - simpleResponse.init() - return ask(simpleResponse) - } - - fun ask(inputPrompt: InputPrompt?, dialogState: MutableMap? = null): ResponseWrapper? { - debug("ask: inputPrompt=$inputPrompt, dialogState=$dialogState") - if (inputPrompt == null) { - error("InputPrompt can not be null") - return null - } - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.TEXT) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - } - - - fun ask(speech: String?, dialogState: MutableMap? = null): ResponseWrapper? { - debug("ask: speech=$speech, dialogState=$dialogState") - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.TEXT) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - return buildAskHelper(speech, mutableListOf(expectedIntent), dialogState) - } - - - fun ask(inputPrompt: RichResponse?, dialogState: MutableMap? = null): ResponseWrapper? { - debug("ask: inputPrompt=$inputPrompt, dialogState=$dialogState") - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.TEXT) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - } - - private fun buildAskHelper(inputPrompt: RichResponse?, possibleIntents: MutableList, dialogState: MutableMap?): ResponseWrapper? { - debug("ask: inputPrompt=$inputPrompt, dialogState=$dialogState") - - val inputPrompt = InputPrompt(richInitialPrompt = inputPrompt) - return buildAskHelper(inputPrompt, possibleIntents, dialogState) - } - - /** - * Asks to collect user"s input with a list. - * - * @example - * val app = ActionsSdkApp(request, response) - * - * fun welcomeIntent (app: ActionSdkApp) { - * app.askWithlist("Which of these looks good?", - * app.buildList("List title") - * .addItems([ - * app.buildOptionItem(SELECTION_KEY_ONE, - * ["synonym of KEY_ONE 1", "synonym of KEY_ONE 2"]) - * .setTitle("Number one"), - * app.buildOptionItem(SELECTION_KEY_TWO, - * ["synonym of KEY_TWO 1", "synonym of KEY_TWO 2"]) - * .setTitle("Number two"), - * ])) - * } - * - * fun optionIntent (app: ActionSDKApp) { - * if (app.getSelectedOption() == SELECTION_KEY_ONE) { - * app.tell("Number one is a great choice!") - * } else { - * app.tell("Number two is a great choice!") - * } - * } - * - * val actionMap = mapOf( - * app.StandardIntents.TEXT to ::welcomeIntent - * app.StandardIntents.OPTION to ::optionIntent) - * app.handleRequest(actionMap) - * - * @param {Object|SimpleResponse|RichResponse} inputPrompt Holding initial and - * no-input prompts. Cannot contain basic card. - * @param {List} list List built with {@link AssistantApp#buildList|buildList}. - * @param {Object=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return The response that is sent to Assistant to ask user to provide input. - * @actionssdk - */ - fun askWithList(inputPrompt: Any, list: List, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askWithList: inputPrompt=$inputPrompt, list=$list, dialogState=$dialogState") - if (list.items.size < 2) { - handleError("List requires at least 2 items") - return null - } - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.OPTION) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - if (isNotApiVersionOne()) { - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.OPTION - listSelect = list - } - } else { - expectedIntent.inputValueSpec { - optionValueSpec = GoogleData.OptionValueSpec( - listSelect = list) - } - } - return when (inputPrompt) { - is String -> buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - is SimpleResponse -> buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - is RichResponse -> buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - else -> { - error("unknown inputPrompt type") - null - } - } - } - - /** - * Asks user for delivery address. - * - * @example - * val app = ActionsSdkApp(request, response) - * val WELCOME_INTENT = app.StandardIntents.MAIN - * val DELIVERY_INTENT = app.StandardIntents.DELIVERY_ADDRESS - * - * fun welcomeIntent (app: ActionSdkApp) { - * app.askForDeliveryAddress("To make sure I can deliver to you") - * } - * - * fun addressIntent (app: ActionSdkApp) { - * val postalCode = app.getDeliveryAddress().postalAddress.postalCode - * if (isInDeliveryZone(postalCode)) { - * app.tell("Great looks like you\"re in our delivery area!") - * } else { - * app.tell("I\"m sorry it looks like we can\"t deliver to you.") - * } - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * DELIVERY_INTENT to ::addressIntent) - * app.handleRequest(actionMap) - * - * @param {String} reason Reason given to user for asking delivery address. - * @param {Object=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return {Object} HTTP response. - * @dialogflow - */ - fun askForDeliveryAddress(reason: String, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForDeliveryAddress: reason=$reason") - if (reason.isEmpty()) { - handleError("reason cannot be empty") - return null - } - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.DELIVERY_ADDRESS) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.DELIVERY_ADDRESS - addressOptions = GoogleData.AddressOptions(reason = reason) - } - - val inputPrompt = buildInputPrompt(false, - "PLACEHOLDER_FOR_DELIVERY_ADDRESS") - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - } - - /** - * Asks to collect user"s input with a carousel. - * - * @example - * val app = ActionsSdkApp(request, response) - * - * fun welcomeIntent (app: ActionSdkApp) { - * app.askWithCarousel("Which of these looks good?", - * app.buildCarousel() - * .addItems([ - * app.buildOptionItem(SELECTION_KEY_ONE, - * ["synonym of KEY_ONE 1", "synonym of KEY_ONE 2"]) - * .setTitle("Number one"), - * app.buildOptionItem(SELECTION_KEY_TWO, - * ["synonym of KEY_TWO 1", "synonym of KEY_TWO 2"]) - * .setTitle("Number two"), - * ])) - * } - * - * fun optionIntent (app: ActionSdk) { - * if (app.getSelectedOption() == SELECTION_KEY_ONE) { - * app.tell("Number one is a great choice!") - * } else { - * app.tell("Number two is a great choice!") - * } - * } - * - * val actionMap = mapOf( - * app.StandardIntents.TEXT to ::welcomeIntent) - * app.StandardIntents.OPTION to ::optionIntent) - * app.handleRequest(actionMap) - * - * @param {Object|SimpleResponse|RichResponse} inputPrompt Holding initial and - * no-input prompts. Cannot contain basic card. - * @param {Carousel} carousel Carousel built with - * {@link AssistantApp#buildCarousel|buildCarousel}. - * @param {Object=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return The response that is sent to Assistant to ask user to provide input. - * @actionssdk - */ - fun askWithCarousel(inputPrompt: Any, carousel: Carousel, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askWithCarousel: inputPrompt=$inputPrompt, carousel=$carousel, dialogState=$dialogState") - - if (carousel.items.size < 2) { - this.handleError("Carousel requires at least 2 items") - return null - } - val expectedIntent = buildExpectedIntent(STANDARD_INTENTS.OPTION) - if (expectedIntent == null) { - error("Error in building expected intent") - return null - } - if (isNotApiVersionOne()) { - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.OPTION - carouselSelect = carousel - } - } else { - expectedIntent.inputValueSpec { - optionValueSpec { - carouselSelect = carousel - } - } - } - return when (inputPrompt) { - is String -> buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - is SimpleResponse -> buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - is RichResponse -> buildAskHelper(inputPrompt, mutableListOf(expectedIntent), dialogState) - else -> { - error("unknown inputPrompt type") - null - } - } - } - - /** - * Tells Assistant to render the speech response and close the mic. - * - * @example - * val app = ActionsSdkApp(request = request, response = response) - * - * fun mainIntent (app) { - * val inputPrompt = app.buildInputPrompt(true, "Hi! " + - * "I can read out an ordinal like " + - * "123. Say a number.", - * ["I didn\"t hear a number", "If you\"re still there, what\"s the number?", "What is the number?"]) - * app.ask(inputPrompt) - * } - * - * fun rawInput (app) { - * if (app.getRawInput() == "bye") { - * app.tell("Goodbye!") - * } else { - * val inputPrompt = app.buildInputPrompt(true, "You said, " + - * app.getRawInput() + "", - * ["I didn\"t hear a number", "If you\"re still there, what\"s the number?", "What is the number?"]) - * app.ask(inputPrompt) - * } - * } - * - * val actionMap = new Map() - * actionMap.set(app.StandardIntents.MAIN, mainIntent) - * actionMap.set(app.StandardIntents.TEXT, rawInput) - * - * app.handleRequest(actionMap) - * - * @param {string|SimpleResponse|RichResponse} textToSpeech Final response. - * Spoken response can be SSML. - * @return The HTTP response that is sent back to Assistant. - * @actionssdk - */ - override fun tell(speech: String, displayText: String?): ResponseWrapper? { - debug("tell: speech=$speech displayText=$displayText") - val simpleResponse = SimpleResponse() - val finalResponse = FinalResponse() - if (isSsml(speech)) { - simpleResponse.ssml = speech - } else { - simpleResponse.textToSpeech = speech - } - simpleResponse.displayText = displayText - if (displayText.isNullOrBlank()) { - finalResponse.speechResponse = simpleResponse - } else { - finalResponse.richResponse = buildRichResponse().addSimpleResponse(simpleResponse) - } - - val response = buildResponseHelper(null, false, null, finalResponse) - return this.doResponse(response, RESPONSE_CODE_OK) - } - - override fun tell(speech: String): ResponseWrapper? = tell(speech, null) - - override fun tell(simpleResponse: SimpleResponse): ResponseWrapper? { - debug("tell: simpleResponse=$simpleResponse") - val finalResponse = FinalResponse() - - finalResponse.richResponse = this.buildRichResponse() - .addSimpleResponse(simpleResponse) - - val response = buildResponseHelper(null, false, null, finalResponse) - return this.doResponse(response, RESPONSE_CODE_OK) - } - - override fun tell(richResponse: RichResponse?): ResponseWrapper? { - debug("tell: richResponse=$richResponse") - val finalResponse = FinalResponse() - finalResponse.richResponse = richResponse - - val response = buildResponseHelper(null, false, null, finalResponse) - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Builds the {@link https://developers.google.com/actions/reference/conversation#InputPrompt|InputPrompt object} - * from initial prompt and no-input prompts. - * - * The App needs one initial prompt to start the conversation. If there is no user response, - * the App re-opens the mic and renders the no-input prompts three times - * (one for each no-input prompt that was configured) to help the user - * provide the right response. - * - * Note: we highly recommend app to provide all the prompts required here in order to ensure a - * good user experience. - * - * @example - * val inputPrompt = app.buildInputPrompt(false, "Welcome to action snippets! Say a number.", - * ["Say any number", "Pick a number", "What is the number?"]) - * app.ask(inputPrompt) - * - * @param {boolean} isSsml Indicates whether the text to speech is SSML or not. - * @param {string} initialPrompt The initial prompt the App asks the user. - * @param {Array=} noInputs Array of re-prompts when the user does not respond (max 3). - * @return {Object} An {@link https://developers.google.com/actions/reference/conversation#InputPrompt|InputPrompt object}. - * @actionssdk - */ - fun buildInputPrompt(isSsml: Boolean, initialPrompt: String, noInputs: MutableList = mutableListOf()): InputPrompt? { - debug("buildInputPrompt: isSsml=$isSsml, initialPrompt=$initialPrompt, noInputs=$noInputs") - val initials = mutableListOf() - - if (noInputs.isNotEmpty()) { - if (noInputs.size > INPUTS_MAX) { - handleError("Invalid number of no inputs") - return null - } - } - - maybeAddItemToArray(initialPrompt, initials) - if (isSsml) { - return InputPrompt( - initialPrompts = buildPromptsFromSsmlHelper(initials), - noInputPrompts = buildPromptsFromSsmlHelper(noInputs.map { it }.toMutableList()) - ) - } else { - return InputPrompt( - initialPrompts = buildPromptsFromPlainTextHelper(initials), - noInputPrompts = buildPromptsFromPlainTextHelper(noInputs.map { it }.toMutableList())) - } - } - -// --------------------------------------------------------------------------- -// Private Helpers -// --------------------------------------------------------------------------- - - /** - * Get the top most Input object. - * - * @return {object} Input object. - * @private - * @actionssdk - */ - private fun getTopInput(): Input? { - debug("getTopInput") - if (request.body.inputs?.size == 0) { - this.handleError("Missing inputs from request body") - return null - } - return request.body.inputs?.get(0) - } - - /** - * Builds the response to send back to Assistant. - * - * @param {string} conversationToken The dialog state. - * @param {boolean} expectUserResponse The expected user response. - * @param {Object} expectedInput The expected response. - * @param {boolean} finalResponse The final response. - * @return {Object} Final response returned to server. - * @private - * @actionssdk - */ - fun buildResponseHelper(conversationToken: String?, expectUserResponse: Boolean, expectedInput: ExpectedInput?, finalResponse: FinalResponse?): ResponseWrapper { - debug("buildResponseHelper: conversationToken=$conversationToken, expectUserResponse=$expectUserResponse, " + - "expectedInput=$expectedInput, finalResponse=$finalResponse") - response.body = ActionResponse() - if (!conversationToken.isNullOrBlank()) { - response.body?.conversationToken = conversationToken - } - response.body?.expectUserResponse = expectUserResponse - if (expectedInput != null) { - response.body?.expectedInputs = mutableListOf(expectedInput) - } - if (!expectUserResponse && finalResponse != null) { - response.body?.finalResponse = finalResponse - } - return response - } - - /** - * Helper to add item to an array. - * - * @private - * @actionssdk - */ - private fun maybeAddItemToArray(item: T, array: MutableList): Unit { - debug("maybeAddItemToArray_: item=$item, array=$array") - if (item == null) { - // ignore add - return - } - array.add(item) - } - - /** - * Extract session data from the incoming JSON request. - * - * @private - * @actionssdk - */ - override fun extractData() { - debug("extractData") - if (request.body.conversation?.conversationToken != null) { - val json = request.body.conversation.conversationToken - //TODO extract state from token -// data = json.data -// state = json?.get("state") as String? - } else { - data = mutableMapOf() - } - } - - /** - * Uses a PermissionsValueSpec object to construct and send a - * permissions request to user. - * - * @param {Object} permissionsValueSpec PermissionsValueSpec object containing - * the permissions prefix and the permissions requested. - * @param {Object} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return {Object} HTTP response object. - * @private - * @actionssdk - */ - override fun fulfillPermissionsRequest(permissionsSpec: GoogleData.PermissionsRequest, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillPermissionsRequest_: permissionsValueSpec=$permissionsSpec, dialogState=$dialogState") - // Build an Expected Intent object. - val expectedIntent = ExpectedIntent( - intent = STANDARD_INTENTS.PERMISSION) - if (isNotApiVersionOne()) { - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.PERMISSION - optContext = permissionsSpec.optContext - permissions = permissionsSpec.permissions - expectUserResponse = permissionsSpec.expectUserResponse - } - } else { - expectedIntent.inputValueSpec = InputValueSpec( - permissionValueSpec = permissionsSpec) - } - val inputPrompt = this.buildInputPrompt(false, "PLACEHOLDER_FOR_PERMISSION") - var outDialogState = dialogState - if (dialogState == null) { - outDialogState = mutableMapOf( - "state" to state, - "data" to this.data) - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), outDialogState) - } - - /** - * Uses TransactionRequirementsCheckValueSpec to construct and send a - * transaction requirements request to Google. - * - * @param {Object} transactionRequirementsSpec TransactionRequirementsSpec - * object. - * @param {Object} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return {Object} HTTP response. - * @private - * @actionssdk - */ - override fun fulfillTransactionRequirementsCheck(transactionRequirementsSpec: TransactionRequirementsCheckSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillTransactionRequirementsCheck: transactionRequirementsSpec=$transactionRequirementsSpec," + - " dialogState=$dialogState") - // Build an Expected Intent object. - val expectedIntent = ExpectedIntent( - intent = STANDARD_INTENTS.TRANSACTION_REQUIREMENTS_CHECK) - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.TRANSACTION_REQ_CHECK - paymentOptions = transactionRequirementsSpec.paymentOptions - orderOptions = transactionRequirementsSpec.orderOptions - } - - val inputPrompt = this.buildInputPrompt(false, "PLACEHOLDER_FOR_TXN_REQUIREMENTS") - var outState = dialogState - if (dialogState == null) { - outState = mutableMapOf( - "state" to this.state, - "data" to this.data) - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), outState) - } - - /** - * Uses TransactionDecisionValueSpec to construct and send a transaction - * requirements request to Google. - * - * @param {Object} transactionDecisionValueSpec TransactionDecisionValueSpec - * object. - * @param {Object} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return {Object} HTTP response. - * @private - * @actionssdk - */ - override fun fulfillTransactionDecision(transactionDecisionValueSpec: TransactionDecisionValueSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillTransactionDecision: transactionDecisionValueSpec=$transactionDecisionValueSpec" + - " dialogState=$dialogState") - // Build an Expected Intent object. - val expectedIntent = ExpectedIntent( - intent = STANDARD_INTENTS.TRANSACTION_DECISION - ) - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.TRANSACTION_DECISION - proposedOrder = transactionDecisionValueSpec.proposedOrder - orderOptions = transactionDecisionValueSpec.orderOptions - paymentOptions = transactionDecisionValueSpec.paymentOptions - } - - // Send an Ask request to Assistant. - val inputPrompt = this.buildInputPrompt(false, "PLACEHOLDER_FOR_TXN_DECISION") - var outDialogState = dialogState - if (dialogState == null) { - outDialogState = mutableMapOf( - "state" to this.state, - "data" to this.data) - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), outDialogState) - } - - /** - * Uses ConfirmationValueSpec to construct and send a confirmation request to - * Google. - * - * @param {Object} confirmationValueSpec ConfirmationValueSpec object. - * @return {Object} HTTP response. - * @private - * @actionssdk - */ - override fun fulfillConfirmationRequest(confirmationValueSpec: ConfirmationValueSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillConfirmationRequest_: confirmationValueSpec=$confirmationValueSpec," + - " dialogState=$dialogState") - // Build an Expected Intent object. - val expectedIntent = ExpectedIntent( - intent = STANDARD_INTENTS.CONFIRMATION) - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.CONFIRMATION - dialogSpec = confirmationValueSpec.dialogSpec - } - - // Send an Ask request to Assistant. - val inputPrompt = this.buildInputPrompt(false, "PLACEHOLDER_FOR_CONFIRMATION") - var outDialogState = dialogState - if (dialogState == null) { - outDialogState = mutableMapOf( - "state" to this.state, - "data" to this.data) - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), outDialogState) - } - - data class DateTimeValueSpec(var tmp: String? = null) - - /** - * Uses DateTimeValueSpec to construct and send a datetime request to Google. - * - * @param {Object} dateTimeValueSpec DateTimeValueSpec object. - * @return {Object} HTTP response. - * @private - * @actionssdk - */ - override fun fulfillDateTimeRequest(confirmationValueSpec: ConfirmationValueSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillDateTimeRequest_: dateTimeValueSpec=$confirmationValueSpec," + - " dialogState=$dialogState") - // Build an Expected Intent object. - val expectedIntent = ExpectedIntent( - intent = STANDARD_INTENTS.DATETIME) - expectedIntent.inputValueData { - `@type` = INPUT_VALUE_DATA_TYPES.DATETIME - dialogSpec = confirmationValueSpec.dialogSpec - } - - // Send an Ask request to Assistant. - val inputPrompt = this.buildInputPrompt(false, "PLACEHOLDER_FOR_DATETIME") - var outDialogState = dialogState - if (dialogState == null) { - outDialogState = mutableMapOf( - "state" to this.state, - "data" to this.data) - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), outDialogState) - } - - /** - * Construct and send a sign in request to Google. - * - * @return {Object} HTTP response. - * @private - * @actionssdk - */ - override fun fulfillSignInRequest(dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillSignInRequest_: dialogState=$dialogState") - // Build an Expected Intent object. - val expectedIntent = ExpectedIntent( - intent = STANDARD_INTENTS.SIGN_IN) - expectedIntent.inputValueData = InputValueData() - // Send an Ask request to Assistant. - val inputPrompt = buildInputPrompt(false, "PLACEHOLDER_FOR_SIGN_IN") - var outDialogState = dialogState - if (dialogState == null) { - outDialogState = mutableMapOf( - "state" to this.state, - "data" to data) - } - return buildAskHelper(inputPrompt, mutableListOf(expectedIntent), outDialogState) - } - - - override fun fulfillSystemIntent(intent: String, specType: String, intentSpec: NewSurfaceValueSpec, promptPlaceholder: String?, dialogState: MutableMap?): ResponseWrapper? { - TODO("not implemented for Actions SDK - please make an issue on actions-on-google-kotlin if this is needed") - } - - override fun fulfillRegisterUpdateIntent(intent: String, specType: String, intentSpec: RegisterUpdateValueSpec, promptPlaceholder: String?, dialogState: MutableMap?): ResponseWrapper? { - TODO("not implemented for Actions SDK - please make an issue on actions-on-google-kotlin if this is needed") - } - - /** - * Builds the ask response to send back to Assistant. - * - * @param {InputPrompt} inputPrompt Holding initial and no-input prompts. - * @param {Array} possibleIntents Array of ExpectedIntents. - * @param {DialogState} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return The response that is sent to Assistant to ask user to provide input. - * @private - * @actionssdk - */ - private fun buildAskHelper(inputPrompt: InputPrompt?, possibleIntents: MutableList, dialogState: MutableMap?): ResponseWrapper? { - debug("buildAskHelper_: inputPrompt=$inputPrompt, possibleIntents, dialogState=$dialogState") - if (inputPrompt == null) { - handleError("Invalid input prompt") - return null - } - - var outDialogState = dialogState - if (dialogState == null) { - outDialogState = mutableMapOf( - "state" to this.state, - "data" to this.data) - } - - val expectedInputs = ExpectedInput( - inputPrompt = inputPrompt, - possibleIntents = possibleIntents - ) - buildResponseHelper( - serializer.serialize(outDialogState), - true, // expectedUserResponse - expectedInputs, - null // finalResponse is null b/c dialog is active - ) - return doResponse(response, RESPONSE_CODE_OK) - } - - fun buildAskHelper(inputPrompt: String?, possibleIntents: MutableList, dialogState: MutableMap?): ResponseWrapper? { - debug("buildAskHelper: inputPrompt=$inputPrompt, possibleIntents=$possibleIntents, dialogState=$dialogState") - if (inputPrompt == null) { - handleError("Invalid input prompt") - return null - } - val inputPrompt = buildInputPrompt(isSsml(inputPrompt), inputPrompt) - return buildAskHelper(inputPrompt, possibleIntents, dialogState) - } - - private fun buildAskHelper(simpleResponse: SimpleResponse, possibleIntents: MutableList, dialogState: MutableMap?): ResponseWrapper? { - debug("buildAskHelper: inputPrompt=$simpleResponse, possibleIntents=$possibleIntents, dialogState=$dialogState") - if (simpleResponse == null) { - handleError("Invalid input prompt") - return null - } -// val inputPrompt = buildInputPrompt(isSsml(simpleResponse.textToSpeech ?: ""), simpleResponse.textToSpeech ?: "") - val inputPrompt = InputPrompt(richInitialPrompt = buildRichResponse().addSimpleResponse(simpleResponse)) - return buildAskHelper(inputPrompt, possibleIntents, dialogState) - } - - /** - * Builds an ExpectedIntent object. Refer to {@link ActionsSdkApp#newRuntimeEntity} to create the list - * of runtime entities required by this method. Runtime entities need to be defined in - * the Action Package. - * - * @param {string} intent Developer specified in-dialog intent inside the Action - * Package or an App built-in intent like - * "assistant.intent.action.TEXT". - * @return {Object} An {@link https://developers.google.com/actions/reference/conversation#ExpectedIntent|ExpectedIntent object} - encapsulating the intent and the runtime entities. - * @private - * @actionssdk - */ - fun buildExpectedIntent(intent: String): ExpectedIntent? { - debug("buildExpectedIntent_: intent=$intent") - if (intent.isBlank()) { - handleError("Invalid intent") - return null - } - val expectedIntent = ExpectedIntent( - intent = intent) - return expectedIntent - } - - data class ExpectedIntent(var intent: String? = null, - var inputValueType: String? = null, - var inputValueSpec: InputValueSpec? = null, - var inputValueData: InputValueData? = null) { - - fun inputValueData(init: InputValueData.() -> Unit): InputValueData { - if (inputValueData == null) { - inputValueData = InputValueData() - } - inputValueData?.init() - return inputValueData!! - } - - fun inputValueSpec(init: InputValueSpec.() -> Unit) { - if (inputValueSpec == null) { - inputValueData = InputValueData() - } - inputValueSpec?.init() - } - - - } - - data class InputValueSpec(var permissionValueSpec: GoogleData.PermissionsRequest? = null, - var optionValueSpec: GoogleData.OptionValueSpec? = null) { - fun optionValueSpec(init: GoogleData.OptionValueSpec.() -> Unit) { - if (optionValueSpec == null) { - optionValueSpec = GoogleData.OptionValueSpec() - } - optionValueSpec?.init() - } - } - - data class InputValueData( - var `@type`: String = "", - var addressOptions: GoogleData.AddressOptions? = null, - var listSelect: List? = null, - var proposedOrder: Order? = null, - var orderOptions: GoogleData.OrderOptions? = null, - var paymentOptions: GoogleData.PaymentOptions? = null, - var dialogSpec: AssistantApp.DialogSpec? = null, - var carouselSelect: Carousel? = null, - var optContext: String? = null, - var permissions: MutableList? = null, - var expectUserResponse: Boolean = false) - -} - -data class ExpectedInput(var inputPrompt: InputPrompt? = null, - var possibleIntents: MutableList? = null) - diff --git a/sdk/src/main/java/com/tmsdurham/actions/AssistantApp.kt b/sdk/src/main/java/com/tmsdurham/actions/AssistantApp.kt deleted file mode 100644 index 4edd286..0000000 --- a/sdk/src/main/java/com/tmsdurham/actions/AssistantApp.kt +++ /dev/null @@ -1,1389 +0,0 @@ -package com.tmsdurham.actions - -import com.tmsdurham.dialogflow.* -import com.tmsdurham.dialogflow.google.GoogleData -import java.util.logging.Logger -import javax.xml.ws.Response - -typealias Handler = (AssistantApp) -> Unit - -internal val logger = Logger.getAnonymousLogger() - -// Constants -val ERROR_MESSAGE = "Sorry, I am unable to process your request." -val API_ERROR_MESSAGE_PREFIX = "Action Error: " -val CONVERSATION_API_VERSION_HEADER = "Google-Assistant-API-Version" -val ACTIONS_CONVERSATION_API_VERSION_HEADER = "Google-Actions-API-Version" -val ACTIONS_CONVERSATION_API_VERSION_TWO = 2 -val RESPONSE_CODE_OK = 200 -val RESPONSE_CODE_BAD_REQUEST = 400 -val HTTP_CONTENT_TYPE_HEADER = "Content-Type" -val HTTP_CONTENT_TYPE_JSON = "application/json" - - -class StandardIntents(val isNotVersionOne: Boolean) { - /** App fires MAIN intent for queries like [talk to $app]. */ - val MAIN = if (isNotVersionOne) "actions.intent.MAIN" else "assistant.intent.action.MAIN" - /** App fires TEXT intent when action issues ask intent. */ - val TEXT = if (isNotVersionOne) "actions.intent.TEXT" else "assistant.intent.action.TEXT" - /** App fires PERMISSION intent when action invokes askForPermission. */ - val PERMISSION = if (isNotVersionOne) "actions.intent.PERMISSION" else "assistant.intent.action.PERMISSION" - /** App fires OPTION intent when user chooses from options provided. */ - val OPTION = if (isNotVersionOne) "actions.intent.OPTION" else "assistant.intent.action.PERMISSION" - /** App fires TRANSACTION_REQUIREMENTS_CHECK intent when action sets up transaction. */ - val TRANSACTION_REQUIREMENTS_CHECK = "actions.intent.TRANSACTION_REQUIREMENTS_CHECK" - /** App fires DELIVERY_ADDRESS intent when action asks for delivery address. */ - val DELIVERY_ADDRESS = "actions.intent.DELIVERY_ADDRESS" - /** App fires TRANSACTION_DECISION intent when action asks for transaction decision. */ - val TRANSACTION_DECISION = "actions.intent.TRANSACTION_DECISION" - /** App fires CONFIRMATION intent when requesting affirmation from user. */ - val CONFIRMATION = "actions.intent.CONFIRMATION" - /** App fires DATETIME intent when requesting date/time from user. */ - val DATETIME = "actions.intent.DATETIME" - /** App fires SIGN_IN intent when requesting sign-in from user. */ - val SIGN_IN = "actions.intent.SIGN_IN" - /** App fires NO_INPUT intent when user doesn't provide input. */ - val NO_INPUT = "actions.intent.NO_INPUT" - /** App fires CANCEL intent when user exits app mid-dialog. */ - val CANCEL = "actions.intent.CANCEL" - /** App fires NEW_SURFACE intent when requesting handoff to a new surface from user. */ - val NEW_SURFACE = "actions.intent.NEW_SURFACE" - /** App fires REGISTER_UPDATE intent when requesting the user to register for proactive updates. */ - val REGISTER_UPDATE = "actions.intent.REGISTER_UPDATE" - /** App receives CONFIGURE_UPDATES intent to indicate a custom REGISTER_UPDATE intent should be sent. */ - val CONFIGURE_UPDATES = "actions.intent.CONFIGURE_UPDATES" -} - -class SupportedIntent { - /** - * The user"s name as defined in the - * {@link https://developers.google.com/actions/reference/conversation#UserProfile|UserProfile object} - */ - val NAME = "NAME" - /** - * The location of the user"s current device, as defined in the - * {@link https://developers.google.com/actions/reference/conversation#Location|Location object}. - */ - val DEVICE_PRECISE_LOCATION = "DEVICE_PRECISE_LOCATION" - /** - * City and zipcode corresponding to the location of the user"s current device, as defined in the - * {@link https://developers.google.com/actions/reference/conversation#Location|Location object}. - */ - val DEVICE_COARSE_LOCATION = "DEVICE_COARSE_LOCATION" -} - -/** - * List of built-in argument names. - */ -class BuiltInArgNames(isNotVersionOne: Boolean) { - /** Permission granted argument. */ - val PERMISSION_GRANTED = if (isNotVersionOne) "PERMISSION" else "permission_granted" - /** Option selected argument. */ - val OPTION = "OPTION" - /** Transaction requirements check result argument. */ - val TRANSACTION_REQ_CHECK_RESULT = "TRANSACTION_REQUIREMENTS_CHECK_RESULT" - /** Delivery address value argument. */ - val DELIVERY_ADDRESS_VALUE = "DELIVERY_ADDRESS_VALUE" - /** Transactions decision argument. */ - val TRANSACTION_DECISION_VALUE = "TRANSACTION_DECISION_VALUE" - /** Confirmation argument. */ - val CONFIRMATION = "CONFIRMATION" - /** DateTime argument. */ - val DATETIME = "DATETIME" - /** Sign in status argument. */ - val SIGN_IN = "SIGN_IN" - /** Reprompt count for consecutive NO_INPUT intents. */ - val REPROMPT_COUNT = "REPROMPT_COUNT" - /** Flag representing finality of NO_INPUT intent. */ - val IS_FINAL_REPROMPT = "IS_FINAL_REPROMPT" - /** New surface value argument. */ - val NEW_SURFACE = "NEW_SURFACE" - /** Update registration value argument. */ - val REGISTER_UPDATE = "REGISTER_UPDATE" -} - -const val ANY_TYPE_PROPERTY = "@type" - -/** - * List of built-in value type names. - */ -class InputValueDataTypes { - /** Permission Value Spec. */ - val PERMISSION = "type.googleapis.com/google.actions.v2.PermissionValueSpec" - /** Option Value Spec. */ - val OPTION = "type.googleapis.com/google.actions.v2.OptionValueSpec" - /** Transaction Requirements Check Value Spec. */ - val TRANSACTION_REQ_CHECK = "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckSpec" - /** Delivery Address Value Spec. */ - val DELIVERY_ADDRESS = "type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec" - /** Transaction Decision Value Spec. */ - val TRANSACTION_DECISION = "type.googleapis.com/google.actions.v2.TransactionDecisionValueSpec" - /** Confirmation Value Spec. */ - val CONFIRMATION = "type.googleapis.com/google.actions.v2.ConfirmationValueSpec" - /** DateTime Value Spec. */ - val DATETIME = "type.googleapis.com/google.actions.v2.DateTimeValueSpec" - /** Sign in Value Spec. */ - val SIGN_IN = "type.googleapis.com/google.actions.v2.SignInValueSpec" - /** New Surface Value Spec. */ - val NEW_SURFACE = "type.googleapis.com/google.actions.v2.NewSurfaceValueSpec" - /** Register Update Value Spec. */ - val REGISTER_UPDATE = "type.googleapis.com/google.actions.v2.RegisterUpdateValueSpec" -} - -/** - * List of possible conversation stages, as defined in the - * {@link https://developers.google.com/actions/reference/conversation#Conversation|Conversation object}. - * @actionssdk - * @dialogflow - */ -class ConversationStages(val isNotVersionOne: Boolean) { - /** - * Unspecified conversation state. - */ - val UNSPECIFIED = if (isNotVersionOne) "UNSPECIFIED" else "0" - /** - * A new conversation. - */ - val NEW = if (isNotVersionOne) "NEW" else "1" - /** - * An active (ongoing) conversation. - */ - val ACTIVE = if (isNotVersionOne) "ACTIVE" else "2" -} - -/** - * List of surface capabilities supported by the app. - * @readonly - * @enum {string} - * @actionssdk - * @dialogflow - */ -class SurfaceCapabilities { - /** - * The ability to output audio. - */ - val AUDIO_OUTPUT = "actions.capability.AUDIO_OUTPUT" - /** - * The ability to output on a screen - */ - val SCREEN_OUTPUT = "actions.capability.SCREEN_OUTPUT" -} - -/** - * List of possible user input types. - * @readonly - * @enum {number} - * @actionssdk - * @dialogflow - */ -class InputTypes(val isNotApiVersionOne: Boolean) { - /** - * Unspecified. - */ - val UNSPECIFIED = if (isNotApiVersionOne) "UNSPECIFIED" else "0" - /** - * Input given by touch. - */ - val TOUCH = if (isNotApiVersionOne) "TOUCH" else "1" - /** - * Input given by voice (spoken). - */ - val VOICE = if (isNotApiVersionOne) "VOICE" else "2" - /** - * Input given by keyboard (typed). - */ - val KEYBOARD = if (isNotApiVersionOne) "KEYBOARD" else "3" -} - -/** - * List of supported permissions the app supports. - */ -class SupportedPermissions { - /** - * The user"s name as defined in the - * {@link https://developers.google.com/actions/reference/conversation#UserProfile|UserProfile object} - */ - val NAME = "NAME" - /** - * The location of the user"s current device, as defined in the - * {@link https://developers.google.com/actions/reference/conversation#Location|Location object}. - */ - val DEVICE_PRECISE_LOCATION = "DEVICE_PRECISE_LOCATION" - /** - * City and zipcode corresponding to the location of the user"s current device, as defined in the - * {@link https://developers.google.com/actions/reference/conversation#Location|Location object}. - */ - val DEVICE_COARSE_LOCATION = "DEVICE_COARSE_LOCATION" - /** - * Confirmation to receive proactive content at any time from the app. - */ - val UPDATE = "UPDATE" -} - -class SignInStatus { - // Unknown status. - val UNSPECIFIED = "SIGN_IN_STATUS_UNSPECIFIED" - // User successfully completed the account linking. - val OK = "OK" - // Cancelled or dismissed account linking. - val CANCELLED = "CANCELLED" - // System or network error. - val ERROR = "ERROR" -} - -/** - * Possible update trigger time context frequencies. - * @readonly - * @type {object} - */ -class TimeContextFrequency { - val DAILY = "DAILY" -} - - -open abstract class AssistantApp(val request: RequestWrapper, val response: ResponseWrapper, val sessionStarted: (() -> Unit)? = null) { - var actionsApiVersion: String = "2" - var STANDARD_INTENTS: StandardIntents - val SUPPORTED_INTENT = SupportedIntent() - var BUILT_IN_ARG_NAMES: BuiltInArgNames - val INPUT_VALUE_DATA_TYPES = InputValueDataTypes() - var CONVERSATION_STAGES: ConversationStages - val SURFACE_CAPABILITIES = SurfaceCapabilities() - var INPUT_TYPES: InputTypes - val SUPPORTED_PERMISSIONS = SupportedPermissions() - val SIGN_IN_STATUS = SignInStatus() - val TIME_CONTEXT_FREQUENCY = TimeContextFrequency() - - var responded = false - var apiVersion_: String = "2" - // Unique to Kotlin sdk - state is a json String that is serialized/deserialized - var state: String? = null - var data: MutableMap = mutableMapOf() - var contexts = mutableMapOf() - val requestExtractor: RequestExtractor - - /** - * Values related to supporting {@link Transactions}. - * @readonly - * @type {object} - */ - - init { - debug("AssistantApp constructor") - - if (request == null) { - handleError("Request can NOT be empty.") - } else if (response == null) { - handleError("Response can NOT be empty.") - } else { - if (request.headers[ACTIONS_CONVERSATION_API_VERSION_HEADER] != null) { - actionsApiVersion = request.headers[ACTIONS_CONVERSATION_API_VERSION_HEADER] ?: "2" - debug("Actions API version from header: " + this.actionsApiVersion) - } else if (request.headers[CONVERSATION_API_VERSION_HEADER] != null) { - actionsApiVersion = if (request.headers[CONVERSATION_API_VERSION_HEADER] == "v1") "1" else "2" - } - if (request.body is DialogflowRequest) { - if (request.body.originalRequest != null) { - actionsApiVersion = request.body.originalRequest?.version ?: "1" - debug("Actions API version from Dialogflow: " + this.actionsApiVersion) - } - } - } - STANDARD_INTENTS = StandardIntents(isNotApiVersionOne()) - BUILT_IN_ARG_NAMES = BuiltInArgNames(isNotApiVersionOne()) - CONVERSATION_STAGES = ConversationStages(isNotApiVersionOne()) - INPUT_TYPES = InputTypes(isNotApiVersionOne()) - - /** - * API version describes version of the Assistant request. - * @deprecated - * @private - * @type {string} - */ - // Populates API version. - if (request.get(CONVERSATION_API_VERSION_HEADER) != null) { - apiVersion_ = request.get(CONVERSATION_API_VERSION_HEADER) ?: "" - debug("Assistant API version: " + apiVersion_) - } - - requestExtractor = RequestExtractor(this) - } - - - fun handleRequest(handler: Handler) { - debug("handleRequest: handler=${handler::javaClass.get().name}") - handler(this) - } - - fun handleRequest(handler: Map<*, *>) { - debug("handleRequest: handler=${handler::javaClass.get().name}") - invokeIntentHandler(handler as Map<*, Handler>, getIntent()) - } - - /** - * Equivalent to {@link AssistantApp#askForPermission|askForPermission}, - * but allows you to prompt the user for more than one permission at once. - * - * Notes: - * - * * The order in which you specify the permission prompts does not matter - - * it is controlled by the Assistant to provide a consistent user experience. - * * The user will be able to either accept all permissions at once, or none. - * If you wish to allow them to selectively accept one or other, make several - * dialog turns asking for each permission independently with askForPermission. - * * Asking for DEVICE_COARSE_LOCATION and DEVICE_PRECISE_LOCATION at once is - * equivalent to just asking for DEVICE_PRECISE_LOCATION - * - * @example - * val app = DialogflowApp(request = req, response = res) - * val REQUEST_PERMISSION_ACTION = "request_permission" - * val GET_RIDE_ACTION = "get_ride" - * - * fun requestPermission (app) { - * app.askForPermissions("To pick you up", app.SupportedPermissions.NAME, - * app.SupportedPermissions.DEVICE_PRECISE_LOCATION) - * } - * - * fun sendRide (app) { - * if (app.isPermissionGranted()) { - * val displayName = app.getUserName().displayName - * val address = app.getDeviceLocation().formattedAddress - * app.tell("I will tell your driver to pick up " + displayName + - * " at " + address) - * } else { - * // Response shows that user did not grant permission - * app.tell("Sorry, I could not figure out where to pick you up.") - * } - * } - * val actionMap = mapOf( - * REQUEST_PERMISSION_ACTION to requestPermission, - * GET_RIDE_ACTION to sendRide) - * app.handleRequest(actionMap) - * - * @param {String} context Context why the permission is being asked; it"s the TTS - * prompt prefix (action phrase) we ask the user. - * @param {Array} permissions Array of permissions App supports, each of - * which comes from AssistantApp.SupportedPermissions. - * @param {DialogState=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkAssistant}. - * @return A response is sent to Assistant to ask for the user"s permission; for any - * invalid input, we return null. - * @actionssdk - * @dialogflow - */ - fun askForPermissions(context: String, vararg permissions: String, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForPermissions: context=$context, permissions=$permissions, dialogState=$dialogState") - if (context.isEmpty()) { - handleError("Assistant context can NOT be empty.") - return null - } - if (permissions.isEmpty()) { - handleError("At least one permission needed.") - return null - } - permissions.forEach { - if (it !== SUPPORTED_PERMISSIONS.NAME && - it !== SUPPORTED_PERMISSIONS.DEVICE_PRECISE_LOCATION && - it !== SUPPORTED_PERMISSIONS.DEVICE_COARSE_LOCATION) { - this.handleError("Assistant permission must be one of " + - "[NAME, DEVICE_PRECISE_LOCATION, DEVICE_COARSE_LOCATION]") - return null - } - } - return fulfillPermissionsRequest(GoogleData.PermissionsRequest( - optContext = context, - permissions = permissions.toMutableList()), dialogState) - } - - - /** - * Prompts the user for permission to send proactive updates at any time. - * - * @example - * val app = new DialogflowApp({request, response}) - * val REQUEST_PERMISSION_ACTION = "request.permission" - * val PERMISSION_REQUESTED = "permission.requested" - * val SHOW_IMAGE = "show.image" - * - * fun requestPermission (app) { - * app.askForUpdatePermission("show.image", [ - * { - * name: "image_to_show", - * textValue: "image_type_1" - * } - * ]) - * } - * - * fun checkPermission (app) { - * if (app.isPermissionGranted()) { - * app.tell("Great, I"ll send an update whenever I notice a change") - * } else { - * // Response shows that user did not grant permission - * app.tell("Alright, just let me know whenever you need the weather!") - * } - * } - * - * fun showImage (app) { - * showPicture(app.getArgument("image_to_show")) - * } - * - * val actionMap = new Map() - * actionMap.set(REQUEST_PERMISSION_ACTION, requestPermission) - * actionMap.set(PERMISSION_REQUESTED, checkPermission) - * actionMap.set(SHOW_IMAGE, showImage) - * app.handleRequest(actionMap) - * - * @param {String} intent If using Dialogflow, the action name of the intent - * to be triggered when the update is received. If using Actions SDK, the - * intent name to be triggered when the update is received. - * @param {Array} intentArguments The necessary arguments - * to fulfill the intent triggered on update. These can be retrieved using - * {@link AssistantApp#getArgument}. - * @param {MutableMap} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkApp}. - * @return {ResponseWrapper?} A response is sent to Assistant to ask for the user"s permission for any - * invalid input, we return null. - * @actionssdk - * @dialogflow - */ - fun askForUpdatePermission(intent: String, intentArguments: MutableList? = null, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForUpdatePermission: intent=$intent, intentArguments=$intentArguments, dialogState=$dialogState") - if (intent.isBlank()) { - handleError("Name of intent to trigger on update must be specified") - return null - } - val updatePermissionValueSpec = GoogleData.PermissionsRequest(intent = intent) - if (intentArguments?.isNotEmpty() == true) { - updatePermissionValueSpec.arguments = intentArguments - } - updatePermissionValueSpec.permissions = mutableListOf(this.SUPPORTED_PERMISSIONS.UPDATE) - - return this.fulfillPermissionsRequest( - permissionsSpec = updatePermissionValueSpec, dialogState = dialogState) - } - - /** - * Asks user for a confirmation. - * - * @example - * val app = DialogflowApp(request, response) - * val WELCOME_INTENT = "input.welcome" - * val CONFIRMATION = "confirmation" - * - * fun welcomeIntent (app: MyAction) { - * app.askForConfirmation("Are you sure you want to do that?") - * } - * - * fun confirmation (app: MyAction) { - * if (app.getUserConfirmation()) { - * app.tell("Great! I\"m glad you want to do it!") - * } else { - * app.tell("That\"s okay. Let\"s not do it now.") - * } - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * CONFIRMATION to ::confirmation) - * app.handleRequest(actionMap) - * - * @param {String=} prompt The confirmation prompt presented to the user to - * query for an affirmative or negative response. If undefined or null, - * Google will use a generic yes/no prompt. - * @param {DialogState?=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkAssistant}. - * @actionssdk - * @dialogflow - */ - fun askForConfirmation(prompt: String = "", dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForConfirmation: prompt=$prompt, dialogState=$dialogState") - val confirmationValueSpec = ConfirmationValueSpec() - if (prompt.isNotBlank()) { - confirmationValueSpec.dialogSpec = DialogSpec( - requestConfirmationText = prompt) - } - return fulfillConfirmationRequest(confirmationValueSpec, dialogState) - } - - /** - * Asks user for a timezone-agnostic date and time. - * - * @example - * val app = DialogflowApp(request, response ) - * val WELCOME_INTENT = "input.welcome" - * val DATETIME = "datetime" - * - * fun welcomeIntent (app: MyAction) { - * app.askForDateTime("When do you want to come in?", - * "Which date works best for you?", - * "What time of day works best for you?") - * } - * - * function datetime (app: MyAction) { - * app.tell({speech: "Great see you at your appointment!", - * displayText: "Great, we will see you on " - * + app.getDateTime().date.month - * + "/" + app.getDateTime().date.day - * + " at " + app.getDateTime().time.hours - * + (app.getDateTime().time.minutes || "")}) - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * DATETIME, ::datetime) - * app.handleRequest(actionMap) - * - * @param {String=} initialPrompt The initial prompt used to ask for a - * date and time. If undefined or null, Google will use a generic - * prompt. - * @param {String=} datePrompt The prompt used to specifically ask for the - * date if not provided by user. If undefined or null, Google will use a - * generic prompt. - * @param {String=} timePrompt The prompt used to specifically ask for the - * time if not provided by user. If undefined or null, Google will use a - * generic prompt. - * @param {DialogState?=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkAssistant}. - * @actionssdk - * @dialogflow - */ - fun askForDateTime(initialPrompt: String? = null, datePrompt: String? = null, timePrompt: String? = null, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForConfirmation: initialPrompt=$initialPrompt, datePrompt=$datePrompt, timePrompt=$timePrompt, dialogState=$dialogState") - val confirmationValueSpec = ConfirmationValueSpec() - if (initialPrompt != null || datePrompt != null || timePrompt != null) { - confirmationValueSpec.dialogSpec = DialogSpec( - requestDatetimeText = initialPrompt, - requestDateText = datePrompt, - requestTimeText = timePrompt) - } - return fulfillDateTimeRequest(confirmationValueSpec, dialogState) - } - - /** - * Hands the user off to a web sign in flow. App sign in and OAuth credentials - * are set in the {@link https://console.actions.google.com|Actions Console}. - * Retrieve the access token in subsequent intents using - * app.getUser().accessToken. - * - * Note: Currently this API requires enabling the app for Transactions APIs. - * To do this, fill out the App Info section of the Actions Console project - * and check the box indicating the use of Transactions under "Privacy and - * consent". - * - * @example - * val app = DialogflowApp(request, response) - * val WELCOME_INTENT = "input.welcome" - * val SIGN_IN = "sign.in" - * - * fun welcomeIntent (app: MyAction) { - * app.askForSignIn() - * } - * - * fun signIn (app: MyAction) { - * if (app.getSignInStatus() == app.SignInstatus.OK) { - * val accessToken = app.getUser().accessToken - * app.ask("Great, thanks for signing in!") - * } else { - * app.ask("I won\"t be able to save your data, but let\"s continue!") - * } - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * SIGN_IN to ::signIn) - * app.handleRequest(actionMap) - * - * @param {DialogState?=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkAssistant}. - * @actionssdk - * @dialogflow - */ - fun askForSignIn(dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForSignIn: dialogState=$dialogState") - return fulfillSignInRequest(dialogState) - } - - /** - * Requests the user to switch to another surface during the conversation. - * - * @example - * val app = DialogflowApp(request, response) - * val WELCOME_INTENT = 'input.welcome' - * val SHOW_IMAGE = 'show.image' - * - * fun welcomeIntent (app) { - * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * showPicture(app) - * } else if (app.hasAvailableSurfaceCapabilities(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * app.askForNewSurface("To show you an image", - * "Check out this image", - * mutableListOf(app.SurfaceCapabilities.SCREEN_OUTPUT) - * ) - * } else { - * app.tell("This part of the app only works on screen devices. Sorry about that") - * } - * } - * - * fun showImage (app) { - * if (!app.isNewSurface()) { - * app.tell("Ok, I understand. You don't want to see pictures. Bye") - * } else { - * showPicture(app, pictureType) - * } - * } - * - * val actionMap = Map() - * actionMap.set(WELCOME_INTENT, welcomeIntent) - * actionMap.set(SHOW_IMAGE, showImage) - * app.handleRequest(actionMap) - * - * @param {String} context Context why surface is requested it's the TTS - * prompt prefix (action phrase) we ask the user. - * @param {String} notificationTitle Title of the notification appearing on - * surface device. - * @param {MutableList} capabilities The list of capabilities required in - * the surface. - * @param {MutableMap?} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkApp}. - * @return {ResponseWrapper?} HTTP response. - * @dialogflow - * @actionssdk - */ - fun askForNewSurface(context: String, notificationTitle: String, capabilities: MutableList, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForNewSurface: context=$context, notificationTitle=$notificationTitle, capabilities=$capabilities, dialogState=$dialogState") - val newSurfaceValueSpec = NewSurfaceValueSpec(context, notificationTitle, capabilities) - return fulfillSystemIntent(this.STANDARD_INTENTS.NEW_SURFACE, - this.INPUT_VALUE_DATA_TYPES.NEW_SURFACE, newSurfaceValueSpec, - "PLACEHOLDER_FOR_NEW_SURFACE", dialogState) - } - - - /** - * Requests the user to register for daily updates. - * - * @example - * val app = DialogflowApp(request, response) - * val WELCOME_INTENT = "input.welcome" - * val SHOW_IMAGE = "show.image" - * - * fun welcomeIntent (app) { - * app.askToRegisterDailyUpdate("show.image", mutableListOf(Arguments( - * name: "image_to_show", - * textValue: "image_type_1")) - * - * - * fun showImage (app) { - * showPicture(app.getArgument("image_to_show")) - * } - * - * val actionMap = new Map() - * actionMap.set(WELCOME_INTENT, welcomeIntent) - * actionMap.set(SHOW_IMAGE, showImage) - * app.handleRequest(actionMap) - * - * @param {String} intent If using Dialogflow, the action name of the intent - * to be triggered when the update is received. If using Actions SDK, the - * intent name to be triggered when the update is received. - * @param {Array?} intentArguments The necessary arguments - * to fulfill the intent triggered on update. These can be retrieved using - * {@link AssistantApp#getArgument}. - * @param {MutableMapOf?} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkApp}. - * @return {ResponseWrapper?} HTTP response. - * @dialogflow - * @actionssdk - */ - fun askToRegisterDailyUpdate(intent: String, intentArguments: MutableList? = null, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askToRegisterDailyUpdate: intent=$intent, intentArguments=$intentArguments, dialogState=$dialogState") - if (intent.isNullOrBlank()) { - handleError("Name of intent to trigger on update must be specified") - return null - } - val registerUpdateValueSpec = RegisterUpdateValueSpec( - intent = intent, - triggerContext = TriggerContext(timeContext = TimeContext(frequency = TIME_CONTEXT_FREQUENCY.DAILY)) - ) - - if (intentArguments?.isNotEmpty() == true) { - registerUpdateValueSpec.arguments = intentArguments - } - return this.fulfillRegisterUpdateIntent(this.STANDARD_INTENTS.REGISTER_UPDATE, - INPUT_VALUE_DATA_TYPES.REGISTER_UPDATE, registerUpdateValueSpec, - "PLACEHOLDER_FOR_REGISTER_UPDATE", dialogState) - } - - - internal abstract fun fulfillSignInRequest(dialogState: MutableMap?): ResponseWrapper? - internal abstract fun fulfillDateTimeRequest(confirmationValueSpec: ConfirmationValueSpec, dialogState: MutableMap?): ResponseWrapper? - internal abstract fun fulfillConfirmationRequest(confirmationValueSpec: ConfirmationValueSpec, dialogState: MutableMap?): ResponseWrapper? - internal abstract fun fulfillSystemIntent(intent: String, specType: String, intentSpec: NewSurfaceValueSpec, promptPlaceholder: String? = null, dialogState: MutableMap? = null): ResponseWrapper? - internal abstract fun fulfillRegisterUpdateIntent(intent: String, specType: String, intentSpec: RegisterUpdateValueSpec, promptPlaceholder: String? = null, dialogState: MutableMap? = null): ResponseWrapper? - - data class ConfirmationValueSpec(var dialogSpec: DialogSpec? = null) - - data class NewSurfaceValueSpec(var context: String? = null, - var notificationTitle: String? = null, - var capabilities: MutableList? = null) - - data class RegisterUpdateValueSpec(var intent: String? = null, - var arguments: MutableList? = null, - var triggerContext: TriggerContext? = null) - - data class TriggerContext(var timeContext: TimeContext? = null) - - data class TimeContext(var frequency: String? = null) - - data class DialogSpec(var requestConfirmationText: String? = null, - var requestDatetimeText: String? = null, - var requestDateText: String? = null, - var requestTimeText: String? = null) - - /** - * Checks whether user is in transactable state. - * - * @example - * val app = DialogflowApp(request = request, response = response) - * val WELCOME_INTENT = "input.welcome" - * val TXN_REQ_COMPLETE = "txn.req.complete" - * - * val transactionConfig = GooglePaymentTransactionConfig( - * deliveryAddressRequired = false, - * type = app.Transactions.PaymentType.BANK, - * displayName = "Checking-1234" - * ) - * fun welcomeIntent (app) { - * app.askForTransactionRequirements(transactionConfig) - * } - * - * fun txnReqCheck (app) { - * if (app.getTransactionRequirementsResult() == app.Transactions.ResultType.OK) { - * // continue cart building flow - * } else { - * // don"t continue cart building - * } - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * TXN_REQ_COMPLETE to ::txnReqCheck) - * app.handleRequest(actionMap) - * - * @param {ActionPaymentTransactionConfig|GooglePaymentTransactionConfig=} - * transactionConfig Configuration for the transaction. Includes payment - * options and order options. Optional if order has no payment or - * delivery. - * @param {DialogState=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkAssistant}. - * @return {ResponseWrapper} HTTP response. - * @actionssdk - * @dialogflow - */ - fun askForTransactionRequirements(transactionConfig: TransactionConfig? = null, dialogState: MutableMap? = null): ResponseWrapper? { - debug("checkForTransactionRequirements: transactionConfig=$transactionConfig," + - " dialogState=$dialogState") - val transactionRequirementsCheckSpec = TransactionRequirementsCheckSpec() - if (transactionConfig?.deliveryAddressRequired ?: false) { - transactionRequirementsCheckSpec.orderOptions = GoogleData.OrderOptions( - requestDeliveryAddress = transactionConfig?.deliveryAddressRequired ?: false) - } - if (transactionConfig?.type != null || - transactionConfig?.cardNetworks != null) { - transactionRequirementsCheckSpec.paymentOptions = - buildPaymentOptions(transactionConfig) - } - return fulfillTransactionRequirementsCheck(transactionRequirementsCheckSpec, - dialogState) - } - - /** - * Asks user to confirm transaction information. - * - * @example - * val app = DialogflowApp(request = request, response = response); - * val WELCOME_INTENT = "input.welcome" - * val TXN_COMPLETE = "txn.complete" - * - * val transactionConfig = GooglePaymentTransactionConfig( - * deliveryAddressRequired = false, - * type = app.Transactions.PaymentType.BANK, - * displayName = "Checking-1234" - * ) - * - * val order = app.buildOrder() - * // fill order cart - * - * fun welcomeIntent (app) { - * app.askForTransaction(order, transactionConfig) - * } - * - * function txnComplete (app) { - * // respond with order update - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * TXN_COMPLETE to ::txnComplete) - * app.handleRequest(actionMap) - * - * @param {Order} order Order built with buildOrder(). - * @param {ActionPaymentTransactionConfig|GooglePaymentTransactionConfig} - * transactionConfig Configuration for the transaction. Includes payment - * options and order options. - * @param {DialogState=} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. Used in {@link ActionsSdkAssistant}. - * @dialogflow - */ - fun askForTransactionDecision(order: Order, transactionConfig: TransactionConfig? = null, dialogState: MutableMap? = null): ResponseWrapper? { - debug("askForTransactionDecision: order=$order, transactionConfig=$transactionConfig, dialogState=$dialogState") - if (transactionConfig?.type != null && - transactionConfig.cardNetworks?.isNotEmpty() ?: false) { - handleError("Invalid transaction configuration. Must be of type" + - "ActionPaymentTransactionConfig or GooglePaymentTransactionConfig") - return null - } - val transactionDecisionValueSpec = TransactionDecisionValueSpec( - proposedOrder = order) - - if (transactionConfig?.deliveryAddressRequired ?: false) { - transactionDecisionValueSpec.orderOptions = GoogleData.OrderOptions( - requestDeliveryAddress = transactionConfig?.deliveryAddressRequired ?: false - ) - } - if (transactionConfig?.type != null || - transactionConfig?.cardNetworks?.isNotEmpty() ?: false) { - transactionDecisionValueSpec.paymentOptions = - buildPaymentOptions(transactionConfig) - } - if (transactionConfig?.customerInfoOptions != null) { - if (transactionDecisionValueSpec.orderOptions == null) { - transactionDecisionValueSpec.orderOptions = GoogleData.OrderOptions() - } - transactionDecisionValueSpec.orderOptions?.customerInfoOptions = - transactionConfig.customerInfoOptions - } - return fulfillTransactionDecision(transactionDecisionValueSpec, - dialogState) - } - - data class TransactionDecisionValueSpec(var proposedOrder: Order, var orderOptions: GoogleData.OrderOptions? = null, var paymentOptions: GoogleData.PaymentOptions? = null) - - data class TransactionRequirementsCheckSpec(var orderOptions: GoogleData.OrderOptions? = null, - var paymentOptions: GoogleData.PaymentOptions? = null) - - internal abstract fun fulfillTransactionRequirementsCheck(transactionRequirementsCheckSpec: TransactionRequirementsCheckSpec, dialogState: MutableMap? = null): ResponseWrapper? - internal abstract fun fulfillTransactionDecision(transactionDecisionValueSpec: TransactionDecisionValueSpec, dialogState: MutableMap? = null): ResponseWrapper? - - - fun doResponse(response: ResponseWrapper?, responseCode: Int = 0): ResponseWrapper? { - debug("doResponse_: responseWrapper=$response., responseCode=$responseCode") - if (responded) { - return null - } - if (response == null || response.body == null) { - this.handleError("Response can NOT be empty.") - return null - } else { - var code = RESPONSE_CODE_OK - if (responseCode != 0) { - code = responseCode - } - if (apiVersion_ != null) { - response.append(CONVERSATION_API_VERSION_HEADER, apiVersion_) - } - response.append(HTTP_CONTENT_TYPE_HEADER, HTTP_CONTENT_TYPE_JSON) - // If request was in Proto2 format, convert response to Proto2 - if (!this.isNotApiVersionOne()) { - //TODO migrate data -// if (response.data) { -// response.data = transformToSnakeCase(response.data); -// } else { -// response = transformToSnakeCase(response); -// } - } - val httpResponse = response.status(code).send(response.body!!) - this.responded = true - return httpResponse - } - } - - /** - * Constructs List with chainable property setters. - * - * @param {string=} title A title to set for a new List. - * @return {List} Constructed List. - */ - fun buildList(title: String? = null): List { - return List(title) - } - - /** - * Constructs Carousel with chainable property setters. - * - * @return {Carousel} Constructed Carousel. - */ - fun buildCarousel(): Carousel { - return Carousel() - } - - /** - * Constructs OptionItem with chainable property setters. - * - * @param {string=} key A unique key to identify this option. This key will - * be returned as an argument in the resulting actions.intent.OPTION - * intent. - * @param {string|Array=} synonyms A list of synonyms which the user may - * use to identify this option instead of the option key. - * @return {OptionItem} Constructed OptionItem. - */ - fun buildOptionItem(key: String, vararg synonyms: String): OptionItem { - val optionInfo = OptionInfo() - if (!key.isNullOrBlank()) { - optionInfo.key = key - } - if (synonyms.isNotEmpty()) { - optionInfo.synonyms = synonyms.toMutableList() - } - return OptionItem(optionInfo) - } - - - // --------------------------------------------------------------------------- - // Transaction Builders - // --------------------------------------------------------------------------- - - /** - * Constructs Order with chainable property setters. - * - * @param {String} orderId Unique identifier for the order. - * @return {Order} Constructed Order. - */ - fun buildOrder(orderId: String): Order { - return Order(orderId) - } - - /** - * Constructs Cart with chainable property setters. - * - * @param {String=} id Unique identifier for the cart. - * @return {Cart} Constructed Cart. - */ - fun buildCart(cartId: String? = null): Cart { - return Cart(cartId) - } - - /** - * Constructs LineItem with chainable property setters. - * - * @param {String} name Name of the line item. - * @param {String} id Unique identifier for the item. - * @return {LineItem} Constructed LineItem. - */ - fun buildLineItem(name: String, id: String): LineItem { - return LineItem(name, id) - } - - /** - * Constructs OrderUpdate with chainable property setters. - * - * @param {String} orderId Unique identifier of the order. - * @param {Boolean} isGoogleOrderId True if the order ID is provided by - * Google. False if the order ID is app provided. - * @return {OrderUpdate} Constructed OrderUpdate. - */ - fun buildOrderUpdate(orderId: String, isGoogleOrderId: Boolean): OrderUpdate { - return OrderUpdate(orderId, isGoogleOrderId) - } - - - internal abstract fun fulfillPermissionsRequest(permissionsSpec: GoogleData.PermissionsRequest, dialogState: MutableMap?): ResponseWrapper? - - abstract fun getIntent(): String? - - abstract fun tell(speech: String, displayText: String? = null): ResponseWrapper? - /** - * One arg function for Convenience from Java - */ - abstract fun tell(speech: String): ResponseWrapper? - - abstract fun tell(richResponse: RichResponse?): ResponseWrapper? - abstract fun tell(simpleResponse: SimpleResponse): ResponseWrapper? - - // --------------------------------------------------------------------------- - // Private Helpers - // --------------------------------------------------------------------------- - - private var lastErrorMessage: String? = null - /** - * Utility function to invoke an intent handler. - * - * @param {Object} handler The handler for the request. - * @param {string} intent The intent to handle. - * @return {boolean} true if the handler was invoked. - * @private - */ - private fun invokeIntentHandler(handler: Map<*, Handler>, intent: String?): Boolean { - debug("invokeIntentHandler_: handler=${handler::class.java.name}, intent=$intent") - lastErrorMessage = null - - // map of intents or states - //TODO handle State, Intent, & Map - val intentHandler = handler[intent] - - if (intentHandler != null) { - intentHandler(this) - return true - } else { - this.handleError("no matching intent handler for: " + intent) - return false - } - } - - /** - * Utility function to detect SSML markup. - * - * @param {string} text The text to be checked. - * @return {boolean} true if text is SSML markup. - * @private - */ - fun isSsml(text: String): Boolean { - debug("isSsml_: text=$text") - if (text.isEmpty()) { - this.handleError("text can NOT be empty.") - return false - } - return ResponseBuilder.isSsml(text) - } - - - /** - * Utility function to detect incoming request format. - * - * @return {boolean} true if request is not Action API Version 1. - * @private - */ - fun isNotApiVersionOne(): Boolean { - debug("isNotApiVersionOne_") - return if (actionsApiVersion.isEmpty()) { - true - } else { - (actionsApiVersion.toInt() >= ACTIONS_CONVERSATION_API_VERSION_TWO) - } - } - - internal abstract fun extractData() - - // --------------------------------------------------------------------------- - // Response Builders - // --------------------------------------------------------------------------- - - /** - * Constructs RichResponse with chainable property setters. - * - * @param {RichResponse=} richResponse RichResponse to clone. - * @return {RichResponse} Constructed RichResponse. - */ - fun buildRichResponse(richResponse: RichResponse? = null): RichResponse { - if (richResponse != null) { - return richResponse.copy() - } else { - return RichResponse() - } - } - - /** - * Zero arg function for convenience when calling from Java - */ - fun buildRichResponse() = buildRichResponse(null) - - - /** - * Constructs BasicCard with chainable property setters. - * - * @param {string=} bodyText Body text of the card. Can be set using setTitle - * instead. - * @return {BasicCard} Constructed BasicCard. - */ - fun buildBasicCard(bodyText: String): BasicCard { - val card = BasicCard() - if (bodyText.isNotBlank()) { - card.formattedText = bodyText - } - return card - } - - /** - * Helper to build prompts from SSML"s. - * - * @param {Array} ssmls Array of ssml. - * @return {Array} Array of SpeechResponse objects. - * @private - */ - fun buildPromptsFromSsmlHelper(ssmls: MutableList): MutableList { - debug("buildPromptsFromSsmlHelper_: ssmls=$ssmls") - return ssmls.map { GoogleData.NoInputPrompts(ssml = it) }.toMutableList() - } - - /** - * Helper to build prompts from plain texts. - * - * @param {Array} plainTexts Array of plain text to speech. - * @return {Array} Array of SpeechResponse objects. - * @private - */ - fun buildPromptsFromPlainTextHelper(plainTexts: MutableList): MutableList { - debug("buildPromptsFromPlainTextHelper_: plainTexts=$plainTexts") - return plainTexts.map { GoogleData.NoInputPrompts(textToSpeech = it) }.toMutableList() - } - - - /** - * If granted permission to user"s name in previous intent, returns user"s - * display name, family name, and given name. If name info is unavailable, - * returns null. - - * @example - * * val app = DialogflowApp(request = req, response = res) - * * val REQUEST_PERMISSION_ACTION = "request_permission" - * * val SAY_NAME_ACTION = "get_name" - * * - * * fun requestPermission (app: DialogflowApp) { - * * val permission = app.SupportedPermissions.NAME - * * app.askForPermission("To know who you are", permission) - * * } - * * - * * fun sayName (app: DialogflowApp) { - * * if (app.isPermissionGranted()) { - * * app.tell("Your name is " + app.getUserName().displayName)) - * * } else { - * * // Response shows that user did not grant permission - * * app.tell("Sorry, I could not get your name.") - * * } - * * } - * * val actionMap = mapOf( - * * REQUEST_PERMISSION_ACTION to requestPermission, - * * SAY_NAME_ACTION to sayName) - * * app.handleRequest(actionMap) - * * - * @return {Profile} Null if name permission is not granted. - * * - * @actionssdk - * * - * @dialogflow - */ - fun getUserName(): Profile? { - debug("getUserName") - return getUser()?.profile - } - - /** - * Gets the user locale. Returned string represents the regional language - * information of the user set in their Assistant settings. - * For example, "en-US" represents US English. - - * @example - * * val app = DialogflowApp(request, response) - * * val locale = app.getUserLocale() - * * - * * - * @return {String} User"s locale, e.g. "en-US". Null if no locale given. - * * - * @actionssdk - * * - * @dialogflow - */ - fun getUserLocale(): String? { - debug("getUserLocale") - return getUser()?.locale - } - - /** - * Get the user's last seen time as a Date object. - * Not supported in V1. - * - * @example - * const app = new DialogflowApp({request, response}); - * const lastSeen = app.getLastSeen(); - * - * Returns a String and client can user as they wish. i.e. ZonedDateTime.parse(app.getLastSeen()), or JodaTime, etc. - * @return {String | null} User's last seen date or null if never seen - */ - fun getLastSeen(): String? { - debug("getLastSeen"); - val user = this.getUser() - return user?.lastSeen - } - - - /** - * Returns the set of other available surfaces for the user. - * - * @return {Array} Empty if no available surfaces. - * @actionssdk - * @dialogflow - */ - fun getAvailableSurfaces(): MutableList { - debug("getAvailableSurfaces") - return requestExtractor.requestData()?.availableSurfaces ?: mutableListOf() - } - - /** - * Returns true if user has an available surface which includes all given - * capabilities. Available surfaces capabilities may exist on surfaces other - * than that used for an ongoing conversation. - * - * @param {string|Array} capabilities Must be one of - * {@link SurfaceCapabilities}. - * @return {boolean} True if user has a capability available on some surface. - * - * @dialogflow - * @actionssdk - */ - fun hasAvailableSurfaceCapabilities(vararg capabilities: String): Boolean { - debug("hasAvailableSurfaceCapabilities: capabilities=$capabilities") - val availableSurfaces = requestExtractor.requestData() - availableSurfaces?.availableSurfaces?.forEach { - val availableCapabilities = it.capabilities?.map { it.name } - val unavailableCapabilities = capabilities.filter { !(availableCapabilities?.contains(it) ?: false) } - if (unavailableCapabilities.isEmpty()) { - return true - } - } - return false - } - - /** - * Returns the result of the AskForNewSurface helper. - * - * @return {boolean} True if user has triggered conversation on a new device - * following the NEW_SURFACE intent. - * @actionssdk - * @dialogflow - */ - fun isNewSurface(): Boolean { - debug("isNewSurface") - val argument = requestExtractor.findArgument(this.BUILT_IN_ARG_NAMES.NEW_SURFACE) - return argument?.extension?.status == "OK" - } - - /** - * Returns true if user device has a given surface capability. - * - * @param {string} capability Must be one of {@link SurfaceCapabilities}. - * @return {boolean} True if user device has the given capability. - * - * @example - * val app = DialogflowApp(request = req, response = res) - * val DESCRIBE_SOMETHING = "DESCRIBE_SOMETHING" - * - * fun describe (app: DialogflowApp) { - * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * app.tell(richResponseWithBasicCard) - * } else { - * app.tell("Let me tell you about ...") - * } - * } - * val actionMap = mapOf( - * DESCRIBE_SOMETHING to ::describe) - * app.handleRequest(actionMap) - * - * @dialogflow - * @actionssdk - */ - fun hasSurfaceCapability(requestedCapability: String): Boolean { - debug("hasSurfaceCapability: requestedCapability=$requestedCapability") - val capabilities = getSurfaceCapabilities() - if (capabilities?.isEmpty() ?: false) { - error("No incoming capabilities to search " + - "for request capability: $requestedCapability") - return false - } - return capabilities?.contains(requestedCapability) ?: false - } - - fun handleError(text: String?) { - debug("handleError_: text=%$text") - if (text.isNullOrEmpty()) { - error("Missing text") - return - } - // Log error -// error.apply(text, Array.prototype.slice.call(arguments, 1)); - // Tell app to say error - if (responded) { - return - } - // Don"t call other methods; just do directly - //TODO revist if response should be sent on all errors - issue with context not set when from other platforms - this.response.status(RESPONSE_CODE_BAD_REQUEST) -// this.response.status(RESPONSE_CODE_BAD_REQUEST).send(API_ERROR_MESSAGE_PREFIX + text) -// this.responded = true - } - - /** - * Helper to process a transaction config and create a payment options object. - * - * @param {ActionPaymentTransactionConfig|GooglePaymentTransactionConfig} - * transactionConfig Configuration for the transaction. Includes payment - * options and order options. - * @return {PaymentOptions} paymentOptions - * @private - */ - fun buildPaymentOptions(transactionConfig: TransactionConfig? = null): GoogleData.PaymentOptions { - debug("buildPromptsFromPlainTextHelper_: transactionConfig=${transactionConfig}") - var paymentOptions = GoogleData.PaymentOptions() - if (transactionConfig?.type != null) { // Action payment - paymentOptions.actionProvidedOptions = GoogleData.ActionProvidedOptions( - paymentType = transactionConfig.type, - displayName = transactionConfig.displayName - ) - } else { // Google payment - paymentOptions.googleProvidedOptions = GoogleData.GoogleProvidedOptions( - supportedCardNetworks = transactionConfig?.cardNetworks ?: mutableListOf(), - prepaidCardDisallowed = transactionConfig?.prepaidCardDisallowed ?: false - ) - if (transactionConfig?.tokenizationParameters != null) { - paymentOptions.googleProvidedOptions?.tokenizationParameters = GoogleData.TokenizationParameters( - tokenizationType = "PAYMENT_GATEWAY", - parameters = transactionConfig.tokenizationParameters - ) - } - } - return paymentOptions - } - - - fun getUser() = requestExtractor.getUser() - fun getDeviceLocation() = requestExtractor.getDeviceLocation() - fun getArgumentCommon(argName: String) = requestExtractor.getArgumentCommon(argName) - fun getTransactionRequirementsResult() = requestExtractor.getTransactionRequirementsResult() - fun getDeliveryAddress() = requestExtractor.getDeliveryAddress() - fun getTransactionDecision() = requestExtractor.getTransactionDecision() - fun getUserConfirmation() = requestExtractor.getUserConfirmation() - fun getDateTime() = requestExtractor.getDateTime() - fun getSignInStatus() = requestExtractor.getSignInStatus() - fun isInSandbox() = requestExtractor.isInSandbox() - fun getSurfaceCapabilities() = requestExtractor.getSurfaceCapabilities() - fun getInputType() = requestExtractor.getInputType() - fun isPermissionGranted() = requestExtractor.isPermissionGranted() - fun getRepromptCount() = requestExtractor.getRepromptCount() - fun isFinalReprompt() = requestExtractor.isFinalReprompt() - fun isUpdateRegistered() = requestExtractor.isUpdateRegistered() -} - -/** - * reference to Functions that will be called for logging and errors. - */ -val defaultLogFunction: ((String) -> Unit)? = { - logger.info(it) -} -var debugFunction: ((String) -> Unit)? = null -var errorFunction: ((String) -> Unit)? = defaultLogFunction - -fun debug(msg: String) { - debugFunction?.invoke(msg) -} - -fun error(msg: String) { - errorFunction?.invoke(msg) -} - diff --git a/sdk/src/main/java/com/tmsdurham/actions/DialogflowApp.kt b/sdk/src/main/java/com/tmsdurham/actions/DialogflowApp.kt deleted file mode 100644 index 11715f4..0000000 --- a/sdk/src/main/java/com/tmsdurham/actions/DialogflowApp.kt +++ /dev/null @@ -1,1437 +0,0 @@ -package com.tmsdurham.actions - -import com.tmsdurham.dialogflow.* -import com.tmsdurham.dialogflow.google.GoogleData - - -class DialogflowApp : AssistantApp { - - - // Constants - val RESPONSE_CODE_OK = 200 - val ACTIONS_DIALOGFLOW_CONTEXT = "_actions_on_google_" - val MAX_LIFESPAN = 100 - val INPUTS_MAX = 3 - val ORIGINAL_SUFFIX = ".original" - val SELECT_EVENT = "actions_intent_option" - - // Dialogflow Rich Response item types - val SIMPLE_RESPONSE = "simple_response" - val BASIC_CARD = "basic_card" - val LIST = "list_card" - val CAROUSEL = "carousel_card" - val SUGGESTIONS = "suggestion_chips" - val LINK_OUT_SUGGESTION = "link_out_chip" - val TYPE = "type" - val PLATFORM = "platform" - - - constructor(request: RequestWrapper, response: ResponseWrapper, sessionStarted: (() -> Unit)? = null) : - super(request, response, sessionStarted) { - debug("DialogflowApp constructor") - - // If request contains originalRequest, convert to Proto3. - if (request.body.originalRequest != null && !isNotApiVersionOne()) { - //TODO("convert to Proto3") - } - - debug("new == ${CONVERSATION_STAGES.NEW}") - debug("type == ${request.body.originalRequest?.data?.conversation?.type}") - if ((request.body.originalRequest?.data?.conversation?.type == - CONVERSATION_STAGES.NEW) && sessionStarted != null) { - sessionStarted() - } - } - - /** - * Verifies whether the request comes from Dialogflow. - * - * @param {String} key The header key specified by the developer in the - * Dialogflow Fulfillment settings of the app. - * @param {String} value The private value specified by the developer inside the - * fulfillment header. - * @return {Boolean} True if the request comes from Dialogflow. - * @dialogflow - */ - fun isRequestFromDialogflow(key: String, value: String): Boolean { - debug("isRequestFromDialogflow: key=$key, value=$value") - if (key.isBlank()) { - handleError("key must be specified.") - return false - } - if (value.isBlank()) { - handleError("value must be specified.") - return false - } - return request.get(key) == value - } - - /** - * Get the current intent. Alternatively, using a handler Map with - * {@link AssistantApp#handleRequest|handleRequest}, - * the client library will automatically handle the incoming intents. - * - * @example - * val app = DialogflowApp(request = request, response = response) - * - * fun responseHandler (app: DialogflowApp) { - * val intent = app.getIntent() - * when (intent) { - * WELCOME_INTENT -> - * app.ask("Welcome to action snippets! Say a number.") - * - * NUMBER_INTENT -> { - * val number = app.getArgument(NUMBER_ARGUMENT) - * app.tell("You said $number") - * } - * } - * } - * - * app.handleRequest(responseHandler); - * - * @return {string} Intent id or null if no value. - * @dialogflow - */ - override fun getIntent(): String? { - debug("getIntent") - if (request.body.result.action == null) { - handleError("Missing result from request body") - return null - } - return request.body.result.action - } - - /** - * Get the argument value by name from the current intent. If the argument - * is included in originalRequest, and is not a text argument, the entire - * argument object is returned. - * - * Note: If incoming request is using an API version under 2 (e.g. "v1"), - * the argument object will be in Proto2 format (snake_case, etc). - * - * @example - * val app = DialogflowApp(request = request, response = response) - * val WELCOME_INTENT = "input.welcome" - * val NUMBER_INTENT = "input.number" - * - * fun welcomeIntent (app: DialogflowApp) { - * app.ask("Welcome to action snippets! Say a number."); - * } - * - * fun numberIntent (app: DialogflowApp) { - * val number = app.getArgument(NUMBER_ARGUMENT) - * app.tell("You said " + number) - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to welcomeIntent, - * NUMBER_INTENT to numberIntent) - * app.handleRequest(actionMap) - * - * @param {String} argName Name of the argument. - * @return {Object} Argument value matching argName - * or null if no matching argument. - * @dialogflow - */ - fun getArgument(argName: String): Any? { - debug("getArgument: argName=$argName") - if (argName.isBlank()) { - this.handleError("Invalid argument name") - return null - } - val parameters = request.body.result.parameters - if (parameters != null) { - if (parameters[argName] != null) { - return parameters[argName] - } - } - return requestExtractor.getArgumentCommon(argName) - } - - /** - * Get the context argument value by name from the current intent. Context - * arguments include parameters collected in previous intents during the - * lifespan of the given context. If the context argument has an original - * value, usually representing the underlying entity value, that will be given - * as part of the return object. - * - * @example - * const app = new DialogflowApp({request: request, response: response}); - * const WELCOME_INTENT = "input.welcome"; - * const NUMBER_INTENT = "input.number"; - * const OUT_CONTEXT = "output_context"; - * const NUMBER_ARG = "myNumberArg"; - * - * function welcomeIntent (app) { - * const parameters = {}; - * parameters[NUMBER_ARG] = "42"; - * app.setContext(OUT_CONTEXT, 1, parameters); - * app.ask("Welcome to action snippets! Ask me for your number."); - * } - * - * function numberIntent (app) { - * const number = app.getContextArgument(OUT_CONTEXT, NUMBER_ARG); - * // number == { value: 42 } - * app.tell("Your number is " + number.value); - * } - * - * const actionMap = new Map(); - * actionMap.set(WELCOME_INTENT, welcomeIntent); - * actionMap.set(NUMBER_INTENT, numberIntent); - * app.handleRequest(actionMap); - * - * @param {string} contextName Name of the context. - * @param {string} argName Name of the argument. - * @return {Object} Object containing value property and optional original - * property matching context argument. Null if no matching argument. - * @dialogflow - */ - fun getContextArgument(contextName: String, argName: String): ContextArgument? { - debug("getContextArgument: contextName=$contextName, argName=$argName") - if (contextName.isBlank()) { - this.handleError("Invalid context name") - return null - } - if (argName.isBlank()) { - this.handleError("Invalid argument name") - return null - } - if (request.body.result.contexts.isEmpty()) { - this.handleError("No contexts included in request") - return null - } - request.body.result.contexts.forEach { - if (it.name == contextName) { - if (it.parameters != null) { - val argument = ContextArgument(value = it.parameters!![argName]) - if (it.parameters!![argName + ORIGINAL_SUFFIX] != null) { - argument.original = it.parameters!![argName + ORIGINAL_SUFFIX] - } - return argument - } - } - } - debug("Failed to get context argument value: $argName") - return null - } - - - /** - * Returns the RichResponse constructed in Dialogflow response builder. - * - * @example - * val app = DialogflowApp(request = req, response = res) - * - * fun tellFact (app: DialogflowApp) { - * val fact = "Google was founded in 1998" - * - * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * app.ask(app.getIncomingRichResponse().addSimpleResponse("Here\"s a " + - * "fact for you. " + fact + " Which one do you want to hear about " + - * "next, Google\"s history or headquarters?")) - * } else { - * app.ask("Here\"s a fact for you. " + fact + " Which one " + - * "do you want to hear about next, Google\"s history or headquarters?") - * } - * } - * - * val actionMap = mapOf("tell.fact" to tellFact) - * - * app.handleRequest(actionMap) - * - * @return {RichResponse} RichResponse created in Dialogflow. If no RichResponse was - * created, an empty RichResponse is returned. - * @dialogflow - */ - fun getIncomingRichResponse(): RichResponse { - debug("getIncomingRichResponse") - val response = buildRichResponse() - request.body.result.fulfillment?.messages?.forEach { - when (it.type) { - SIMPLE_RESPONSE -> { - val item = SimpleResponse() - item.textToSpeech = it.textToSpeech - item.displayText = it.displayText - if (response.items.size == 0) { - response.items.add(RichResponseItem(item)) - } else { - response.items.add(0, RichResponseItem(item)) - } - } - BASIC_CARD -> { - val item = BasicCard() - item.formattedText = it.formattedText ?: "" - if (it.buttons != null) { - item.buttons = it.buttons!! - } - item.image = it.image - item.subtitle = it.subtitle - item.title = it.title ?: "" - response.items.add(RichResponseItem(basicCard = item)) - } - SUGGESTIONS -> { - response.suggestions = it.suggestions - } - LINK_OUT_SUGGESTION -> response.linkOutSuggestion = LinkOutSuggestion(it.destinationName, it.url) - } - } - return response - } - - /** - * Returns the List constructed in Dialogflow response builder. - * - * @example - * val app = DialogflowApp(request = req, response = res) - * - * fun pickOption (app: DialogflowApp) { - * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * app.askWithList("Which of these looks good?", - * app.getIncomingList().addItems( - * app.buildOptionItem("another_choice", ["Another choice"]). - * setTitle("Another choice"))) - * } else { - * app.ask("What would you like?") - * } - * } - * - * val actionMap = mapOf( - * "pick.option" to ::pickOption) - * - * app.handleRequest(actionMap) - * - * @return {List} List created in Dialogflow. If no List was created, an empty - * List is returned. - * @dialogflow - */ - fun getIncomingList(): List { - debug("getIncomingList") - val list = buildList() - request.body.result.fulfillment?.messages?.forEach { - if (it.type == LIST) { - list.title = it.title - list.items = it.items ?: mutableListOf() - } - } - return list - } - - - /** - * Returns the Carousel constructed in Dialogflow response builder. - * - * @example - * val app = DialogflowApp(request = req, response = res) - * - * fun pickOption (app: DialogflowApp) { - * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT)) { - * app.askWithCarousel("Which of these looks good?", - * app.getIncomingCarousel().addItems( - * app.buildOptionItem("another_choice", ["Another choice"]). - * setTitle("Another choice").setDescription("Choose me!"))) - * } else { - * app.ask("What would you like?") - * } - * } - * - * val actionMap = mapOf( - * "pick.option" to ::pickOption) - * - * app.handleRequest(actionMap) - * - * @return {Carousel} Carousel created in Dialogflow. If no Carousel was created, - * an empty Carousel is returned. - * @dialogflow - */ - fun getIncomingCarousel(): Carousel { - debug("getIncomingCarousel") - val carousel = buildCarousel() - request.body.result.fulfillment?.messages?.forEach { - if (it.type == CAROUSEL) { - carousel.items = it.items ?: mutableListOf() - } - } - return carousel - } - - /** - * Returns the option key user chose from options response. - * @example - * * val app = DialogflowApp(request = req, response = res); - * * - * * fun pickOption (app: DialogflowApp) { - * * if (app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT) != null) { - * * app.askWithCarousel("Which of these looks good?", - * * app.getIncomingCarousel().addItems( - * * app.buildOptionItem("another_choice", ["Another choice"]). - * * setTitle("Another choice").setDescription("Choose me!"))) - * * } else { - * * app.ask("What would you like?") - * * } - * * } - * * - * * fun optionPicked (app: DialogflowApp) { - * * assistant.ask("You picked " + app.getSelectedOption()) - * * } - * * - * * val actionMap = mapOf( - * * "pick.option" to pickOption, - * * "option.picked" to optionPicked) - * * - * * app.handleRequest(actionMap) - * * - * * - * @return {string} Option key of selected item. Null if no option selected or - * * if current intent is not OPTION intent. - * * - * @dialogflow - */ - fun getSelectedOption(): String? { - debug("getSelectedOption") - if (getContextArgument(SELECT_EVENT, BUILT_IN_ARG_NAMES.OPTION)?.value != null) { - return getContextArgument(SELECT_EVENT, BUILT_IN_ARG_NAMES.OPTION)?.value as String? - } else if (getArgument(BUILT_IN_ARG_NAMES.OPTION) != null) { - return getArgument(BUILT_IN_ARG_NAMES.OPTION) as String? - } - debug("Failed to get selected option") - return null - } - - data class ContextArgument(var value: Any?, var original: Any? = null) - - /** - * Asks to collect the user"s input. - * - * NOTE: Due to a bug, if you specify the no-input prompts, - * the mic is closed after the 3rd prompt, so you should use the 3rd prompt - * for a bye message until the bug is fixed. - * - * @example - * const app = new DialogflowApp({request: request, response: response}); - * const WELCOME_INTENT = "input.welcome"; - * const NUMBER_INTENT = "input.number"; - * - * function welcomeIntent (app) { - * app.ask("Welcome to action snippets! Say a number.", - * ["Say any number", "Pick a number", "We can stop here. See you soon."]); - * } - * - * function numberIntent (app) { - * const number = app.getArgument(NUMBER_ARGUMENT); - * app.tell("You said " + number); - * } - * - * const actionMap = new Map(); - * actionMap.set(WELCOME_INTENT, welcomeIntent); - * actionMap.set(NUMBER_INTENT, numberIntent); - * app.handleRequest(actionMap); - * - * @param {string|SimpleResponse|RichResponse} inputPrompt The input prompt - * response. - * @param {Array=} noInputs Array of re-prompts when the user does not respond (max 3). - * @return {Object} HTTP response. - * @dialogflow - */ - fun ask(inputPrompt: RichResponse, noInputs: MutableList? = null): ResponseWrapper? { - debug("ask: inputPrompt=$inputPrompt, noInputs=$noInputs") - if (inputPrompt.empty()) { - handleError("Invalid input prompt") - return null - } - val response = buildResponse(inputPrompt, true, noInputs) - if (response == null) { - error("Error in building response") - return null - } - return doResponse(response, RESPONSE_CODE_OK) - } - - fun ask(speech: String, vararg noInputs: String = arrayOf()): ResponseWrapper? { - debug("ask: speech:$speech") - if (speech.isBlank()) { - handleError("Invalid input prompt") - return null - } - val response = buildResponse(speech, true, noInputs = noInputs.toMutableList()) - if (response == null) { - error("Error in building response") - return null - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * One arg function for convenience when calling from Java - */ - fun ask(speech: String): ResponseWrapper? { - debug("ask: speech:$speech") - if (speech.isBlank()) { - handleError("Invalid input prompt") - return null - } - val response = buildResponse(speech, true, noInputs = mutableListOf()) - if (response == null) { - error("Error in building response") - return null - } - return doResponse(response, RESPONSE_CODE_OK) - } - - fun ask(speech: String, displayText: String?): ResponseWrapper? { - debug("ask: speechResponse=$speech displayText=$displayText") - if (speech.isNullOrBlank()) { - handleError("Invalid speech response") - return null - } - val simpleResponse = SimpleResponse(textToSpeech = speech, displayText = displayText) - val response = buildResponse(simpleResponse, true) - return this.doResponse(response, RESPONSE_CODE_OK) - } - - fun ask(richResponse: RichResponse) = ask(richResponse, null) - - /** - * Asks to collect the user"s input with a list. - * - * @example - * const app = new DialogflowApp({request, response}); - * const WELCOME_INTENT = "input.welcome"; - * const OPTION_INTENT = "option.select"; - * - * function welcomeIntent (app) { - * app.askWithList("Which of these looks good?", - * app.buildList("List title") - * .addItems([ - * app.buildOptionItem(SELECTION_KEY_ONE, - * ["synonym of KEY_ONE 1", "synonym of KEY_ONE 2"]) - * .setTitle("Title of First List Item"), - * app.buildOptionItem(SELECTION_KEY_TWO, - * ["synonym of KEY_TWO 1", "synonym of KEY_TWO 2"]) - * .setTitle("Title of Second List Item"), - * ])); - * } - * - * function optionIntent (app) { - * if (app.getSelectedOption() == SELECTION_KEY_ONE) { - * app.tell("Number one is a great choice!"); - * } else { - * app.tell("Number two is a great choice!"); - * } - * } - * - * const actionMap = new Map(); - * actionMap.set(WELCOME_INTENT, welcomeIntent); - * actionMap.set(OPTION_INTENT, optionIntent); - * app.handleRequest(actionMap); - * - * @param {string|RichResponse|SimpleResponse} inputPrompt The input prompt - * response. - * @param {List} list List built with {@link AssistantApp#buildList|buildList}. - * @return {Object} HTTP response. - * @dialogflow - */ - - fun askWithList(richResponse: RichResponse, list: List): ResponseWrapper? { - if (list.items.size < 2) { - this.handleError("List requires at least 2 items") - return null - } - return askWithResponseAndList(buildResponse(richResponse, true), list) - } - - fun askWithList(inputPrompt: String?, list: List): ResponseWrapper? { - debug("askWithList: inputPrompt=$inputPrompt, list=$list") - if (inputPrompt.isNullOrBlank()) { - this.handleError("Invalid input prompt") - return null - } - - if (list.items.size < 2) { - this.handleError("List requires at least 2 items") - return null - } - return askWithResponseAndList(buildResponse(inputPrompt ?: "", true), list) - } - - private fun askWithResponseAndList(response: ResponseWrapper?, list: List): ResponseWrapper? { - if (response == null) { - error("Error in building response") - return null - } - response.body?.data?.google?.systemIntent { - intent = STANDARD_INTENTS.OPTION - } - if (isNotApiVersionOne()) { - response.body?.data?.google?.systemIntent?.data = GoogleData.Data( - `@type` = INPUT_VALUE_DATA_TYPES.OPTION, - listSelect = list) - } else { - response.body?.data?.google?.systemIntent?.spec = GoogleData.Spec( - optionValueSpec = GoogleData.OptionValueSpec( - listSelect = list)) - } - - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Asks to collect the user"s input with a carousel. - * - * @example - * const app = new DialogflowApp({request, response}); - * const WELCOME_INTENT = "input.welcome"; - * const OPTION_INTENT = "option.select"; - * - * function welcomeIntent (app) { - * app.askWithCarousel("Which of these looks good?", - * app.buildCarousel() - * .addItems([ - * app.buildOptionItem(SELECTION_KEY_ONE, - * ["synonym of KEY_ONE 1", "synonym of KEY_ONE 2"]) - * .setTitle("Number one"), - * app.buildOptionItem(SELECTION_KEY_TWO, - * ["synonym of KEY_TWO 1", "synonym of KEY_TWO 2"]) - * .setTitle("Number two"), - * ])); - * } - * - * function optionIntent (app) { - * if (app.getSelectedOption() == SELECTION_KEY_ONE) { - * app.tell("Number one is a great choice!"); - * } else { - * app.tell("Number two is a great choice!"); - * } - * } - * - * const actionMap = new Map(); - * actionMap.set(WELCOME_INTENT, welcomeIntent); - * actionMap.set(OPTION_INTENT, optionIntent); - * app.handleRequest(actionMap); - * - * @param {string|RichResponse|SimpleResponse} inputPrompt The input prompt - * response. - * @param {Carousel} carousel Carousel built with - * {@link AssistantApp#buildCarousel|buildCarousel}. - * @return {Object} HTTP response. - * @dialogflow - */ - fun askWithCarousel(inputPrompt: String, carousel: Carousel): ResponseWrapper? { - debug("askWithCarousel: inputPrompt=$inputPrompt, carousel=$carousel") - if (inputPrompt.isNullOrBlank()) { - handleError("Invalid input prompt") - return null - } - - if (carousel.items.size < 2) { - handleError("Carousel requires at least 2 items") - return null - } - val response = buildResponse(inputPrompt, true) - if (response == null) { - error("Error in building response") - return null - } - response.body?.data?.google?.systemIntent = GoogleData.SystemIntent( - intent = STANDARD_INTENTS.OPTION - ) - if (isNotApiVersionOne()) { - response.body?.data?.google?.systemIntent?.data = GoogleData.Data( - `@type` = INPUT_VALUE_DATA_TYPES.OPTION, - carouselSelect = carousel - ) - } else { - response.body?.data?.google?.systemIntent?.spec = GoogleData.Spec( - optionValueSpec = GoogleData.OptionValueSpec( - carouselSelect = carousel - ) - ) - } - return doResponse(response, RESPONSE_CODE_OK) - } - - - /** - * Same as #askWithCarousel(input:String, carousel: Carousel), except takes a RichResponse. - */ - fun askWithCarousel(inputPrompt: RichResponse, carousel: Carousel): ResponseWrapper? { - debug("askWithCarousel: inputPrompt=$inputPrompt, carousel=$carousel") - if (inputPrompt.empty()) { - handleError("Invalid input prompt") - return null - } - if (carousel == null) { - handleError("Invalid carousel") - return null - } - if (carousel.items.size < 2) { - handleError("Carousel requires at least 2 items") - return null - } - val response = buildResponse(inputPrompt, true) - if (response == null) { - error("Error in building response") - return null - } - response.body?.data?.google?.systemIntent = GoogleData.SystemIntent( - intent = STANDARD_INTENTS.OPTION - ) - if (isNotApiVersionOne()) { - response.body?.data?.google?.systemIntent?.data = GoogleData.Data( - `@type` = INPUT_VALUE_DATA_TYPES.OPTION, - carouselSelect = carousel - ) - } else { - response.body?.data?.google?.systemIntent?.spec = GoogleData.Spec( - optionValueSpec = GoogleData.OptionValueSpec( - carouselSelect = carousel - ) - ) - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Asks user for delivery address. - * - * @example - * val app = DialogflowApp(request = request, response = response) - * val WELCOME_INTENT = "input.welcome" - * val DELIVERY_INTENT = "delivery.address" - * - * fun welcomeIntent (app) { - * app.askForDeliveryAddress("To make sure I can deliver to you") - * } - * - * fun addressIntent (app) { - * val postalCode = app.getDeliveryAddress().postalAddress.postalCode - * if (isInDeliveryZone(postalCode)) { - * app.tell("Great looks like you\"re in our delivery area!") - * } else { - * app.tell("I\"m sorry it looks like we can\"t deliver to you.") - * } - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * DELIVERY_INTENT to ::addressIntent) - * app.handleRequest(actionMap) - * - * @param {String} reason Reason given to user for asking delivery address. - * @return {ResponseWrapper>} HTTP response. - * @dialogflow - */ - fun askForDeliveryAddress(reason: String): ResponseWrapper? { - debug("askForDeliveryAddress: reason=$reason") - if (reason.isBlank()) { - this.handleError("reason cannot be empty") - return null - } - val response = buildResponse("PLACEHOLDER_FOR_DELIVERY_ADDRESS", true) - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.DELIVERY_ADDRESS - data { - `@type` = INPUT_VALUE_DATA_TYPES.DELIVERY_ADDRESS - addressOptions = GoogleData.AddressOptions(reason) - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Tells the Assistant to render the speech response and close the mic. - * - * @example - * const app = new DialogflowApp({request: request, response: response}); - * const WELCOME_INTENT = "input.welcome"; - * const NUMBER_INTENT = "input.number"; - * - * function welcomeIntent (app) { - * app.ask("Welcome to action snippets! Say a number."); - * } - * - * function numberIntent (app) { - * const number = app.getArgument(NUMBER_ARGUMENT); - * app.tell("You said " + number); - * } - * - * const actionMap = new Map(); - * actionMap.set(WELCOME_INTENT, welcomeIntent); - * actionMap.set(NUMBER_INTENT, numberIntent); - * app.handleRequest(actionMap); - * - * @param {string|SimpleResponse|RichResponse} textToSpeech Final response. - * Spoken response can be SSML. - * @return The response that is sent back to Assistant. - * @dialogflow - */ - override fun tell(richResponse: RichResponse?): ResponseWrapper? { - debug("tell: richResponse=$richResponse") - if (richResponse == null || richResponse.empty()) { - handleError("Invalid rich response") - return null - } - val response = buildResponse(richResponse, false) - return doResponse(response, RESPONSE_CODE_OK) - } - - override fun tell(simpleResponse: SimpleResponse): ResponseWrapper? { - debug("tell: speechResponse=$simpleResponse") - if (simpleResponse.empty()) { - handleError("Invalid speech response") - return null - } - val response = buildResponse(simpleResponse, false) - return doResponse(response, RESPONSE_CODE_OK) - } - - override fun tell(speech: String, displayText: String?): ResponseWrapper? { - debug("tell: speechResponse=$speech displayText=$displayText") - if (speech.isNullOrBlank()) { - handleError("Invalid speech response") - return null - } - val simpleResponse = SimpleResponse() - if (isSsml(speech)) { - simpleResponse.ssml = speech - } else { - simpleResponse.textToSpeech = speech - } - simpleResponse.displayText = displayText - val response = buildResponse(simpleResponse, false) - return this.doResponse(response, RESPONSE_CODE_OK) - } - - override fun tell(speech: String): ResponseWrapper? { - debug("tell: speechResponse=$speech") - if (speech.isBlank()) { - handleError("Invalid speech response") - return null - } - - val response = buildResponse(speech, false) - return this.doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Set a new context for the current intent. - * - * @example - * val app = DialogflowApp(request = request, response = response) - * val CONTEXT_NUMBER = "number" - * val NUMBER_ARGUMENT = "myNumber" - * - * fun welcomeIntent (app: DialogflowApp) { - * app.setContext(CONTEXT_NUMBER) - * app.ask("Welcome to action snippets! Say a number.") - * } - * - * fun numberIntent (app: DialogflowApp) { - * val number = app.getArgument(NUMBER_ARGUMENT) - * app.tell("You said " + number) - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * NUMBER_INTENT to ::numberIntent) - * app.handleRequest(actionMap) - * - * @param {String} name Name of the context. Dialogflow converts to lowercase. - * @param {Int} [lifespan=1] Context lifespan. - * @param {Map=} parameters Context JSON parameters. - * @dialogflow - */ - fun setContext(name: String, lifespan: Int? = null, parameters: MutableMap? = null): Unit { - debug("setContext: context=$contexts, lifespan=$lifespan, parameters=$parameters") - if (name.isEmpty()) { - handleError("Invalid context name") - return - } - val newContext = Context( - name = name, - lifespan = 1 - ) - if (lifespan != null) { - newContext.lifespan = lifespan - } - if (parameters != null) { - newContext.parameters = parameters - } - this.contexts[name] = newContext - } - - /** - * Returns the incoming contexts for this intent. - * - * @example - * val app = DialogflowApp(request = request, response = response) - * val CONTEXT_NUMBER = "number" - * val NUMBER_ARGUMENT = "myNumber" - * - * function welcomeIntent (app: DialogflowApp) { - * app.setContext(CONTEXT_NUMBER) - * app.ask("Welcome to action snippets! Say a number.") - * } - * - * fun numberIntent (app: DialogflowApp) { - * val contexts = app.getContexts() - * // contexts == [{ - * // name: "number", - * // lifespan: 0, - * // parameters: { - * // myNumber: "23", - * // myNumber.original: "23" - * // } - * // }] - * val number = app.getArgument(NUMBER_ARGUMENT) - * app.tell("You said " + number) - * } - * - * val actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * NUMBER_INTENT to numberIntent) - * app.handleRequest(actionMap) - * - * @return {MutableList} Empty if no active contexts. - * @dialogflow - */ - fun getContexts(): MutableList { - debug("getContexts") - if (request.body.result.contexts.isEmpty()) { - handleError("No contexts included in request") - return mutableListOf() - } - return request.body.result.contexts.filter { it.name != ACTIONS_DIALOGFLOW_CONTEXT }.filterNotNull().toMutableList() - } - - /** - * Returns the incoming context by name for this intent. - * - * @example - * val app = Dialogflowapp(request = request, response = response) - * val CONTEXT_NUMBER = "number" - * val NUMBER_ARGUMENT = "myNumber" - * - * fun welcomeIntent (app: DialogflowApp) { - * app.setContext(CONTEXT_NUMBER) - * app.ask("Welcome to action snippets! Say a number.") - * } - * - * fun numberIntent (app: DialogflowApp) { - * val context = app.getContext(CONTEXT_NUMBER) - * // context == { - * // name: "number", - * // lifespan: 0, - * // parameters: { - * // myNumber: "23", - * // myNumber.original: "23" - * // } - * // } - * val number = app.getArgument(NUMBER_ARGUMENT) - * app.tell("You said " + number) - * } - * - * const actionMap = mapOf( - * WELCOME_INTENT to ::welcomeIntent, - * NUMBER_INTENT to ::numberIntent) - * app.handleRequest(actionMap) - * - * @return {Object} Context value matching name - * or null if no matching context. - * @dialogflow - */ - - fun getContext(name: String): Context? { - debug("getContext: name=$name") - if (request.body.result.contexts == null) { - handleError("No contexts included in request") - return null - } - request.body.result.contexts.forEach { - if (it.name == name) { - return it - } - } - debug("Failed to get context: $name") - return null - } - - - /** - * Gets the user"s raw input query. - - * @example - * * val app = DialogflowApp(request = request, response = response) - * * app.tell("You said " + app.getRawInput()) - * * - * * - * @return {String} User"s raw query or null if no value. - * * - * @dialogflow - */ - fun getRawInput(): String? { - debug("getRawInput") - if (request.body.result.resolvedQuery.isEmpty()) { - handleError("No raw input") - return null - } - return request.body.result.resolvedQuery - } - - // --------------------------------------------------------------------------- - // Private Helpers - // --------------------------------------------------------------------------- - - /** - * Uses a PermissionsValueSpec object to construct and send a - * permissions request to the user. - * - * @param {Object} permissionsValueSpec PermissionsValueSpec object containing - * the permissions prefix and permissions requested. - * @return {Object} The HTTP response. - * @private - * @dialogflow - */ - override fun fulfillPermissionsRequest(permissionsSpec: GoogleData.PermissionsRequest, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillPermissionsRequest_: permissionsValueSpec=$permissionsSpec") - val inputPrompt = "PLACEHOLDER_FOR_PERMISSION" - val response = buildResponse(inputPrompt, true) - - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.PERMISSION - } - } - } - } - } - - if (isNotApiVersionOne()) { - response { - body { - data { - google { - systemIntent { - data { - `@type` = INPUT_VALUE_DATA_TYPES.PERMISSION - permissions = permissionsSpec.permissions - optContext = permissionsSpec.optContext - } - } - } - } - } - } - } else { - response { - body { - data { - google { - systemIntent { - spec { - permissionValueSpec = permissionsSpec - } - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Uses TransactionRequirementsCheckValueSpec to construct and send a - * transaction requirements request to Google. - * - * @param {TransactionRequirementsCheckSpec} transactionRequirementsSpec TransactionRequirementsSpec - * object. - * @return {ResponseWrapper} HTTP response. - * @private - * @dialogflow - */ - override fun fulfillTransactionRequirementsCheck(transactionRequirementsCheckSpec: TransactionRequirementsCheckSpec, - dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillTransactionRequirementsCheck_: transactionRequirementsSpec=%s") - val response = buildResponse("PLACEHOLDER_FOR_TXN_REQUIREMENTS", true) - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.TRANSACTION_REQUIREMENTS_CHECK - data { - `@type` = INPUT_VALUE_DATA_TYPES.TRANSACTION_REQ_CHECK - paymentOptions = transactionRequirementsCheckSpec.paymentOptions - orderOptions = transactionRequirementsCheckSpec.orderOptions - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Uses TransactionDecisionValueSpec to construct and send a transaction - * requirements request to Google. - * - * @param {TransactionDecisionValueSpec} transactionDecisionValueSpec TransactionDecisionValueSpec - * object. - * @return {ResponseWrapper>} HTTP response. - * @private - * @dialogflow - */ - override fun fulfillTransactionDecision(transactionDecisionValueSpec: TransactionDecisionValueSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillTransactionDecision_: transactionDecisionValueSpec=$transactionDecisionValueSpec") - val response = buildResponse("PLACEHOLDER_FOR_TXN_DECISION", true) - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.TRANSACTION_DECISION - data { - `@type` = INPUT_VALUE_DATA_TYPES.TRANSACTION_DECISION - paymentOptions = transactionDecisionValueSpec.paymentOptions - orderOptions = transactionDecisionValueSpec.orderOptions - proposedOrder = transactionDecisionValueSpec.proposedOrder - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - - /** - * Uses ConfirmationValueSpec to construct and send a confirmation request to - * Google. - * - * @param {Object} confirmationValueSpec ConfirmationValueSpec object. - * @return {Object} HTTP response. - * @private - * @dialogflow - */ - override fun fulfillConfirmationRequest(confirmationValueSpec: ConfirmationValueSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillConfirmationRequest_: confirmationValueSpec=$confirmationValueSpec") - val response = this.buildResponse("PLACEHOLDER_FOR_CONFIRMATION", true) - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.CONFIRMATION - data { - `@type` = INPUT_VALUE_DATA_TYPES.CONFIRMATION - dialogSpec = confirmationValueSpec.dialogSpec - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Uses DateTimeValueSpec to construct and send a datetime request to Google. - * - * @param {Object} dateTimeValueSpec DateTimeValueSpec object. - * @return {Object} HTTP response. - * @private - * @dialogflow - */ - override fun fulfillDateTimeRequest(confirmationValueSpec: ConfirmationValueSpec, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillDateTimeRequest_: dateTimeValueSpec=$confirmationValueSpec") - val response = buildResponse("PLACEHOLDER_FOR_DATETIME", true) - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.DATETIME - data { - `@type` = INPUT_VALUE_DATA_TYPES.DATETIME - dialogSpec = confirmationValueSpec.dialogSpec - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Constructs and sends a sign in request to Google. - * - * @return {ResponseWrapper>} HTTP response. - * @private - * @dialogflow - */ - override fun fulfillSignInRequest(dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillSignInRequest_") - val response = buildResponse("PLACEHOLDER_FOR_SIGN_IN", true) - response { - body { - data { - google { - systemIntent { - intent = STANDARD_INTENTS.SIGN_IN - data { - `@type` = INPUT_VALUE_DATA_TYPES.SIGN_IN - } - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - - /** - * Builds a response for Dialogflow to send back to the Assistant. - * - * @param {SimpleResponse} textToSpeech TTS/response - * spoken/shown to end user. - * @param {boolean} expectUserResponse true if the user response is expected. - * @param {Array=} noInputs Array of re-prompts when the user does not respond (max 3). - * @return {Object} The final response returned to Assistant. - * @private - * @dialogflow - */ - fun buildResponse(simpleResponse: SimpleResponse, expectUserResponse: Boolean, noInputs: MutableList? = null): ResponseWrapper? { - debug("buildResponse_: simpleResponse=$simpleResponse, expectUserResponse=$expectUserResponse, noInputs=$noInputs") - if (simpleResponse.empty()) { - handleError("Invalid text to speech") - return null - } - return buildResponse(buildRichResponse().addSimpleResponse(simpleResponse), expectUserResponse, noInputs) - } - - /** - * Builds a response for Dialogflow to send back to the Assistant. - * - * @param {string|RichResponse|SimpleResponse} textToSpeech TTS/response - * spoken/shown to end user. - * @param {boolean} expectUserResponse true if the user response is expected. - * @param {Array=} noInputs Array of re-prompts when the user does not respond (max 3). - * @return {Object} The final response returned to Assistant. - * @private - * @dialogflow - */ - fun buildResponse(richResponse: RichResponse, expectUserResponse: Boolean, noInputs: MutableList? = null): ResponseWrapper? { - debug("buildResponse_: textToSpeech=$richResponse, expectUserResponse=$expectUserResponse, noInputs=$noInputs") - if (richResponse.empty()) { - handleError("Invalid text to speech") - return null - } - if (richResponse.items.first().simpleResponse == null) { - handleError("Invalid RichResponse. First item must be SimpleResponse") - return null - } - - var speech = "" - with(richResponse.items.first().simpleResponse) { - if (this?.textToSpeech == null && this?.ssml == null) { - handleError("Invalid RichResponse. Speech must be non null when adding SimpleResponse.") - return null - } - speech = this.textToSpeech ?: this.ssml!! - } - var noInputsFinal = mutableListOf() - val dialogState = mutableMapOf( - "state" to state, //TODO (this.state instanceof State ? this.state.getName() : this.state), - "data" to data) - if (noInputs != null) { - if (noInputs.size > INPUTS_MAX) { - handleError("Invalid number of no inputs") - return null - } - if (isSsml(speech)) { - noInputsFinal.addAll(buildPromptsFromSsmlHelper(noInputs)) - } else { - noInputsFinal.addAll(buildPromptsFromPlainTextHelper(noInputs)) - } - } else { - noInputsFinal = mutableListOf() - } - val response = DialogflowResponse( - speech = speech) - response.data.google = GoogleData( - expectUserResponse = expectUserResponse, - isSsml = isSsml(speech), - richResponse = richResponse, - noInputPrompts = noInputsFinal) - if (expectUserResponse) { - response.contextOut.add( - Context( - name = ACTIONS_DIALOGFLOW_CONTEXT, - lifespan = MAX_LIFESPAN, - parameters = dialogState["data"] as MutableMap?)) - } - response.contextOut = response.contextOut.plus(contexts.values).toMutableList() - this.response.body = response - return this.response - } - - /** - * Builds a response for Dialogflow to send back to the Assistant. - * - * @param {String} textToSpeech TTS/response - * spoken/shown to end user. - * @param {Boolean} expectUserResponse true if the user response is expected. - * @param {Array=} noInputs Array of re-prompts when the user does not respond (max 3). - * @return {Object} The final response returned to Assistant. - * @private - * @dialogflow - */ - fun buildResponse(textToSpeech: String, expectUserResponse: Boolean, noInputs: MutableList? = null): ResponseWrapper? { - debug("buildResponse_: textToSpeech=$textToSpeech, expectUserResponse=$expectUserResponse, noInputs=$noInputs") - if (textToSpeech.isEmpty()) { - handleError("Invalid text to speech") - return null - } - - var noInputsFinal = mutableListOf() - val dialogState = mutableMapOf( - "state" to state, //TODO (this.state instanceof State ? this.state.getName() : this.state), - "data" to data) - if (noInputs != null) { - if (noInputs.size > INPUTS_MAX) { - handleError("Invalid number of no inputs") - return null - } - if (isSsml(textToSpeech)) { - noInputsFinal.addAll(buildPromptsFromSsmlHelper(noInputs)) - } else { - noInputsFinal.addAll(buildPromptsFromPlainTextHelper(noInputs)) - } - } else { - noInputsFinal = mutableListOf() - } - val hasDataForAnotherPlatform = response.body?.data != null - val response = if (hasDataForAnotherPlatform) { - DialogflowResponse( - speech = textToSpeech, - data = response.body?.data!!) - } else { - DialogflowResponse( - speech = textToSpeech) - } - if (!hasDataForAnotherPlatform) { - response.data.google = GoogleData( - expectUserResponse = expectUserResponse, - isSsml = isSsml(textToSpeech), - noInputPrompts = noInputsFinal) - } - if (expectUserResponse) { - response.contextOut.add( - Context( - name = ACTIONS_DIALOGFLOW_CONTEXT, - lifespan = MAX_LIFESPAN, - parameters = dialogState["data"] as MutableMap?)) - } - response.contextOut.addAll(contexts.values) - this.response.body = response - return this.response - } - - /** - * Uses a given intent spec to construct and send a non-TEXT intent response - * to Google. - * - * @param {String} intent Name of the intent to fulfill. One of - * {@link AssistantApp#StandardIntents|StandardIntents}. - * @param {String} specType Type of the related intent spec. One of - * {@link AssistantApp#InputValueDataTypes_|InputValueDataTypes_}. - * @param {NewSurfaceValueSpec} intentSpec Intent Spec object. - * @param {String} promptPlaceholder Some placeholder text for the response - * prompt. Default is "PLACEHOLDER_FOR_INTENT". - * @param {MutableMap?} dialogState JSON object the app uses to hold dialog state that - * will be circulated back by Assistant. - * @return {ResponseWrapper?} HTTP response. - * @private - * @dialogflow - */ - override fun fulfillSystemIntent(intent: String, specType: String, intentSpec: NewSurfaceValueSpec, promptPlaceholder: String?, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillSystemIntent_: intent=$intent, specType=$specType, intentSpec=$intentSpec, " + - "promptPlaceholder=$promptPlaceholder dialogState=$dialogState") - val response = this.buildResponse(promptPlaceholder ?: "PLACEHOLDER_FOR_INTENT", true) - response?.body { - data { - google { - systemIntent { - this.intent = intent - data { - `@type` = specType - context = intentSpec.context - notificationTitle = intentSpec.notificationTitle - capabilities = intentSpec.capabilities - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - override fun fulfillRegisterUpdateIntent(intent: String, specType: String, intentSpec: RegisterUpdateValueSpec, promptPlaceholder: String?, dialogState: MutableMap?): ResponseWrapper? { - debug("fulfillSystemIntent_: intent=$intent, specType=$specType, intentSpec=$intentSpec, " + - "promptPlaceholder=$promptPlaceholder dialogState=$dialogState") - val response = this.buildResponse(promptPlaceholder ?: "PLACEHOLDER_FOR_INTENT", true) - response?.body { - data { - google { - systemIntent { - this.intent = intent - data { - `@type` = specType - triggerContext = intentSpec.triggerContext - arguments = intentSpec.arguments - } - } - } - } - } - return doResponse(response, RESPONSE_CODE_OK) - } - - /** - * Extract the session data from the incoming JSON request. - * - */ - override fun extractData() { - debug("extractData") - data = request.body.result.contexts.find { it.name == ACTIONS_DIALOGFLOW_CONTEXT }?.parameters ?: mutableMapOf() - } - - /** - * SPECIFIC TO KOTLIN SDK - * Allows adding data for other platforms, such as Facebook messenger, Slack, etc. - */ - fun data(init: Data.() -> Unit) { - if (response.body == null) { - response.body = DialogflowResponse() - } - if (response.body?.data == null) { - response.body?.data = Data() - } - response.body?.data?.init() - } -} diff --git a/sdk/src/main/java/com/tmsdurham/actions/DialogflowRequest.kt b/sdk/src/main/java/com/tmsdurham/actions/DialogflowRequest.kt deleted file mode 100644 index 997fc12..0000000 --- a/sdk/src/main/java/com/tmsdurham/actions/DialogflowRequest.kt +++ /dev/null @@ -1,183 +0,0 @@ -package com.tmsdurham.dialogflow - -import com.tmsdurham.dialogflow.google.GoogleData -import com.tmsdurham.actions.* -import com.tmsdurham.actions.actions.ActionRequest -import com.tmsdurham.actions.actions.Sender - -fun dialogflowRequest(init: DialogflowRequest.() -> Unit): DialogflowRequest { - val request = DialogflowRequest() - request.init() - return request -} - -data class DialogflowRequest( - var id: String? = null, - val timestamp: String? = null, - val lang: String? = null, - var result: Result = Result(), - var data: Data = Data(), - val status: Status? = null, - val sessionId: String? = null, - var originalRequest: OriginalRequest? = null) { - - inline fun result(f: Result.() -> Unit) = result.f() - - fun originalRequest(init: OriginalRequest.() -> Unit) { - originalRequest = OriginalRequest() - originalRequest!!.init() - } -} - -data class Metadata( - val intentId: String? = null, - val webhookUsed: String? = null, - val webhookForSlotFillingUsed: String? = null, - val intentName: String? = null) - -/** - * Messages from Dialogflow, such as Cards, simple response, etc, that are added in the console. - */ -data class Messages( - var type: String = "", - var items: MutableList? = null, - var speech: String? = null, - var textToSpeech: String? = null, - var displayText: String? = null, - var suggestions: MutableList? = null, - var destinationName: String? = null, - var url: String? = null, - var title: String? = null, - var subtitle: String? = null, - var formattedText: String? = null, - var image: Image? = null, - var buttons: MutableList