diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock new file mode 100644 index 00000000000..46b869e5960 --- /dev/null +++ b/packages/auth/demo/functions/yarn.lock @@ -0,0 +1,2703 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@firebase/app-types@0.1.2": + version "0.1.2" + resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.1.2.tgz#a20cb346e3be374c0bdee6b102de0ea5e8e6fa27" + +"@firebase/app@^0.1.10": + version "0.1.10" + resolved "https://registry.npmjs.org/@firebase/app/-/app-0.1.10.tgz#fc80c62dbe4d601cad1495bc095309adb9074f85" + dependencies: + "@firebase/app-types" "0.1.2" + "@firebase/util" "0.1.10" + tslib "^1.9.0" + +"@firebase/database-types@0.2.1": + version "0.2.1" + resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.2.1.tgz#f83a6d03af5f8c93276ceb89e1f31e4664c9df1b" + +"@firebase/database@^0.2.0": + version "0.2.2" + resolved "https://registry.npmjs.org/@firebase/database/-/database-0.2.2.tgz#a8a0709644d7f281b400e983c71c8c65fba90c70" + dependencies: + "@firebase/database-types" "0.2.1" + "@firebase/logger" "0.1.1" + "@firebase/util" "0.1.11" + faye-websocket "0.11.1" + tslib "1.9.0" + +"@firebase/logger@0.1.1": + version "0.1.1" + resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.1.tgz#af5df54253286993f4b367c3dabe569c848860d3" + +"@firebase/util@0.1.10": + version "0.1.10" + resolved "https://registry.npmjs.org/@firebase/util/-/util-0.1.10.tgz#7898f6e36c8231c287c4024c313000df677b1363" + dependencies: + tslib "^1.9.0" + +"@firebase/util@0.1.11": + version "0.1.11" + resolved "https://registry.npmjs.org/@firebase/util/-/util-0.1.11.tgz#9990dff53930aa9fcae31494ebe8de5c5b8e815c" + dependencies: + tslib "1.9.0" + +"@google-cloud/common-grpc@^0.6.0": + version "0.6.1" + resolved "https://registry.npmjs.org/@google-cloud/common-grpc/-/common-grpc-0.6.1.tgz#629dfb90690f6a38263bbf16eb9740ea4cbcf9df" + dependencies: + "@google-cloud/common" "^0.17.0" + dot-prop "^4.2.0" + duplexify "^3.5.1" + extend "^3.0.1" + grpc "^1.10.0" + is "^3.2.0" + modelo "^4.2.0" + retry-request "^3.3.1" + through2 "^2.0.3" + +"@google-cloud/common@^0.17.0": + version "0.17.0" + resolved "https://registry.npmjs.org/@google-cloud/common/-/common-0.17.0.tgz#8ef558750db481fc10a13757a49479ab9a1c8c07" + dependencies: + array-uniq "^1.0.3" + arrify "^1.0.1" + concat-stream "^1.6.0" + create-error-class "^3.0.2" + duplexify "^3.5.0" + ent "^2.2.0" + extend "^3.0.1" + google-auto-auth "^0.10.0" + is "^3.2.0" + log-driver "1.2.7" + methmeth "^1.1.0" + modelo "^4.2.0" + request "^2.79.0" + retry-request "^3.0.0" + split-array-stream "^1.0.0" + stream-events "^1.0.1" + string-format-obj "^1.1.0" + through2 "^2.0.3" + +"@google-cloud/firestore@^0.13.1": + version "0.13.1" + resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-0.13.1.tgz#40e376852d9aa19aee62deb0334ffc437ebd8d64" + dependencies: + "@google-cloud/common" "^0.17.0" + "@google-cloud/common-grpc" "^0.6.0" + bun "^0.0.12" + deep-equal "^1.0.1" + extend "^3.0.1" + functional-red-black-tree "^1.0.1" + google-gax "^0.16.0" + is "^3.2.1" + safe-buffer "^5.1.1" + through2 "^2.0.3" + +"@google-cloud/storage@^1.6.0": + version "1.7.0" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.7.0.tgz#07bff573d92d5c294db6a04af246688875a8f74b" + dependencies: + "@google-cloud/common" "^0.17.0" + arrify "^1.0.0" + async "^2.0.1" + compressible "^2.0.12" + concat-stream "^1.5.0" + create-error-class "^3.0.2" + duplexify "^3.5.0" + extend "^3.0.0" + gcs-resumable-upload "^0.10.2" + hash-stream-validation "^0.2.1" + is "^3.0.1" + mime "^2.2.0" + mime-types "^2.0.8" + once "^1.3.1" + pumpify "^1.5.1" + request "^2.85.0" + safe-buffer "^5.1.1" + snakeize "^0.1.0" + stream-events "^1.0.1" + through2 "^2.0.0" + xdg-basedir "^3.0.0" + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.stat@^1.0.1": + version "1.1.0" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a" + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + +"@types/body-parser@*": + version "1.17.0" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/caseless@*": + version "0.12.1" + resolved "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" + +"@types/connect@*": + version "3.4.32" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" + dependencies: + "@types/node" "*" + +"@types/cors@^2.8.1": + version "2.8.4" + resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.4.tgz#50991a759a29c0b89492751008c6af7a7c8267b0" + dependencies: + "@types/express" "*" + +"@types/events@*": + version "1.2.0" + resolved "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" + +"@types/express-serve-static-core@*": + version "4.16.0" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7" + dependencies: + "@types/events" "*" + "@types/node" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.11.1": + version "4.16.0" + resolved "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19" + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + +"@types/form-data@*": + version "2.2.1" + resolved "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" + dependencies: + "@types/node" "*" + +"@types/google-cloud__storage@^1.1.7": + version "1.7.0" + resolved "https://registry.npmjs.org/@types/google-cloud__storage/-/google-cloud__storage-1.7.0.tgz#60abb5669f78ed07abb625f556d1f396ee84724e" + dependencies: + "@types/node" "*" + "@types/request" "*" + +"@types/jsonwebtoken@^7.1.32": + version "7.2.8" + resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz#8d199dab4ddb5bba3234f8311b804d2027af2b3a" + dependencies: + "@types/node" "*" + +"@types/lodash@^4.14.34": + version "4.14.115" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.115.tgz#54d171b2ce12c058742443b5f6754760f701b8f9" + +"@types/long@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz#719551d2352d301ac8b81db732acb6bdc28dbdef" + +"@types/mime@*": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b" + +"@types/node@*", "@types/node@^10.1.0": + version "10.5.5" + resolved "https://registry.npmjs.org/@types/node/-/node-10.5.5.tgz#8e84d24e896cd77b0d4f73df274027e3149ec2ba" + +"@types/node@^8.0.53": + version "8.10.23" + resolved "https://registry.npmjs.org/@types/node/-/node-8.10.23.tgz#e5ccfdafff42af5397c29669b6d7d65f7d629a00" + +"@types/range-parser@*": + version "1.2.2" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d" + +"@types/request@*": + version "2.47.1" + resolved "https://registry.npmjs.org/@types/request/-/request-2.47.1.tgz#25410d3afbdac04c91a94ad9efc9824100735824" + dependencies: + "@types/caseless" "*" + "@types/form-data" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + +"@types/serve-static@*": + version "1.13.2" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48" + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + +"@types/tough-cookie@*": + version "2.3.3" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz#7f226d67d654ec9070e755f46daebf014628e9d9" + +abbrev@1: + version "1.1.1" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + dependencies: + mime-types "~2.1.18" + negotiator "0.6.1" + +acorn-es7-plugin@^1.0.12: + version "1.1.7" + resolved "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b" + +acorn@^5.0.0: + version "5.7.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +ascli@~1: + version "1.0.1" + resolved "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz#bcfa5974a62f18e81cabaeb49732ab4a88f906bc" + dependencies: + colour "~0.7.1" + optjs "~3.2.2" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + +async@^2.0.1, async@^2.3.0, async@^2.4.0: + version "2.6.1" + resolved "https://registry.npmjs.org/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + dependencies: + lodash "^4.17.10" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +axios@^0.18.0: + version "0.18.0" + resolved "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" + dependencies: + follow-redirects "^1.3.0" + is-buffer "^1.1.5" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +body-parser@1.18.2: + version "1.18.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.1" + http-errors "~1.6.2" + iconv-lite "0.4.19" + on-finished "~2.3.0" + qs "6.5.1" + raw-body "2.3.2" + type-is "~1.6.15" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + +bun@^0.0.12: + version "0.0.12" + resolved "https://registry.npmjs.org/bun/-/bun-0.0.12.tgz#d54fae69f895557f275423bc14b404030b20a5fc" + dependencies: + readable-stream "~1.0.32" + +bytebuffer@~5: + version "5.0.1" + resolved "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd" + dependencies: + long "~3" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + +call-signature@0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996" + +camelcase@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^3.0.3: + version "3.2.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +colour@~0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" + +combined-stream@1.0.6, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +compressible@^2.0.12: + version "2.0.14" + resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7" + dependencies: + mime-db ">= 1.34.0 < 2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.5.0, concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +configstore@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + +core-js@^2.0.0: + version "2.5.7" + resolved "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cors@^2.8.4: + version "2.8.4" + resolved "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" + dependencies: + object-assign "^4" + vary "^1" + +create-error-class@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +deep-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + +depd@~1.1.1, depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +diff-match-patch@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.1.tgz#d5f880213d82fbc124d2b95111fb3c033dbad7fa" + +dir-glob@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" + dependencies: + arrify "^1.0.1" + path-type "^3.0.0" + +dot-prop@^4.1.0, dot-prop@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + +duplexify@^3.5.0, duplexify@^3.5.1, duplexify@^3.5.4, duplexify@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ecdsa-sig-formatter@1.0.10: + version "1.0.10" + resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz#1c595000f04a8897dfb85000892a0f4c33af86c3" + dependencies: + safe-buffer "^5.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +empower-core@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/empower-core/-/empower-core-1.2.0.tgz#ce3fb2484d5187fa29c23fba8344b0b2fdf5601c" + dependencies: + call-signature "0.0.2" + core-js "^2.0.0" + +empower@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/empower/-/empower-1.3.0.tgz#6b05e77625e77dc44945c4328562c3020b01fa4b" + dependencies: + core-js "^2.0.0" + empower-core "^1.2.0" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" + +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +espurify@^1.6.0: + version "1.8.1" + resolved "https://registry.npmjs.org/espurify/-/espurify-1.8.1.tgz#5746c6c1ab42d302de10bd1d5bf7f0e8c0515056" + dependencies: + core-js "^2.0.0" + +estraverse@^4.1.0, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +express@^4.16.2: + version "4.16.3" + resolved "https://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.2" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.3" + qs "6.5.1" + range-parser "~1.2.0" + safe-buffer "5.1.1" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@^3.0.0, extend@^3.0.1, extend@~3.0.1: + version "3.0.2" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-glob@^2.0.2: + version "2.2.2" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.0.1" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.1" + micromatch "^3.1.10" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +faye-websocket@0.11.1: + version "0.11.1" + resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38" + dependencies: + websocket-driver ">=0.5.1" + +faye-websocket@0.9.3: + version "0.9.3" + resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz#482a505b0df0ae626b969866d3bd740cdb962e83" + dependencies: + websocket-driver ">=0.5.1" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.4.0" + unpipe "~1.0.0" + +firebase-admin@5.12.0: + version "5.12.0" + resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-5.12.0.tgz#3291b0466b4d161cb4135e83c97f9878e7768cac" + dependencies: + "@firebase/app" "^0.1.10" + "@firebase/database" "^0.2.0" + "@google-cloud/firestore" "^0.13.1" + "@google-cloud/storage" "^1.6.0" + "@types/google-cloud__storage" "^1.1.7" + "@types/node" "^8.0.53" + faye-websocket "0.9.3" + jsonwebtoken "8.1.0" + node-forge "0.7.4" + +firebase-functions@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-1.0.1.tgz#13160e957d48135fc95c04b40f7fc24f6ebed565" + dependencies: + "@types/cors" "^2.8.1" + "@types/express" "^4.11.1" + "@types/jsonwebtoken" "^7.1.32" + "@types/lodash" "^4.14.34" + cors "^2.8.4" + express "^4.16.2" + jsonwebtoken "^7.1.9" + lodash "^4.6.1" + +follow-redirects@^1.3.0: + version "1.5.1" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz#67a8f14f5a1f67f962c2c46469c79eaec0a90291" + dependencies: + debug "^3.1.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gcp-metadata@^0.6.1, gcp-metadata@^0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.6.3.tgz#4550c08859c528b370459bd77a7187ea0bdbc4ab" + dependencies: + axios "^0.18.0" + extend "^3.0.1" + retry-axios "0.3.2" + +gcs-resumable-upload@^0.10.2: + version "0.10.2" + resolved "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.10.2.tgz#7f29b3ee23dcec4170367c0711418249c660545f" + dependencies: + configstore "^3.1.2" + google-auto-auth "^0.10.0" + pumpify "^1.4.0" + request "^2.85.0" + stream-events "^1.0.3" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + +glob@^7.0.5, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + +globby@^8.0.0: + version "8.0.1" + resolved "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + fast-glob "^2.0.2" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + +google-auth-library@^1.3.1: + version "1.6.1" + resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-1.6.1.tgz#9c73d831ad720c0c3048ab89d0ffdec714d07dd2" + dependencies: + axios "^0.18.0" + gcp-metadata "^0.6.3" + gtoken "^2.3.0" + jws "^3.1.5" + lodash.isstring "^4.0.1" + lru-cache "^4.1.3" + retry-axios "^0.3.2" + +google-auto-auth@^0.10.0: + version "0.10.1" + resolved "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.10.1.tgz#68834a6f3da59a6cb27fce56f76e3d99ee49d0a2" + dependencies: + async "^2.3.0" + gcp-metadata "^0.6.1" + google-auth-library "^1.3.1" + request "^2.79.0" + +google-gax@^0.16.0: + version "0.16.1" + resolved "https://registry.npmjs.org/google-gax/-/google-gax-0.16.1.tgz#30bf1284a1c384cd31a01163def4d671cec10c0f" + dependencies: + duplexify "^3.5.4" + extend "^3.0.0" + globby "^8.0.0" + google-auto-auth "^0.10.0" + google-proto-files "^0.15.0" + grpc "^1.10.0" + is-stream-ended "^0.1.0" + lodash "^4.17.2" + protobufjs "^6.8.0" + through2 "^2.0.3" + +google-p12-pem@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.2.tgz#c8a3843504012283a0dbffc7430b7c753ecd4b07" + dependencies: + node-forge "^0.7.4" + pify "^3.0.0" + +google-proto-files@^0.15.0: + version "0.15.1" + resolved "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.15.1.tgz#5c9c485e574e2c100fe829a5ec0bbb3d9bc789a2" + dependencies: + globby "^7.1.1" + power-assert "^1.4.4" + protobufjs "^6.8.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +grpc@^1.10.0: + version "1.13.1" + resolved "https://registry.npmjs.org/grpc/-/grpc-1.13.1.tgz#9b5c49d4e56309b6e3bd631f8948b7b298d88790" + dependencies: + lodash "^4.17.5" + nan "^2.0.0" + node-pre-gyp "^0.10.0" + protobufjs "^5.0.3" + +gtoken@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/gtoken/-/gtoken-2.3.0.tgz#4e0ffc16432d7041a1b3dbc1d97aac17a5dc964a" + dependencies: + axios "^0.18.0" + google-p12-pem "^1.0.0" + jws "^3.1.4" + mime "^2.2.0" + pify "^3.0.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +hash-stream-validation@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz#ecc9b997b218be5bb31298628bb807869b73dcd1" + dependencies: + through2 "^2.0.0" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +http-errors@1.6.2: + version "1.6.2" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.4.0: + version "0.4.13" + resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz#3bd6d6fde6e3172c9334c3b33b6c193d80fe1137" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@0.4.19: + version "0.4.19" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +iconv-lite@^0.4.4: + version "0.4.23" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + +ignore@^3.3.5: + version "3.3.10" + resolved "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ipaddr.js@1.8.0: + version "1.8.0" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-stream-ended@^0.1.0: + version "0.1.4" + resolved "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + +is@^3.0.1, is@^3.2.0, is@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isemail@1.x.x: + version "1.2.0" + resolved "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +joi@^6.10.1: + version "6.10.1" + resolved "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" + dependencies: + hoek "2.x.x" + isemail "1.x.x" + moment "2.x.x" + topo "1.x.x" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonwebtoken@8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz#c6397cd2e5fd583d65c007a83dc7bb78e6982b83" + dependencies: + jws "^3.1.4" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.0.0" + xtend "^4.0.1" + +jsonwebtoken@^7.1.9: + version "7.4.3" + resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638" + dependencies: + joi "^6.10.1" + jws "^3.1.4" + lodash.once "^4.0.0" + ms "^2.0.0" + xtend "^4.0.1" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jwa@^1.1.5: + version "1.1.6" + resolved "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz#87240e76c9808dbde18783cf2264ef4929ee50e6" + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.10" + safe-buffer "^5.0.1" + +jws@^3.1.4, jws@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz#80d12d05b293d1e841e7cb8b4e69e561adcf834f" + dependencies: + jwa "^1.1.5" + safe-buffer "^5.0.1" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + +lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.5, lodash@^4.6.1: + version "4.17.10" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +log-driver@1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + +long@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + +long@~3: + version "3.2.0" + resolved "https://registry.npmjs.org/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" + +lru-cache@^4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + dependencies: + pify "^3.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +merge2@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" + +methmeth@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/methmeth/-/methmeth-1.1.0.tgz#e80a26618e52f5c4222861bb748510bd10e29089" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +"mime-db@>= 1.34.0 < 2", mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18: + version "2.1.19" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + dependencies: + mime-db "~1.35.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + +mime@^2.2.0: + version "2.3.1" + resolved "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +modelo@^4.2.0: + version "4.2.3" + resolved "https://registry.npmjs.org/modelo/-/modelo-4.2.3.tgz#b278588a4db87fc1e5107ae3a277c0876f38d894" + +moment@2.x.x: + version "2.22.2" + resolved "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +ms@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + +nan@^2.0.0: + version "2.10.0" + resolved "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +node-forge@0.7.4: + version "0.7.4" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.7.4.tgz#8e6e9f563a1e32213aa7508cded22aa791dbf986" + +node-forge@^0.7.4: + version "0.7.5" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.11" + resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.0, object-keys@^1.0.8: + version "1.0.12" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optjs@~3.2.2: + version "3.2.2" + resolved "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + dependencies: + pify "^3.0.0" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +power-assert-context-formatter@^1.0.7: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.2.0.tgz#8fbe72692288ec5a7203cdf215c8b838a6061d2a" + dependencies: + core-js "^2.0.0" + power-assert-context-traversal "^1.2.0" + +power-assert-context-reducer-ast@^1.0.7: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.2.0.tgz#c7ca1c9e39a6fb717f7ac5fe9e76e192bf525df3" + dependencies: + acorn "^5.0.0" + acorn-es7-plugin "^1.0.12" + core-js "^2.0.0" + espurify "^1.6.0" + estraverse "^4.2.0" + +power-assert-context-traversal@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.2.0.tgz#f6e71454baf640de5c1c9c270349f5c9ab0b2e94" + dependencies: + core-js "^2.0.0" + estraverse "^4.1.0" + +power-assert-formatter@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz#5dc125ed50a3dfb1dda26c19347f3bf58ec2884a" + dependencies: + core-js "^2.0.0" + power-assert-context-formatter "^1.0.7" + power-assert-context-reducer-ast "^1.0.7" + power-assert-renderer-assertion "^1.0.7" + power-assert-renderer-comparison "^1.0.7" + power-assert-renderer-diagram "^1.0.7" + power-assert-renderer-file "^1.0.7" + +power-assert-renderer-assertion@^1.0.7: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.2.0.tgz#3db6ffcda106b37bc1e06432ad0d748a682b147a" + dependencies: + power-assert-renderer-base "^1.1.1" + power-assert-util-string-width "^1.2.0" + +power-assert-renderer-base@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz#96a650c6fd05ee1bc1f66b54ad61442c8b3f63eb" + +power-assert-renderer-comparison@^1.0.7: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.2.0.tgz#e4f88113225a69be8aa586ead05aef99462c0495" + dependencies: + core-js "^2.0.0" + diff-match-patch "^1.0.0" + power-assert-renderer-base "^1.1.1" + stringifier "^1.3.0" + type-name "^2.0.1" + +power-assert-renderer-diagram@^1.0.7: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.2.0.tgz#37f66e8542e5677c5b58e6d72b01c0d9a30e2219" + dependencies: + core-js "^2.0.0" + power-assert-renderer-base "^1.1.1" + power-assert-util-string-width "^1.2.0" + stringifier "^1.3.0" + +power-assert-renderer-file@^1.0.7: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.2.0.tgz#3f4bebd9e1455d75cf2ac541e7bb515a87d4ce4b" + dependencies: + power-assert-renderer-base "^1.1.1" + +power-assert-util-string-width@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.2.0.tgz#6e06d5e3581bb876c5d377c53109fffa95bd91a0" + dependencies: + eastasianwidth "^0.2.0" + +power-assert@^1.4.4: + version "1.6.0" + resolved "https://registry.npmjs.org/power-assert/-/power-assert-1.6.0.tgz#3a9d2b943cf0d6fc6a623766869c4460838c05fb" + dependencies: + define-properties "^1.1.2" + empower "^1.3.0" + power-assert-formatter "^1.4.1" + universal-deep-strict-equal "^1.2.1" + xtend "^4.0.0" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +protobufjs@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz#e4dfe9fb67c90b2630d15868249bcc4961467a17" + dependencies: + ascli "~1" + bytebuffer "~5" + glob "^7.0.5" + yargs "^3.10.0" + +protobufjs@^6.8.0: + version "6.8.8" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c" + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.0" + "@types/node" "^10.1.0" + long "^4.0.0" + +proxy-addr@~2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.8.0" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.4.0, pumpify@^1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@6.5.1: + version "6.5.1" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +raw-body@2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.19" + unpipe "1.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + 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" + +readable-stream@~1.0.32: + version "1.0.34" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +request@^2.79.0, request@^2.81.0, request@^2.85.0: + version "2.87.0" + resolved "https://registry.npmjs.org/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + +retry-axios@0.3.2, retry-axios@^0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz#5757c80f585b4cc4c4986aa2ffd47a60c6d35e13" + +retry-request@^3.0.0, retry-request@^3.3.1: + version "3.3.2" + resolved "https://registry.npmjs.org/retry-request/-/retry-request-3.3.2.tgz#fd8e0079e7b0dfc7056e500b6f089437db0da4df" + dependencies: + request "^2.81.0" + through2 "^2.0.0" + +rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +safe-buffer@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +semver@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +send@0.16.2: + version "0.16.2" + resolved "https://registry.npmjs.org/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +snakeize@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +split-array-stream@^1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/split-array-stream/-/split-array-stream-1.0.3.tgz#d2b75a8e5e0d824d52fdec8b8225839dc2e35dfa" + dependencies: + async "^2.4.0" + is-stream-ended "^0.1.0" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +stream-events@^1.0.1, stream-events@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/stream-events/-/stream-events-1.0.4.tgz#73bfd4007b8f677b46ec699f14e9e2304c2f0a9e" + dependencies: + stubs "^3.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + +string-format-obj@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/string-format-obj/-/string-format-obj-1.1.1.tgz#c7612ca4e2ad923812a81db192dc291850aa1f65" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +stringifier@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz#def18342f6933db0f2dbfc9aa02175b448c17959" + dependencies: + core-js "^2.0.0" + traverse "^0.6.6" + type-name "^2.0.1" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + +tar@^4: + version "4.4.4" + resolved "https://registry.npmjs.org/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +through2@^2.0.0, through2@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +topo@1.x.x: + version "1.1.0" + resolved "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" + dependencies: + hoek "2.x.x" + +tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +traverse@^0.6.6: + version "0.6.6" + resolved "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + +tslib@1.9.0: + version "1.9.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" + +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-is@~1.6.15, type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.18" + +type-name@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz#efe7d4123d8ac52afff7f40c7e4dec5266008fb4" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + +universal-deep-strict-equal@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz#0da4ac2f73cff7924c81fa4de018ca562ca2b0a7" + dependencies: + array-filter "^1.0.0" + indexof "0.0.1" + object-keys "^1.0.0" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + +uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +websocket-driver@>=0.5.1: + version "0.7.0" + resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" + dependencies: + http-parser-js ">=0.4.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.3" + resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + dependencies: + string-width "^1.0.2 || 2" + +window-size@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.0: + version "3.2.1" + resolved "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + +yargs@^3.10.0: + version "3.32.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" + dependencies: + camelcase "^2.0.1" + cliui "^3.0.3" + decamelize "^1.1.1" + os-locale "^1.4.0" + string-width "^1.0.1" + window-size "^0.1.4" + y18n "^3.2.0" diff --git a/packages/auth/demo/public/web-worker.js b/packages/auth/demo/public/web-worker.js index 442e3bd774e..37cce8d48ec 100644 --- a/packages/auth/demo/public/web-worker.js +++ b/packages/auth/demo/public/web-worker.js @@ -77,11 +77,11 @@ var runWorkerTests = function(googleIdToken) { firebase.auth().useDeviceLanguage(); return firebase.auth().signInAnonymously(); }) - .then(function(user) { - if (!user.uid) { + .then(function(result) { + if (!result.user.uid) { throw new Error('signInAnonymously unexpectedly failed!'); } - return user.updateProfile({displayName: expectedDisplayName}); + return result.user.updateProfile({displayName: expectedDisplayName}); }) .then(function() { if (firebase.auth().currentUser.displayName != expectedDisplayName) { @@ -95,8 +95,8 @@ var runWorkerTests = function(googleIdToken) { } return firebase.auth().createUserWithEmailAndPassword(email, pass); }) - .then(function(user) { - if (user.email != email) { + .then(function(result) { + if (result.user.email != email) { throw new Error( 'createUserWithEmailAndPassword unexpectedly failed!'); } @@ -107,11 +107,11 @@ var runWorkerTests = function(googleIdToken) { } return firebase.auth().signInWithEmailAndPassword(email, pass); }) - .then(function(user) { - if (user.email != email) { + .then(function(result) { + if (result.user.email != email) { throw new Error('signInWithEmailAndPassword unexpectedly failed!'); } - return user.delete(); + return result.user.delete(); }) .then(function() { return firebase.auth().signInWithPopup(provider) diff --git a/packages/auth/src/messagechannel/defines.js b/packages/auth/src/messagechannel/defines.js new file mode 100644 index 00000000000..f53da4f7f8d --- /dev/null +++ b/packages/auth/src/messagechannel/defines.js @@ -0,0 +1,81 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Defines the MessageChannel common utilities and enums. + */ + +goog.provide('fireauth.messagechannel.Error'); +goog.provide('fireauth.messagechannel.Status'); +goog.provide('fireauth.messagechannel.TimeoutDuration'); +goog.provide('fireauth.messagechannel.utils'); + + +/** + * Enum for the messagechannel error messages. These errors are not meant to be + * user facing. + * @enum {string} + */ +fireauth.messagechannel.Error = { + CONNECTION_UNAVAILABLE: 'connection_unavailable', + INVALID_RESPONSE: 'invalid_response', + TIMEOUT: 'timeout', + UNKNOWN: 'unknown_error', + UNSUPPORTED_EVENT: 'unsupported_event' +}; + + +/** + * Enum for the message channel request status labels. + * @enum {string} + */ +fireauth.messagechannel.Status = { + ACK: 'ack', + DONE: 'done' +}; + + +/** + * Enum for the timeout durations in milliseconds for different contexts. + * @enum {number} + */ +fireauth.messagechannel.TimeoutDuration = { + ACK: 20, + COMPLETION: 500 +}; + + +/** + * @param {?string=} opt_prefix An optional prefix string to prepend to ID. + * @param {?number=} opt_digits An optional number of digits used for event ID. + * @return {string} The generated event ID used to identify a generic event. + */ +fireauth.messagechannel.utils.generateEventId = + function(opt_prefix, opt_digits) { + // 0, null and undefined will default to 20. + var digits = opt_digits || 20; + return opt_prefix ? opt_prefix : '' + + Math.floor(Math.random() * Math.pow(10, digits)).toString(); +}; + + +/** + * @return {?MessageChannel} The initialized MessageChannel instance if + * supported. + */ +fireauth.messagechannel.utils.initializeMessageChannel = function() { + return typeof MessageChannel !== 'undefined' ? new MessageChannel() : null; +}; diff --git a/packages/auth/src/messagechannel/postmessager.js b/packages/auth/src/messagechannel/postmessager.js new file mode 100644 index 00000000000..ee21caffe1b --- /dev/null +++ b/packages/auth/src/messagechannel/postmessager.js @@ -0,0 +1,130 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Defines the PostMessager interface needed for the + * `fireauth.messagechannel.Sender`, in addition to 2 types of implementations. + */ + +goog.provide('fireauth.messagechannel.PostMessager'); +goog.provide('fireauth.messagechannel.WindowPostMessager'); +goog.provide('fireauth.messagechannel.WorkerClientPostMessager'); + + +/** + * This is the interface defining the postMessage format of a window which + * takes an additional second parameter for target origin. + * + * @typedef {{ + * postMessage: function(*, string, !Array) + * }} + */ +fireauth.messagechannel.Window; + + +/** + * This is the interface defining the postMessage format of a worker or + * ServiceWorkerClient, etc. which just takes a message and a list of + * Transferables. + * + * @typedef {{ + * postMessage: function(*, !Array) + * }} + */ +fireauth.messagechannel.WorkerClient; + + +/** + * Defines a common interface to postMessage data to a specified PostMessager. + * @interface + */ +fireauth.messagechannel.PostMessager = function() {}; + + +/** + * Sends a message to the specified context. + * @param {*} message The message to send. + * @param {!Array} transfer The list of `Transferable` objects + * that are transferred with the message. The ownsership fo these objects is + * given to the destination side and they are no longer usable on the + * sending side. + */ +fireauth.messagechannel.PostMessager.prototype.postMessage = + function(message, transfer) {}; + + + +/** + * Defines the implementation for postMessaging to a window context. + * @param {!fireauth.messagechannel.Window} win The window PostMessager. + * @param {?string=} opt_targetOrigin The target origin. + * @constructor + * @implements {fireauth.messagechannel.PostMessager} + */ +fireauth.messagechannel.WindowPostMessager = function(win, opt_targetOrigin) { + /** + * @const @private {!fireauth.messagechannel.Window} The window PostMessager. + */ + this.win_ = win; + /** @const @private {string} The postMessage target origin. */ + this.targetOrigin_ = opt_targetOrigin || '*'; +}; + + +/** + * Sends a message to the specified window context. + * @param {*} message The message to send. + * @param {!Array} transfer The list of `Transferable` objects + * that are transferred with the message. The ownsership fo these objects is + * given to the destination side and they are no longer usable on the + * sending side. + * @override + */ +fireauth.messagechannel.WindowPostMessager.prototype.postMessage = + function(message, transfer) { + this.win_.postMessage(message, this.targetOrigin_, transfer); +}; + + +/** + * Defines the implementation for postMessaging to a worker/client context. + * @param {!fireauth.messagechannel.WorkerClient} worker The worker/client + * PostMessager. + * @constructor + * @implements {fireauth.messagechannel.PostMessager} + */ +fireauth.messagechannel.WorkerClientPostMessager = function(worker) { + /** + * @const @private {!fireauth.messagechannel.WorkerClient} The worker/client + * PostMessager. + */ + this.worker_ = worker; +}; + + +/** + * Sends a message to the specified worker/client context. + * @param {*} message The message to send. + * @param {!Array} transfer The list of `Transferable` objects + * that are transferred with the message. The ownsership fo these objects is + * given to the destination side and they are no longer usable on the + * sending side. + * @override + */ +fireauth.messagechannel.WorkerClientPostMessager.prototype.postMessage = + function(message, transfer) { + this.worker_.postMessage(message, transfer); +}; diff --git a/packages/auth/src/messagechannel/receiver.js b/packages/auth/src/messagechannel/receiver.js new file mode 100644 index 00000000000..97a7837002d --- /dev/null +++ b/packages/auth/src/messagechannel/receiver.js @@ -0,0 +1,222 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Defines the MessageChannel based wrapper for receiving + * messages from other windows or workers. + */ + +goog.provide('fireauth.messagechannel.Receiver'); + +goog.require('fireauth.messagechannel.Status'); +goog.require('goog.Promise'); +goog.require('goog.array'); +goog.require('goog.object'); + + +/** + * Initializes a channel to receive specific messages from a specified event + * target. + * Note receivers should not be manually instantiated. Instead `getInstance()` + * should be used instead to get a receiver instance for a specified event + * target. + * @param {!EventTarget} eventTarget The event target to listen to. + * @constructor + */ +fireauth.messagechannel.Receiver = function(eventTarget) { + /** + * @const @private {!EventTarget} The messageChannel event target. + */ + this.eventTarget_ = eventTarget; + /** + * @const @private {!Object.|void>>} + * This is the event type to handlers hash map. It is used to hold the + * corresponding handlers for specified events. + */ + this.eventHandlers_ = {}; + /** + * @const@private {function(!Event)} The internal 'message' event handler used + * to reroute the request to corresponding subscribed handlers. + */ + this.messageEventHandler_ = goog.bind(this.handleEvent_, this); +}; + + +/** + * @param {!EventTarget} eventTarget The event target to check for. + * @return {boolean} Whether the receiver is listening to the specified event + * target. + */ +fireauth.messagechannel.Receiver.prototype.isListeningTo = + function(eventTarget) { + return this.eventTarget_ == eventTarget; +}; + + +/** + * @const @private {!Array} The list of all + * created `fireauth.messagechannel.Receiver` instances. + */ +fireauth.messagechannel.Receiver.receivers_ = []; + + +/** + * Return a receiver instance for the specified event target. This is needed + * since one instance can be available per event target. Otherwise receivers + * could clobber each other. + * @param {!EventTarget} eventTarget The event target to listen to. + * @return {!fireauth.messagechannel.Receiver} The receiver instance for the + * specified event target. + */ +fireauth.messagechannel.Receiver.getInstance = function(eventTarget) { + // The results are stored in an array since objects can't be keys for other + // objects. In addition, setting a unique property on an event target as a + // hash map key may not be allowed due to CORS restrictions. + var instance; + goog.array.forEach( + fireauth.messagechannel.Receiver.receivers_, + function(receiver) { + if (receiver.isListeningTo(eventTarget)) { + instance = receiver; + } + }); + if (!instance) { + instance = new fireauth.messagechannel.Receiver(eventTarget); + fireauth.messagechannel.Receiver.receivers_.push(instance); + } + return instance; +}; + + +/** + * Handles a PostMessage event based on the following protocol: + * + * + * @param {!Event} event The PostMessage event to handle. + * @private + */ +fireauth.messagechannel.Receiver.prototype.handleEvent_ = function(event) { + // Respond to sender first with ack reply. This will let the client + // know that the service worker can handle this event. + var eventType = event.data['eventType']; + var eventId = event.data['eventId']; + var handlers = this.eventHandlers_[eventType]; + if (handlers && handlers.length > 0) { + // Event can be handled. + event.ports[0].postMessage({ + 'status': fireauth.messagechannel.Status.ACK, + 'eventId': eventId, + 'eventType': eventType, + 'response': null + }); + var promises = []; + goog.array.forEach(handlers, function(handler) { + // Wrap in promise in case the handler doesn't return a promise. + promises.push(goog.Promise.resolve().then(function() { + return handler(event.origin, event.data['data']); + })); + }); + // allSettled is more flexible as it executes all the promises passed and + // returns whether they succeeded or failed. + goog.Promise.allSettled(promises) + .then(function(result) { + // allResponse has the format: + // !Array + // Respond to sender with ack reply. + // De-obfuscate the allSettled result. + var allResponses = []; + goog.array.forEach(result, function(item) { + allResponses.push({ + 'fulfilled': item.fulfilled, + 'value': item.value, + // Error cannot be clone in postMessage. + 'reason': item.reason ? item.reason.message : undefined + }); + }); + // Remove undefined fields. + goog.array.forEach(allResponses, function(item) { + for (var key in item) { + if (typeof item[key] === 'undefined') { + delete item[key]; + } + } + }); + event.ports[0].postMessage({ + 'status': fireauth.messagechannel.Status.DONE, + 'eventId': eventId, + 'eventType': eventType, + 'response': allResponses + }); + }); + } + // Let unsupported events time out, as there could be external receivers + // that can handle them. +}; + + +/** + * Subscribes to events of the specified type. + * @param {string} eventType The event type to listen to. + * @param {function(string, *):!goog.Promise<*>|void} handler The async callback + * function to run when the event is triggered. + */ +fireauth.messagechannel.Receiver.prototype.subscribe = + function(eventType, handler) { + if (goog.object.isEmpty(this.eventHandlers_)) { + this.eventTarget_.addEventListener('message', this.messageEventHandler_); + } + if (typeof this.eventHandlers_[eventType] === 'undefined') { + this.eventHandlers_[eventType] = []; + } + this.eventHandlers_[eventType].push(handler); +}; + + +/** + * Unsubscribes the specified handler from the specified event. If no handler + * is specified, all handlers are unsubscribed. + * @param {string} eventType The event type to unsubscribe from. + * @param {?function(string, *):!goog.Promise<*>|void=} opt_handler The + * callback function to unsubscribe from the specified event type. If none + * is specified, all handlers are unsubscribed. + */ +fireauth.messagechannel.Receiver.prototype.unsubscribe = + function(eventType, opt_handler) { + if (typeof this.eventHandlers_[eventType] !== 'undefined' && opt_handler) { + goog.array.removeAllIf(this.eventHandlers_[eventType], function(ele) { + return ele == opt_handler; + }); + if (this.eventHandlers_[eventType].length == 0) { + delete this.eventHandlers_[eventType]; + } + } else if (!opt_handler) { + // Unsubscribe all handlers for speficied event. + delete this.eventHandlers_[eventType]; + } + if (goog.object.isEmpty(this.eventHandlers_)) { + this.eventTarget_.removeEventListener('message', this.messageEventHandler_); + } +}; diff --git a/packages/auth/src/messagechannel/sender.js b/packages/auth/src/messagechannel/sender.js new file mode 100644 index 00000000000..34766b1628c --- /dev/null +++ b/packages/auth/src/messagechannel/sender.js @@ -0,0 +1,237 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Defines the MessageChannel based wrapper for sending messages + * to other windows or workers. + */ + +goog.provide('fireauth.messagechannel.Sender'); + +goog.require('fireauth.messagechannel.Error'); +goog.require('fireauth.messagechannel.PostMessager'); +goog.require('fireauth.messagechannel.Status'); +goog.require('fireauth.messagechannel.TimeoutDuration'); +goog.require('fireauth.messagechannel.utils'); +goog.require('goog.Promise'); +goog.require('goog.array'); + + + +/** + * Helper static function to create messageChannel errors. + * @param {!fireauth.messagechannel.Error} errorId The error identifier. + * @param {?string=} opt_message The optional error message used for generic + * error types. + * @return {!Error} The constructed error to return. + * @private + */ +fireauth.messagechannel.createError_ = function(errorId, opt_message) { + if (errorId != fireauth.messagechannel.Error.UNKNOWN || !opt_message) { + return new Error(errorId); + } else { + return new Error(opt_message); + } +}; + + +/** + * Initializes a channel to send specific messages to a specified PostMessage. + * @param {!fireauth.messagechannel.PostMessager} postMessager The post messager + * to send messages to. + * @constructor + */ +fireauth.messagechannel.Sender = function(postMessager) { + /** + * @const @private {!fireauth.messagechannel.PostMessager} The messageChannel + * PostMessager. + */ + this.postMessager_ = postMessager; + /** + * @private {?MessageChannel} The messageChannel reference if + * supported. + */ + this.messageChannel_ = + fireauth.messagechannel.utils.initializeMessageChannel(); + /** @private {boolean} Whether the connection was started. */ + this.started_ = false; + /** + * @const @private {!Array} The list of subscribed message + * handlers. + */ + this.messageHandlers_ = []; +}; + + +/** + * Sends a message to the receiver. The message is identified by an event + * type and can carry additional payload data. + * The sender protocol works as follows: + * + * + * @param {string} eventType The event type identifying the message. This is + * used to help the receiver handle this message. + * @param {?Object=} opt_data The optional data to send along the message. + * @return {!goog.Promise>} A promise that + * resolves with the receiver responses. + */ +fireauth.messagechannel.Sender.prototype.send = function(eventType, opt_data) { + var self = this; + var eventId; + var data = opt_data || {}; + var onMessage; + var ackTimer; + var completionTimer; + return new goog.Promise(function(resolve, reject) { + // Send message along with port for reply + if (self.messageChannel_) { + eventId = fireauth.messagechannel.utils.generateEventId(); + // Start the connection if not already started. + self.start(); + // Handler for receiving message reply from receiver. + // Blocks promise resolution until service worker detects the change. + ackTimer = setTimeout(function() { + // The receiver may not be able to handle the response for various + // reasons: library not included, or an incompatible version of + // the library is included. + // Timeout after some time. + reject(fireauth.messagechannel.createError_( + fireauth.messagechannel.Error.UNSUPPORTED_EVENT)); + }, fireauth.messagechannel.TimeoutDuration.ACK); + onMessage = function(event) { + // Process only the expected events that match current event ID. + if (event.data['eventId'] !== eventId) { + return; + } + // This avoids adding a long wait when the receiver is unable to handle + // the event. + if (event.data['status'] === fireauth.messagechannel.Status.ACK) { + clearTimeout(ackTimer); + // Set longer timeout to allow receiver to process. + completionTimer = setTimeout(function() { + reject(fireauth.messagechannel.createError_( + fireauth.messagechannel.Error.TIMEOUT)); + }, fireauth.messagechannel.TimeoutDuration.COMPLETION); + return; + } else if (event.data['status'] === + fireauth.messagechannel.Status.DONE) { + clearTimeout(completionTimer); + if (typeof event.data['response'] !== 'undefined') { + resolve(event.data['response']); + } else { + reject(fireauth.messagechannel.createError_( + fireauth.messagechannel.Error.UNKNOWN)); + } + } else { + clearTimeout(ackTimer); + clearTimeout(completionTimer); + reject(fireauth.messagechannel.createError_( + fireauth.messagechannel.Error.INVALID_RESPONSE)); + } + }; + self.messageHandlers_.push(onMessage); + self.messageChannel_.port1.addEventListener('message', onMessage); + var request = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + // It is possible the receiver cannot handle this result. + // For example, the developer may not be including the library in the + // receiver or using an outdated version. + self.postMessager_.postMessage( + request, + [self.messageChannel_.port2]); + } else { + // No connection available. + reject(fireauth.messagechannel.createError_( + fireauth.messagechannel.Error.CONNECTION_UNAVAILABLE)); + } + }).then(function(result) { + // On completion, remove the message handler. A new one is needed for a + // new message. + self.removeMessageHandler_(onMessage); + return result; + }).thenCatch(function(error) { + // On failure, remove the message handler. A new one is needed for a new + // message. + self.removeMessageHandler_(onMessage); + throw error; + }); +}; + + +/** + * @param {function(!Event)} onMessage The message handler to remove. + * @private + */ +fireauth.messagechannel.Sender.prototype.removeMessageHandler_ = + function(onMessage) { + if (this.messageChannel_) { + goog.array.removeAllIf(this.messageHandlers_, function(ele) { + return ele == onMessage; + }); + this.messageChannel_.port1.removeEventListener('message', onMessage); + } +}; + + +/** + * Removing all subscribed message handlers. + * @private + */ +fireauth.messagechannel.Sender.prototype.removeAllMessageHandlers_ = + function() { + while (this.messageHandlers_.length > 0) { + var onMessage = this.messageHandlers_.pop(); + this.messageChannel_.port1.removeEventListener('message', onMessage); + } +}; + + +/** Closes the underlying MessageChannel connection. */ +fireauth.messagechannel.Sender.prototype.close = function() { + if (this.messageChannel_) { + // Any pending event will timeout. + this.removeAllMessageHandlers_(); + // No new messages will be returned. + this.messageChannel_.port1.close(); + this.messageChannel_ = null; + this.started_ = false; + } +}; + + +/** Starts the underlying MessageChannel connection if not already started. */ +fireauth.messagechannel.Sender.prototype.start = function() { + // Note that re-connection is not supported. If a connection is closed, a new + // sender has to be created. + if (this.messageChannel_ && !this.started_) { + this.messageChannel_.port1.start(); + this.started_ = true; + } +}; diff --git a/packages/auth/src/storage/indexeddb.js b/packages/auth/src/storage/indexeddb.js index 6f9d4ac2f33..dcd71ecec1b 100644 --- a/packages/auth/src/storage/indexeddb.js +++ b/packages/auth/src/storage/indexeddb.js @@ -24,6 +24,9 @@ goog.provide('fireauth.storage.IndexedDB'); goog.require('fireauth.AuthError'); goog.require('fireauth.authenum.Error'); +goog.require('fireauth.messagechannel.Receiver'); +goog.require('fireauth.messagechannel.Sender'); +goog.require('fireauth.messagechannel.WorkerClientPostMessager'); goog.require('fireauth.storage.Storage'); goog.require('fireauth.util'); goog.require('goog.Promise'); @@ -96,6 +99,36 @@ fireauth.storage.IndexedDB = function( opt_indexedDB || goog.global.indexedDB); /** @public {string} The storage type identifier. */ this.type = fireauth.storage.Storage.Type.INDEXEDDB; + /** + * @private {?fireauth.messagechannel.Receiver} The messageChannel receiver if + * running from a serviceworker. + */ + this.receiver_ = null; + var scope = this; + if (fireauth.util.getWorkerGlobalScope()) { + this.receiver_ = fireauth.messagechannel.Receiver.getInstance( + /** @type {!WorkerGlobalScope} */ ( + fireauth.util.getWorkerGlobalScope())); + // Listen to indexedDB changes. + this.receiver_.subscribe('keyChanged', function(origin, request) { + // Sync data. + return scope.sync_().then(function(keys) { + // Trigger listeners if unhandled changes are detected. + if (keys.length > 0) { + goog.array.forEach( + scope.storageListeners_, + function(listener) { + listener(keys); + }); + } + // When this is false, it means the change was already + // detected and processed before the notification. + return { + 'keyProcessed': goog.array.contains(keys, request['key']) + }; + }); + }); + } }; @@ -361,6 +394,8 @@ fireauth.storage.IndexedDB.prototype.set = function(key, value) { .then(function() { // Save in local copy to avoid triggering false external event. self.localMap_[key] = value; + // Announce change in key to service worker. + return self.notifySW_(key); }) .thenAlways(function() { if (isLocked) { @@ -370,6 +405,31 @@ fireauth.storage.IndexedDB.prototype.set = function(key, value) { }; +/** + * Notify the service worker of the indexeDB write operation. + * Waits until the operation is processed. + * @param {string} key The key which is changing. + * @return {!goog.Promise} A promise that resolves on delivery. + * @private + */ +fireauth.storage.IndexedDB.prototype.notifySW_ = function(key) { + if (fireauth.util.getServiceWorkerController()) { + var sender = new fireauth.messagechannel.Sender( + new fireauth.messagechannel.WorkerClientPostMessager( + /** @type {!ServiceWorker} */ ( + fireauth.util.getServiceWorkerController()))); + return sender.send('keyChanged', {'key': key}) + .then(function(responses) { + // Return nothing. + }) + .thenCatch(function(error) { + // This is a best effort approach. Ignore errors. + }); + } + return goog.Promise.resolve(); +}; + + /** * Retrieves a stored item identified by the key provided asynchronously. * The value is passed to the callback function provided. @@ -411,6 +471,8 @@ fireauth.storage.IndexedDB.prototype.remove = function(key) { }).then(function() { // Delete from local copy to avoid triggering false external event. delete self.localMap_[key]; + // Announce change in key to service worker. + return self.notifySW_(key); }).thenAlways(function() { if (isLocked) { self.pendingOpsTracker_--; diff --git a/packages/auth/src/utils.js b/packages/auth/src/utils.js index ebd9e26e8d9..f6c731f15fc 100644 --- a/packages/auth/src/utils.js +++ b/packages/auth/src/utils.js @@ -1455,3 +1455,18 @@ fireauth.util.setNoReferrer = function() { } } }; + + +/** @return {?ServiceWorker} The servicerWorker controller if available. */ +fireauth.util.getServiceWorkerController = function() { + return (navigator && + navigator.serviceWorker && + navigator.serviceWorker.controller) || null; +}; + + +/** @return {?WorkerGlobalScope} The worker global scope if available. */ +fireauth.util.getWorkerGlobalScope = function() { + return fireauth.util.isWorker() ? /** @type {!WorkerGlobalScope} */ (self) : + null; +}; diff --git a/packages/auth/test/messagechannel/postmessager_test.js b/packages/auth/test/messagechannel/postmessager_test.js new file mode 100644 index 00000000000..ab0566f17fa --- /dev/null +++ b/packages/auth/test/messagechannel/postmessager_test.js @@ -0,0 +1,88 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Tests for postmessager.js. + */ + +goog.provide('fireauth.messagechannel.PostMessagerTest'); + +goog.require('fireauth.messagechannel.WindowPostMessager'); +goog.require('fireauth.messagechannel.WorkerClientPostMessager'); +goog.require('goog.testing.MockControl'); +goog.require('goog.testing.jsunit'); + +goog.setTestOnly('fireauth.messagechannel.PostMessagerTest'); + + +var mockControl; + + +function setUp() { + mockControl = new goog.testing.MockControl(); + mockControl.$resetAll(); +} + + +function tearDown() { + try { + mockControl.$verifyAll(); + } finally { + mockControl.$tearDown(); + } +} + + +function testWindowPostMessager_defaultTargetOrigin() { + var message = {'a': 1, 'b': 2}; + var transfer = [{'tranferable1': {}}, {'tranferable2': {}}]; + var targetOrigin = '*'; + var postMessage = mockControl.createFunctionMock('postMessage'); + postMessage(message, targetOrigin, transfer).$once(); + mockControl.$replayAll(); + + var windowPostMessager = new fireauth.messagechannel.WindowPostMessager( + {'postMessage': postMessage}); + windowPostMessager.postMessage(message, transfer); +} + + +function testWindowPostMessager_explicitTargetOrigin() { + var message = {'a': 1, 'b': 2}; + var transfer = [{'tranferable1': {}}, {'tranferable2': {}}]; + var targetOrigin = 'http://www.example.com'; + var postMessage = mockControl.createFunctionMock('postMessage'); + postMessage(message, targetOrigin, transfer).$once(); + mockControl.$replayAll(); + + var windowPostMessager = new fireauth.messagechannel.WindowPostMessager( + {'postMessage': postMessage}, targetOrigin); + windowPostMessager.postMessage(message, transfer); +} + + +function testWorkerClientPostMessager() { + var message = {'a': 1, 'b': 2}; + var transfer = [{'tranferable1': {}}, {'tranferable2': {}}]; + var postMessage = mockControl.createFunctionMock('postMessage'); + postMessage(message, transfer); + mockControl.$replayAll(); + + var workerClientPostMessager = + new fireauth.messagechannel.WorkerClientPostMessager( + {'postMessage': postMessage}); + workerClientPostMessager.postMessage(message, transfer); +} diff --git a/packages/auth/test/messagechannel/receiver_test.js b/packages/auth/test/messagechannel/receiver_test.js new file mode 100644 index 00000000000..59adbaafdc0 --- /dev/null +++ b/packages/auth/test/messagechannel/receiver_test.js @@ -0,0 +1,478 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Tests for receiver.js. + */ + +goog.provide('fireauth.messagechannel.ReceiverTest'); + +goog.require('fireauth.messagechannel.Receiver'); +goog.require('goog.Promise'); +goog.require('goog.events.Event'); +goog.require('goog.events.EventTarget'); +goog.require('goog.testing.MockControl'); +goog.require('goog.testing.jsunit'); + +goog.setTestOnly('fireauth.messagechannel.ReceiverTest'); + + +var mockControl; + + +function setUp() { + ignoreArgument = goog.testing.mockmatchers.ignoreArgument; + mockControl = new goog.testing.MockControl(); + mockControl.$resetAll(); +} + + +function tearDown() { + try { + mockControl.$verifyAll(); + } finally { + mockControl.$tearDown(); + } +} + + +function testReceiver_singleHandler_success() { + // Used to prevent the test from finishing prematurely before the underlying + // logic completes. + var sendCompletionSignal; + var eventType = 'eventType1'; + var eventId = '1234'; + var origin = 'https://www.example.com'; + var data = { + 'a': 1, + 'b': 2 + }; + var expectedResponse = { + 'success': true + }; + var eventTarget = new goog.events.EventTarget(); + var postMessage = mockControl.createFunctionMock('postMessage'); + var handler1 = mockControl.createFunctionMock('handler1'); + var handler2 = mockControl.createFunctionMock('handler2'); + var event = new goog.events.Event('message'); + event.origin = origin; + event.ports = [{'postMessage': postMessage}]; + event.data = { + 'eventId': eventId, + 'eventType': eventType, + 'data': data + }; + postMessage({ + 'status': 'ack', + 'eventId': eventId, + 'eventType': eventType, + 'response': null + }).$once(); + handler1(origin, data).$does(function() { + return expectedResponse; + }).$once(); + postMessage({ + 'status': 'done', + 'eventId': eventId, + 'eventType': eventType, + 'response': [{ + 'fulfilled': true, + 'value': expectedResponse + }] + }).$does(function() { + sendCompletionSignal(); + }).$once(); + handler2().$never(); + mockControl.$replayAll(); + + var receiver = new fireauth.messagechannel.Receiver(eventTarget); + assertTrue(receiver.isListeningTo(eventTarget)); + assertFalse(receiver.isListeningTo(new goog.events.EventTarget())); + receiver.subscribe(eventType, handler1); + receiver.subscribe('unsupportedEvent', handler2); + // Simulate incoming sender message event. + eventTarget.dispatchEvent(event); + receiver.unsubscribe(eventType, handler1); + // Second event should not have any effect. + eventTarget.dispatchEvent(event); + + return new goog.Promise(function(resolve, reject) { + sendCompletionSignal = resolve; + }); +} + + +function testReceiver_singleHandler_error() { + var sendCompletionSignal; + var eventType = 'eventType1'; + var eventId = '1234'; + var origin = 'https://www.example.com'; + var data = { + 'a': 1, + 'b': 2 + }; + var expectedError = new Error('some error occurred'); + var eventTarget = new goog.events.EventTarget(); + var postMessage = mockControl.createFunctionMock('postMessage'); + var handler1 = mockControl.createFunctionMock('handler1'); + var handler2 = mockControl.createFunctionMock('handler2'); + var event = new goog.events.Event('message'); + event.origin = origin; + event.ports = [{'postMessage': postMessage}]; + event.data = { + 'eventId': eventId, + 'eventType': eventType, + 'data': data + }; + postMessage({ + 'status': 'ack', + 'eventId': eventId, + 'eventType': eventType, + 'response': null + }).$once(); + handler1(origin, data).$does(function() { + throw expectedError; + }).$once(); + postMessage({ + 'status': 'done', + 'eventId': eventId, + 'eventType': eventType, + 'response': [{ + 'fulfilled': false, + 'reason': expectedError.message + }] + }).$does(function() { + sendCompletionSignal(); + }).$once(); + handler2().$never(); + mockControl.$replayAll(); + + var receiver = new fireauth.messagechannel.Receiver(eventTarget); + receiver.subscribe(eventType, handler1); + receiver.subscribe('unsupportedEvent', handler2); + // Simulate incoming sender message event. + eventTarget.dispatchEvent(event); + receiver.unsubscribe(eventType, handler1); + // Second event should not have any effect. + eventTarget.dispatchEvent(event); + + return new goog.Promise(function(resolve, reject) { + sendCompletionSignal = resolve; + }); +} + + +function testReceiver_multipleHandler_singleEvent_success() { + var sendCompletionSignal; + var eventType = 'eventType1'; + var eventId = '1234'; + var origin = 'https://www.example.com'; + var data = { + 'a': 1, + 'b': 2 + }; + var expectedResponse1 = { + 'c': 3 + }; + var expectedResponse2 = { + 'd': 4 + }; + var eventTarget = new goog.events.EventTarget(); + var postMessage = mockControl.createFunctionMock('postMessage'); + var handler1 = mockControl.createFunctionMock('handler1'); + var handler2 = mockControl.createFunctionMock('handler2'); + var handler3 = mockControl.createFunctionMock('handler3'); + var event = new goog.events.Event('message'); + event.origin = origin; + event.ports = [{'postMessage': postMessage}]; + event.data = { + 'eventId': eventId, + 'eventType': eventType, + 'data': data + }; + // First handler. + postMessage({ + 'status': 'ack', + 'eventId': eventId, + 'eventType': eventType, + 'response': null + }).$once(); + handler1(origin, data).$does(function() { + return expectedResponse1; + }).$once(); + // Second handler. + handler2(origin, data).$does(function() { + return expectedResponse2; + }).$once(); + postMessage({ + 'status': 'done', + 'eventId': eventId, + 'eventType': eventType, + 'response': [{ + 'fulfilled': true, + 'value': expectedResponse1 + }, { + 'fulfilled': true, + 'value': expectedResponse2 + }] + }).$does(function() { + sendCompletionSignal(); + }).$once(); + // Third handler. + handler3().$never(); + mockControl.$replayAll(); + + var receiver = new fireauth.messagechannel.Receiver(eventTarget); + assertTrue(receiver.isListeningTo(eventTarget)); + assertFalse(receiver.isListeningTo(new goog.events.EventTarget())); + receiver.subscribe(eventType, handler1); + receiver.subscribe(eventType, handler2); + receiver.subscribe('unsupportedEvent', handler3); + // Simulate incoming sender message event. handler1 and handler2 should + // trigger. + eventTarget.dispatchEvent(event); + receiver.unsubscribe(eventType, handler1); + receiver.unsubscribe(eventType, handler2); + // Second event should not have any effect. + eventTarget.dispatchEvent(event); + + return new goog.Promise(function(resolve, reject) { + sendCompletionSignal = resolve; + }); +} + + +function testReceiver_multipleHandler_singleEvent_error() { + var sendCompletionSignal; + var eventType = 'eventType1'; + var eventId = '1234'; + var origin = 'https://www.example.com'; + var data = { + 'a': 1, + 'b': 2 + }; + var expectedResponse1 = { + 'c': 3 + }; + var expectedError = new Error('some error occurred'); + var eventTarget = new goog.events.EventTarget(); + var postMessage = mockControl.createFunctionMock('postMessage'); + var handler1 = mockControl.createFunctionMock('handler1'); + var handler2 = mockControl.createFunctionMock('handler2'); + var handler3 = mockControl.createFunctionMock('handler3'); + var event = new goog.events.Event('message'); + event.origin = origin; + event.ports = [{'postMessage': postMessage}]; + event.data = { + 'eventId': eventId, + 'eventType': eventType, + 'data': data + }; + // First handler. + postMessage({ + 'status': 'ack', + 'eventId': eventId, + 'eventType': eventType, + 'response': null + }).$once(); + handler1(origin, data).$does(function() { + return expectedResponse1; + }).$once(); + // Second handler. + handler2(origin, data).$does(function() { + throw expectedError; + }).$once(); + postMessage({ + 'status': 'done', + 'eventId': eventId, + 'eventType': eventType, + 'response': [{ + 'fulfilled': true, + 'value': expectedResponse1 + }, { + 'fulfilled': false, + 'reason': expectedError.message + }] + }).$does(function() { + sendCompletionSignal(); + }).$once(); + // Third handler. + handler3().$never(); + mockControl.$replayAll(); + + var receiver = new fireauth.messagechannel.Receiver(eventTarget); + assertTrue(receiver.isListeningTo(eventTarget)); + assertFalse(receiver.isListeningTo(new goog.events.EventTarget())); + receiver.subscribe(eventType, handler1); + receiver.subscribe(eventType, handler2); + receiver.subscribe('unsupportedEvent', handler3); + // Simulate incoming sender message event. handler1 and handler2 should + // trigger. + eventTarget.dispatchEvent(event); + receiver.unsubscribe(eventType, handler1); + receiver.unsubscribe(eventType, handler2); + // Second event should not have any effect. + eventTarget.dispatchEvent(event); + + return new goog.Promise(function(resolve, reject) { + sendCompletionSignal = resolve; + }); +} + + +function testReceiver_multipleHandler_multipleEvent_success() { + var sendCompletionSignal; + var eventType1 = 'eventType1'; + var eventId1 = '1234'; + var origin1 = 'https://www.example.com'; + var data1 = { + 'a': 1, + 'b': 2 + }; + var expectedResponse1 = { + 'response': 'res1' + }; + var eventType2 = 'eventType2'; + var eventId2 = '5678'; + var origin2 = 'https://www.other.com'; + var data2 = { + 'c': 3, + 'd': 4 + }; + var expectedResponse2 = { + 'response': 'res2' + }; + var eventTarget = new goog.events.EventTarget(); + var postMessage = mockControl.createFunctionMock('postMessage'); + var handler1 = mockControl.createFunctionMock('handler1'); + var handler2 = mockControl.createFunctionMock('handler2'); + var handler3 = mockControl.createFunctionMock('handler3'); + var event1 = new goog.events.Event('message'); + event1.origin = origin1; + event1.ports = [{'postMessage': postMessage}]; + event1.data = { + 'eventId': eventId1, + 'eventType': eventType1, + 'data': data1 + }; + var event2 = new goog.events.Event('message'); + event2.origin = origin2; + event2.ports = [{'postMessage': postMessage}]; + event2.data = { + 'eventId': eventId2, + 'eventType': eventType2, + 'data': data2 + }; + // First handler. + postMessage({ + 'status': 'ack', + 'eventId': eventId1, + 'eventType': eventType1, + 'response': null + }).$once(); + postMessage({ + 'status': 'ack', + 'eventId': eventId2, + 'eventType': eventType2, + 'response': null + }).$once(); + handler1(origin1, data1).$does(function() { + return expectedResponse1; + }).$once(); + // Second handler. + handler2(origin2, data2).$does(function() { + return expectedResponse2; + }).$once(); + postMessage({ + 'status': 'done', + 'eventId': eventId1, + 'eventType': eventType1, + 'response': [{ + 'fulfilled': true, + 'value': expectedResponse1 + }] + }).$once(); + postMessage({ + 'status': 'done', + 'eventId': eventId2, + 'eventType': eventType2, + 'response': [{ + 'fulfilled': true, + 'value': expectedResponse2 + }] + }).$does(function() { + sendCompletionSignal(); + }).$once(); + // Third handler. + handler3().$never(); + mockControl.$replayAll(); + + var receiver = new fireauth.messagechannel.Receiver(eventTarget); + assertTrue(receiver.isListeningTo(eventTarget)); + assertFalse(receiver.isListeningTo(new goog.events.EventTarget())); + // Subscribe, unsubscribe and then re-subscribe handler1. + receiver.subscribe(eventType1, handler1); + receiver.unsubscribe(eventType1, handler1); + receiver.subscribe(eventType1, handler1); + + receiver.subscribe(eventType2, handler2); + receiver.subscribe('unsupportedEvent', handler3); + // Simulate 2 incoming sender message events (eventType 1 and 2). handler1 and + // handler2 should trigger. + eventTarget.dispatchEvent(event1); + eventTarget.dispatchEvent(event2); + + return new goog.Promise(function(resolve, reject) { + sendCompletionSignal = resolve; + }); +} + + +function testReceiver_singleHandler_unsubscribeAll() { + var eventType = 'eventType1'; + var eventId = '1234'; + var origin = 'https://www.example.com'; + var data = { + 'a': 1, + 'b': 2 + }; + var eventTarget = new goog.events.EventTarget(); + var postMessage = mockControl.createFunctionMock('postMessage'); + var handler1 = mockControl.createFunctionMock('handler1'); + var handler2 = mockControl.createFunctionMock('handler2'); + var event = new goog.events.Event('message'); + event.origin = origin; + event.ports = [{'postMessage': postMessage}]; + event.data = { + 'eventId': eventId, + 'eventType': eventType, + 'data': data + }; + postMessage(ignoreArgument).$never(); + handler1().$never(); + handler2().$never(); + mockControl.$replayAll(); + + var receiver = new fireauth.messagechannel.Receiver(eventTarget); + assertTrue(receiver.isListeningTo(eventTarget)); + assertFalse(receiver.isListeningTo(new goog.events.EventTarget())); + receiver.subscribe(eventType, handler1); + receiver.subscribe(eventType, handler2); + // Unsubscribe all handlers. + receiver.unsubscribe(eventType); + // No handler should be triggered. + eventTarget.dispatchEvent(event); +} diff --git a/packages/auth/test/messagechannel/sender_test.js b/packages/auth/test/messagechannel/sender_test.js new file mode 100644 index 00000000000..365565443ff --- /dev/null +++ b/packages/auth/test/messagechannel/sender_test.js @@ -0,0 +1,541 @@ +/** + * Copyright 2018 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. + */ + +/** + * @fileoverview Tests for sender.js. + */ + +goog.provide('fireauth.messagechannel.SenderTest'); + +goog.require('fireauth.messagechannel.Error'); +goog.require('fireauth.messagechannel.Sender'); +goog.require('fireauth.messagechannel.TimeoutDuration'); +goog.require('fireauth.messagechannel.utils'); +goog.require('goog.Promise'); +goog.require('goog.events.Event'); +goog.require('goog.events.EventTarget'); +goog.require('goog.testing.MockClock'); +goog.require('goog.testing.MockControl'); +goog.require('goog.testing.jsunit'); + +goog.setTestOnly('fireauth.messagechannel.SenderTest'); + + +var mockControl; +var clock; +var ignoreArgument; + + +function setUp() { + ignoreArgument = goog.testing.mockmatchers.ignoreArgument; + mockControl = new goog.testing.MockControl(); + mockControl.$resetAll(); + // Install mock clock. + clock = new goog.testing.MockClock(true); +} + + +function tearDown() { + try { + mockControl.$verifyAll(); + } finally { + mockControl.$tearDown(); + } + goog.dispose(clock); +} + + +/** + * @param {!mockControl} mockControl The MockControl reference. + * @return {!MessageChannel} A mock messagechannel for testing. + */ +function createMockMessageChannel(mockControl) { + var messageChannel = { + port1: new goog.events.EventTarget(), + port2: new goog.events.EventTarget() + }; + messageChannel.port1.start = mockControl.createFunctionMock('start'); + messageChannel.port1.close = mockControl.createFunctionMock('close'); + return messageChannel; +} + + +function testSender_messageChannelUnsupported() { + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + initializeMessageChannel().$returns(null); + postMessage(ignoreArgument, ignoreArgument, ignoreArgument).$never(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + return sender.send('myEvent', {'a': 1, 'b': 2}) + .then(fail) + .thenCatch(function(error) { + assertEquals( + error.message, + fireauth.messagechannel.Error.CONNECTION_UNAVAILABLE); + }); +} + + +function testSender_send_ackTimeout() { + var eventId = '12345678'; + var eventType = 'myEvent'; + var data = {'a': 1, 'b': 2}; + var expectedRequest = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + generateEventId().$returns(eventId).$once(); + messageChannel.port1.start().$once(); + postMessage(expectedRequest, [messageChannel.port2]).$does(function() { + // Simulate ACK timeout. + clock.tick(fireauth.messagechannel.TimeoutDuration.ACK); + }).$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + return sender.send(eventType, data) + .then(fail) + .thenCatch(function(error) { + assertEquals( + error.message, + fireauth.messagechannel.Error.UNSUPPORTED_EVENT); + }); +} + + +function testSender_send_invalidResponse() { + var eventId = '12345678'; + var eventType = 'myEvent'; + var data = {'a': 1, 'b': 2}; + var expectedRequest = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + generateEventId().$returns(eventId).$once(); + messageChannel.port1.start().$once(); + postMessage(expectedRequest, [messageChannel.port2]).$does(function() { + var event = new goog.events.Event('message'); + // Simulate an invalid response. + event.data = { + 'eventType': eventType, + 'eventId': eventId, + 'status': 'invalid' + }; + messageChannel.port1.dispatchEvent(event); + }).$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + return sender.send(eventType, data) + .then(fail) + .thenCatch(function(error) { + assertEquals( + error.message, + fireauth.messagechannel.Error.INVALID_RESPONSE); + }); +} + + +function testSender_send_completionTimeout() { + var eventId = '12345678'; + var eventType = 'myEvent'; + var data = {'a': 1, 'b': 2}; + var expectedRequest = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + generateEventId().$returns(eventId).$once(); + messageChannel.port1.start().$once(); + postMessage(expectedRequest, [messageChannel.port2]).$does(function() { + var event = new goog.events.Event('message'); + event.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'ack' + }; + // Simulate ACK response sent successfully. + messageChannel.port1.dispatchEvent(event); + // Simulate completion response timing out. + clock.tick(fireauth.messagechannel.TimeoutDuration.COMPLETION); + }).$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + return sender.send(eventType, data) + .then(fail) + .thenCatch(function(error) { + assertEquals( + error.message, + fireauth.messagechannel.Error.TIMEOUT); + }); +} + + +function testSender_send_completionSuccess() { + var eventId = '12345678'; + var eventType = 'myEvent'; + var data = {'a': 1, 'b': 2}; + var expectedRequest = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + var expectedSuccessResponse = [{ + 'fulfilled': true, + 'value': { + 'c': 3, + 'd': 4 + } + }]; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + generateEventId().$returns(eventId).$once(); + messageChannel.port1.start().$once(); + postMessage(expectedRequest, [messageChannel.port2]).$does(function() { + var event1 = new goog.events.Event('message'); + var event2 = new goog.events.Event('message'); + event1.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'ack' + }; + event2.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'done', + 'response': expectedSuccessResponse + }; + // Simulate successful ACK and DONE responses. + messageChannel.port1.dispatchEvent(event1); + messageChannel.port1.dispatchEvent(event2); + }).$once(); + messageChannel.port1.close().$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + return sender.send(eventType, data) + .then(function(result) { + assertEquals(expectedSuccessResponse, result); + sender.close(); + // Second call should do nothing. + sender.close(); + // Start should not be able to restart the connection. + sender.start(); + // Connection should not be available anymore. + return sender.send(eventType, data).then(fail, function(error) { + assertEquals( + error.message, + fireauth.messagechannel.Error.CONNECTION_UNAVAILABLE); + }); + }); +} + + +function testSender_send_completionError() { + var eventId = '12345678'; + var eventType = 'myEvent'; + var data = {'a': 1, 'b': 2}; + var expectedRequest = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + var expectedErrorResponse = [{ + 'fulfilled': false, + 'reason': 'some error occurred' + }]; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + // start called early. + messageChannel.port1.start().$once(); + generateEventId().$returns(eventId).$once(); + postMessage(expectedRequest, [messageChannel.port2]).$does(function() { + var event1 = new goog.events.Event('message'); + var event2 = new goog.events.Event('message'); + event1.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'ack' + }; + event2.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'done', + 'response': expectedErrorResponse + }; + clock.tick(fireauth.messagechannel.TimeoutDuration.ACK - 1); + messageChannel.port1.dispatchEvent(event1); + clock.tick(fireauth.messagechannel.TimeoutDuration.COMPLETION - 1); + messageChannel.port1.dispatchEvent(event2); + }).$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + sender.start(); + // Second call should be ignored. + sender.start(); + return sender.send(eventType, data) + .then(function(result) { + assertEquals(expectedErrorResponse, result); + }); +} + + +function testSender_send_closedConnection() { + var eventId = '12345678'; + var eventType = 'myEvent'; + var data = {'a': 1, 'b': 2}; + var expectedRequest = { + 'eventType': eventType, + 'eventId': eventId, + 'data': data + }; + var expectedErrorResponse = { + 'fulfilled': true, + 'value': 'success' + }; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + // start called early. + messageChannel.port1.start().$once(); + generateEventId().$returns(eventId).$once(); + postMessage(expectedRequest, [messageChannel.port2]).$does(function() { + var event1 = new goog.events.Event('message'); + var event2 = new goog.events.Event('message'); + event1.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'ack' + }; + event2.data = { + 'eventId': eventId, + 'eventType': eventType, + 'status': 'done', + 'response': expectedErrorResponse + }; + messageChannel.port1.dispatchEvent(event1); + // Simulate the connection gets closed. + sender.close(); + messageChannel.port1.dispatchEvent(event2); + // Second event will be ignored and the resolver will timeout. + clock.tick(fireauth.messagechannel.TimeoutDuration.COMPLETION); + }).$once(); + messageChannel.port1.close().$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + return sender.send(eventType, data) + .then(fail, function(error) { + assertEquals( + error.message, + fireauth.messagechannel.Error.TIMEOUT); + }); +} + + +function testSender_send_multipleMessages() { + var eventId1 = '1234'; + var eventType1 = 'myEvent1'; + var data1 = {'request1': 'req1'}; + var expectedRequest1 = { + 'eventType': eventType1, + 'eventId': eventId1, + 'data': data1 + }; + var expectedSuccessResponse1 = [{ + 'fulfilled': true, + 'value': { + 'response': 'res1' + } + }]; + + var eventId2 = '5678'; + var eventType2 = 'myEvent2'; + var data2 = {'request2': 'req2'}; + var expectedRequest2 = { + 'eventType': eventType2, + 'eventId': eventId2, + 'data': data2 + }; + var expectedSuccessResponse2 = [{ + 'fulfilled': true, + 'value': { + 'response': 'res2' + } + }]; + + var eventId3 = '9012'; + var data3 = {'request3': 'req3'}; + var expectedRequest3 = { + // Test with same event as above. + 'eventType': eventType1, + 'eventId': eventId3, + 'data': data3 + }; + var expectedSuccessResponse3 = [{ + 'fulfilled': true, + 'value': { + 'response': 'res3' + } + }]; + + var messageChannel = createMockMessageChannel(mockControl); + var postMessage = mockControl.createFunctionMock('postMessage'); + var initializeMessageChannel = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'initializeMessageChannel'); + var generateEventId = mockControl.createMethodMock( + fireauth.messagechannel.utils, 'generateEventId'); + initializeMessageChannel().$returns(messageChannel).$once(); + generateEventId().$returns(eventId1).$once(); + generateEventId().$returns(eventId2).$once(); + generateEventId().$returns(eventId3).$once(); + messageChannel.port1.start().$once(); + // First event. + postMessage(expectedRequest1, [messageChannel.port2]).$does(function() { + var event1 = new goog.events.Event('message'); + var event2 = new goog.events.Event('message'); + event1.data = { + 'eventId': eventId1, + 'eventType': eventType1, + 'status': 'ack' + }; + event2.data = { + 'eventId': eventId1, + 'eventType': eventType1, + 'status': 'done', + 'response': expectedSuccessResponse1 + }; + messageChannel.port1.dispatchEvent(event1); + messageChannel.port1.dispatchEvent(event2); + }).$once(); + // Second event. + postMessage(expectedRequest2, [messageChannel.port2]).$does(function() { + var event1 = new goog.events.Event('message'); + var event2 = new goog.events.Event('message'); + event1.data = { + 'eventId': eventId2, + 'eventType': eventType2, + 'status': 'ack' + }; + event2.data = { + 'eventId': eventId2, + 'eventType': eventType2, + 'status': 'done', + 'response': expectedSuccessResponse2 + }; + messageChannel.port1.dispatchEvent(event1); + messageChannel.port1.dispatchEvent(event2); + }).$once(); + // Third event. + postMessage(expectedRequest3, [messageChannel.port2]).$does(function() { + var event1 = new goog.events.Event('message'); + var event2 = new goog.events.Event('message'); + event1.data = { + 'eventId': eventId3, + 'eventType': eventType1, + 'status': 'ack' + }; + event2.data = { + 'eventId': eventId3, + 'eventType': eventType1, + 'status': 'done', + 'response': expectedSuccessResponse3 + }; + messageChannel.port1.dispatchEvent(event1); + messageChannel.port1.dispatchEvent(event2); + }).$once(); + mockControl.$replayAll(); + + var sender = new fireauth.messagechannel.Sender({ + 'postMessage': postMessage + }); + // goog.Promise.all will fail if a single promise fails. + // Test with mixture of events (2 types of events). Each request will have a + // unique event ID. + return goog.Promise.all( + [ + sender.send(eventType1, data1), + sender.send(eventType2, data2), + sender.send(eventType1, data3) + ]).then(function(results) { + assertEquals(3, results.length); + assertEquals(expectedSuccessResponse1, results[0]); + assertEquals(expectedSuccessResponse2, results[1]); + assertEquals(expectedSuccessResponse3, results[2]); + }); +} diff --git a/packages/auth/test/storage/indexeddb_test.js b/packages/auth/test/storage/indexeddb_test.js index fc3346dae9c..2de6afc89f1 100644 --- a/packages/auth/test/storage/indexeddb_test.js +++ b/packages/auth/test/storage/indexeddb_test.js @@ -18,10 +18,13 @@ goog.provide('fireauth.storage.IndexedDBTest'); goog.require('fireauth.AuthError'); goog.require('fireauth.authenum.Error'); +goog.require('fireauth.messagechannel.Receiver'); +goog.require('fireauth.messagechannel.Sender'); goog.require('fireauth.storage.IndexedDB'); goog.require('fireauth.storage.Storage'); goog.require('goog.Promise'); goog.require('goog.testing.MockClock'); +goog.require('goog.testing.MockControl'); goog.require('goog.testing.PropertyReplacer'); goog.require('goog.testing.jsunit'); goog.require('goog.testing.recordFunction'); @@ -29,6 +32,8 @@ goog.require('goog.testing.recordFunction'); goog.setTestOnly('fireauth.storage.IndexedDBTest'); +var mockControl; +var ignoreArgument; var stubs = new goog.testing.PropertyReplacer(); var db = null; var manager; @@ -39,6 +44,9 @@ var deleted; function setUp() { + mockControl = new goog.testing.MockControl(); + ignoreArgument = goog.testing.mockmatchers.ignoreArgument; + mockControl.$resetAll(); deleted = 0; // IndexedDB not supported in IE9. stubs.replace( @@ -216,6 +224,11 @@ function tearDown() { indexedDBMock = null; stubs.reset(); goog.dispose(clock); + try { + mockControl.$verifyAll(); + } finally { + mockControl.$tearDown(); + } } @@ -395,3 +408,207 @@ function testStopListeners() { assertArrayEquals( ['key1', 'key2'], listener3.getLastCall().getArgument(0)); } + + +function testReceiverSubscribed_noWorkerGlobalScope() { + var getWorkerGlobalScope = mockControl.createMethodMock( + fireauth.util, 'getWorkerGlobalScope'); + var getInstance = mockControl.createMethodMock( + fireauth.messagechannel.Receiver, 'getInstance'); + getWorkerGlobalScope().$returns(null).$atLeastOnce(); + getInstance().$never(); + mockControl.$replayAll(); + + manager = getDefaultFireauthManager(); + return manager.get('abc').then(function(value) { + assertNull(value); + }); +} + + +function testReceiverSubscribed_externalChange_notYetProcessed() { + var listener1 = goog.testing.recordFunction(); + var subscribedCallback; + var workerGlobalScope = {}; + var getWorkerGlobalScope = mockControl.createMethodMock( + fireauth.util, 'getWorkerGlobalScope'); + var receiver = mockControl.createStrictMock(fireauth.messagechannel.Receiver); + var getInstance = mockControl.createMethodMock( + fireauth.messagechannel.Receiver, 'getInstance'); + getWorkerGlobalScope().$returns(workerGlobalScope).$atLeastOnce(); + getInstance(workerGlobalScope).$returns(receiver); + receiver.subscribe('keyChanged', ignoreArgument) + .$does(function(eventType, callback) { + subscribedCallback = callback; + }).$once(); + mockControl.$replayAll(); + + manager = getDefaultFireauthManager(); + manager.addStorageListener(listener1); + return manager.get('abc').then(function(value) { + assertNull(value); + // Simulate external indexedDB change. + db.store['firebaseLocalStorage'] = { + 'abc': {'fbase_key': 'abc', 'value': 'def'} + }; + return subscribedCallback('https://www.example.com', {'key': 'abc'}); + }).then(function(response) { + // Confirm sync completed. Status true returned to confirm the key was + // processed. + assertObjectEquals({'keyProcessed': true}, response); + // Listener should trigger with expected argument. + assertEquals(1, listener1.getCallCount()); + assertArrayEquals(['abc'], listener1.getLastCall().getArgument(0)); + return manager.get('abc'); + }).then(function(value) { + assertEquals('def', value); + }); +} + + +function testReceiverSubscribed_externalChange_alreadyProcessed() { + var listener1 = goog.testing.recordFunction(); + var subscribedCallback; + var workerGlobalScope = {}; + var getWorkerGlobalScope = mockControl.createMethodMock( + fireauth.util, 'getWorkerGlobalScope'); + var receiver = mockControl.createStrictMock(fireauth.messagechannel.Receiver); + var getInstance = mockControl.createMethodMock( + fireauth.messagechannel.Receiver, 'getInstance'); + getWorkerGlobalScope().$returns(workerGlobalScope).$atLeastOnce(); + getInstance(workerGlobalScope).$returns(receiver); + receiver.subscribe('keyChanged', ignoreArgument) + .$does(function(eventType, callback) { + subscribedCallback = callback; + }).$once(); + mockControl.$replayAll(); + + manager = getDefaultFireauthManager(); + manager.addStorageListener(listener1); + return manager.set('abc', 'def').then(function() { + return subscribedCallback('https://www.example.com', {'key': 'abc'}); + }).then(function(response) { + // Confirm sync completed but key not processed since no change is detected. + assertObjectEquals({'keyProcessed': false}, response); + // No listener should trigger. + assertEquals(0, listener1.getCallCount()); + return manager.get('abc'); + }).then(function(value) { + assertEquals('def', value); + }); +} + + +function testSender_writeOperations_serviceWorkerControllerUnavailable() { + var getServiceWorkerController = mockControl.createMethodMock( + fireauth.util, 'getServiceWorkerController'); + var sender = mockControl.createStrictMock(fireauth.messagechannel.Sender); + var senderConstructor = mockControl.createConstructorMock( + fireauth.messagechannel, 'Sender'); + getServiceWorkerController().$returns(null).$atLeastOnce(); + // No sender initialized. + senderConstructor(ignoreArgument).$never(); + sender.send(ignoreArgument).$never(); + mockControl.$replayAll(); + + // Set and remove should not trigger sender. + manager = getDefaultFireauthManager(); + return manager.set('abc', 'def').then(function() { + return manager.get('abc'); + }).then(function(value) { + assertEquals('def', value); + return manager.remove('abc'); + }).then(function() { + return manager.get('abc'); + }).then(function(value) { + assertNull(value); + }); +} + + +function testSender_writeOperations_serviceWorkerControllerAvailable() { + var status = []; + var serviceWorkerController = {}; + var getServiceWorkerController = mockControl.createMethodMock( + fireauth.util, 'getServiceWorkerController'); + + getServiceWorkerController().$returns(serviceWorkerController).$atLeastOnce(); + var sender = mockControl.createStrictMock(fireauth.messagechannel.Sender); + var senderConstructor = mockControl.createConstructorMock( + fireauth.messagechannel, 'Sender'); + // Successful set event. + senderConstructor(ignoreArgument).$returns(sender); + sender.send('keyChanged', {'key': 'abc'}).$does(function(eventType, data) { + status.push(0); + return goog.Promise.resolve([ + { + 'fulfilled': true, + 'value': {'keyProcessed': true} + } + ]); + }).$once(); + // Successful remove event. + senderConstructor(ignoreArgument).$returns(sender); + sender.send('keyChanged', {'key': 'abc'}).$does(function(eventType, data) { + status.push(1); + return goog.Promise.resolve([ + { + 'fulfilled': true, + 'value': {'keyProcessed': true} + } + ]); + }).$once(); + // Failing set event. + senderConstructor(ignoreArgument).$returns(sender); + sender.send('keyChanged', {'key': 'abc'}).$does(function(eventType, data) { + status.push(2); + return goog.Promise.reject(new Error('unsupported_event')); + }).$once(); + // Failing remove event. + senderConstructor(ignoreArgument).$returns(sender); + sender.send('keyChanged', {'key': 'abc'}).$does(function(eventType, data) { + status.push(3); + return goog.Promise.reject(new Error('invalid_response')); + }).$once(); + mockControl.$replayAll(); + + manager = getDefaultFireauthManager(); + return manager.set('abc', 'def').then(function() { + // Set should trigger sender at this point. + assertArrayEquals([0], status); + return manager.get('abc'); + }).then(function(value) { + // Get shouldn't trigger. + assertArrayEquals([0], status); + assertEquals('def', value); + return manager.remove('abc'); + }).then(function() { + // Remove should trigger sender at this point. + assertArrayEquals([0, 1], status); + return manager.get('abc'); + }).then(function(value) { + // Get shouldn't trigger. + assertArrayEquals([0, 1], status); + assertNull(value); + // This should resolve even if sender error occurs. + return manager.set('abc', 'ghi'); + }).then(function() { + // Set should trigger sender at this point. + assertArrayEquals([0, 1, 2], status); + return manager.get('abc'); + }).then(function(value) { + // Get shouldn't trigger. + assertArrayEquals([0, 1, 2], status); + assertEquals('ghi', value); + // This should resolve even if sender error occurs. + return manager.remove('abc'); + }).then(function() { + // Remove should trigger sender at this point. + assertArrayEquals([0, 1, 2, 3], status); + return manager.get('abc'); + }).then(function(value) { + // Get shouldn't trigger. + assertArrayEquals([0, 1, 2, 3], status); + assertNull(value); + }); +}