├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── browser.ts ├── index.ts ├── request.ts └── tsconfig.json └── test ├── a.html └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | /lib/ 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src 3 | test 4 | .* 5 | tslint.json 6 | *.log 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | - 12 5 | - 11 6 | - 10 7 | - 9 8 | - 8 9 | - 7 10 | - 6 11 | - 5 12 | - 4 13 | before_script: 14 | - npm run prepare 15 | os: 16 | - linux 17 | - osx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webdav-client [![npm Version](https://img.shields.io/npm/v/webdav-client.svg)](https://www.npmjs.com/package/webdav-client) [![Build Status](https://travis-ci.org/OpenMarshal/npm-WebDAV-Client.svg?branch=master)](https://travis-ci.org/OpenMarshal/npm-WebDAV-Client) 2 | 3 | This is a WebDAV client. 4 | 5 | It is not meant to be used on browsers yet. 6 | 7 | ## Install 8 | 9 | ```bash 10 | npm install webdav-client 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```javascript 16 | import * as webdavClient from 'webdav-client' 17 | // or 18 | import { Connection } from 'webdav-client' 19 | // or 20 | const webdavClient = require('webdav-client'); 21 | 22 | // Create the client object 23 | const connection = new webdavClient.Connection('http://my-webdav-server:1900'); 24 | 25 | connection.get('/path/of/my/file.txt', (e, content) => { 26 | if(e) 27 | throw e; 28 | 29 | console.log(content); 30 | }) 31 | ``` 32 | 33 | ## Methods 34 | 35 | ```typescript 36 | class Connection 37 | { 38 | constructor(url : string) 39 | constructor(options : ConnectionOptions) 40 | 41 | request(options : RequestOptions, callback : ResponseCallback) // Custom request 42 | stream(options : RequestOptions) : Stream // Custom streaming request 43 | 44 | // Might be needed before using the streaming form of the methods (put and get) 45 | prepareForStreaming(path : string, callback : (error : Error) => void) : void 46 | prepareForStreaming(callback : (error : Error) => void) : void 47 | 48 | readdir(path : string, callback : (error : Error, files ?: string[]) => void) : void 49 | readdir(path : string, options : ConnectionReaddirOptions, callback : (error : Error, files : string[] | ConnectionReaddirComplexResult[]) => void) : void 50 | 51 | exists(path : string, callback : (error : Error, exists : boolean) => void) : void 52 | 53 | mkdir(path : string, callback : (error : Error) => void) : void 54 | delete(path : string, callback : (error : Error) => void) : void 55 | 56 | get(path : string, callback : (error : Error, body : ContentType) => void) : void 57 | get(path : string, callback : (error : Error, body : ContentType) => void) : Stream 58 | 59 | put(path : string, content : ContentType, callback : (error : Error) => void) : void 60 | put(path : string) : Stream 61 | 62 | move(pathSource : string, pathDestination : string, override : boolean, callback : (error : Error) => void) : void 63 | move(pathSource : string, pathDestination : string, callback : (error : Error) => void) : void 64 | 65 | copy(pathSource : string, pathDestination : string, override : boolean, callback : (error : Error) => void) : void 66 | copy(pathSource : string, pathDestination : string, callback : (error : Error) => void) : void 67 | 68 | lock(path : string, callback : (error ?: Error, lockUID ?: Lock) => void) : void 69 | refreshLock(path : string, lock : string | Lock, callback : (error : Error) => void) : void 70 | unlock(path : string, lock : string | Lock, callback : (error : Error) => void) : void 71 | 72 | setProperties(path : string, properties : Properties, callback : (error : Error) => void) : void 73 | removeProperties(path : string, properties : string[], callback : (error : Error) => void) : void 74 | getProperties(path : string, callback : (error : Error, properties : Properties) => void) : void 75 | getProperties(path : string, options : ConnectionReaddirOptions, callback : (error : Error, properties : Properties) => void) : void 76 | } 77 | ``` 78 | 79 | The `Connection` options : 80 | 81 | ```typescript 82 | interface ConnectionOptions 83 | { 84 | url : string 85 | authenticator ?: Authenticator 86 | username ?: string 87 | password ?: string 88 | } 89 | ``` 90 | 91 | The `ConnectionReaddirOptions` interface : 92 | 93 | ```typescript 94 | interface ConnectionReaddirOptions 95 | { 96 | // true = get a ConnectionReaddirComplexResult Array as callback result 97 | // false (default) = get a String Array as callback result 98 | properties ?: boolean 99 | // An array of properties which will be sent with the PROPFIND request 100 | extraProperties: ConnectionReaddirProperty[] 101 | } 102 | ``` 103 | 104 | The `ConnectionReaddirOptions` interface : 105 | 106 | ```typescript 107 | interface ConnectionReaddirProperty 108 | { 109 | namespace: string 110 | namespaceShort: string 111 | element: string 112 | // Default value. If undefined and the XML response doesn't have this element, it will not be returned 113 | default?: any 114 | // true = It will be cast to number | string | boolean 115 | // false (default) = it is returned as string 116 | nativeType?: boolean 117 | } 118 | ``` 119 | 120 | The `ConnectionReaddirComplexResult` interface : 121 | 122 | ```typescript 123 | interface ConnectionReaddirComplexResult 124 | { 125 | creationDate : Date 126 | lastModified : Date 127 | isDirectory : boolean 128 | isFile : boolean 129 | type : 'directory' | 'file' 130 | size : number 131 | href : string 132 | name : string 133 | extraProperties: { 134 | [name : string] : string | number | boolean 135 | } 136 | } 137 | ``` 138 | 139 | ## Streaming 140 | 141 | If you want to perform a `get` or `put` in streaming mode, you can call the methods without a callback (and without the content argument for the `put`). 142 | 143 | ```javascript 144 | const stream = connection.get('/my/file.txt'); 145 | stream.on('data', (chunk) => { 146 | console.log(chunk.toString()); 147 | }) 148 | stream.on('end', () => { 149 | console.log('Done.'); 150 | }); 151 | ``` 152 | 153 | ```javascript 154 | const stream = connection.put('/my/file.txt'); 155 | stream.on('finish', () => { 156 | console.log('Done.'); 157 | }); 158 | otherStream.pipe(stream); 159 | ``` 160 | 161 | ## Custom requests 162 | 163 | To do custom requests, you can use the `request(...)` and `stream(...)` methods. 164 | 165 | They take a `RequestOptions` argument. 166 | 167 | ```typescript 168 | interface RequestOptions 169 | { 170 | url : string 171 | method : string 172 | headers ?: { 173 | [name : string] : string 174 | } 175 | body ?: ContentType 176 | } 177 | ``` 178 | 179 | ## Web browser compatibility 180 | 181 | This library can be used in a web browser. 182 | 183 | You can produce the web browser library from your from with, for instance, `browserify` or you can use the "browserified" file itsef (located at `lib/browserified.js`). 184 | 185 | Here is the usage of the `browserified.js` file : 186 | 187 | ```html 188 | 189 | 190 | 191 | 192 | 193 | 194 | 204 | 205 | 206 | 207 | ``` 208 | 209 | Keep in mind that the library uses the `request` package, which might not be the most optimized package for web browsers. 210 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webdav-client", 3 | "version": "1.4.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/form-data": { 8 | "version": "2.2.1", 9 | "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", 10 | "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", 11 | "dev": true, 12 | "requires": { 13 | "@types/node": "*" 14 | } 15 | }, 16 | "@types/node": { 17 | "version": "7.0.33", 18 | "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.33.tgz", 19 | "integrity": "sha512-8fVvl6Yyk3jZvSYxRMS9/AmZJ5RXCOP9N4xSlykyBViVESu751pxHYTN14Embn1Fem78YwEHdC7p7KGQQpwunw==", 20 | "dev": true 21 | }, 22 | "@types/request": { 23 | "version": "0.0.46", 24 | "resolved": "https://registry.npmjs.org/@types/request/-/request-0.0.46.tgz", 25 | "integrity": "sha512-DkJItMxIi+Hgwms0TnItekByTqmHEcRkciT+JD9p7V8sUHoegdcSWNgYvrNTLoEIpgnE60dkn2imyOCFapaFkQ==", 26 | "dev": true, 27 | "requires": { 28 | "@types/form-data": "*", 29 | "@types/node": "*" 30 | } 31 | }, 32 | "JSONStream": { 33 | "version": "1.3.5", 34 | "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", 35 | "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", 36 | "requires": { 37 | "jsonparse": "^1.2.0", 38 | "through": ">=2.2.7 <3" 39 | } 40 | }, 41 | "acorn": { 42 | "version": "6.2.1", 43 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", 44 | "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==" 45 | }, 46 | "acorn-dynamic-import": { 47 | "version": "4.0.0", 48 | "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", 49 | "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" 50 | }, 51 | "acorn-node": { 52 | "version": "1.7.0", 53 | "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.7.0.tgz", 54 | "integrity": "sha512-XhahLSsCB6X6CJbe+uNu3Mn9sJBNFxtBN9NLgAOQovfS6Kh0lDUtmlclhjn9CvEK7A7YyRU13PXlNcpSiLI9Yw==", 55 | "requires": { 56 | "acorn": "^6.1.1", 57 | "acorn-dynamic-import": "^4.0.0", 58 | "acorn-walk": "^6.1.1", 59 | "xtend": "^4.0.1" 60 | } 61 | }, 62 | "acorn-walk": { 63 | "version": "6.2.0", 64 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", 65 | "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" 66 | }, 67 | "ajv": { 68 | "version": "6.10.0", 69 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", 70 | "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", 71 | "requires": { 72 | "fast-deep-equal": "^2.0.1", 73 | "fast-json-stable-stringify": "^2.0.0", 74 | "json-schema-traverse": "^0.4.1", 75 | "uri-js": "^4.2.2" 76 | } 77 | }, 78 | "array-filter": { 79 | "version": "0.0.1", 80 | "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", 81 | "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" 82 | }, 83 | "array-map": { 84 | "version": "0.0.0", 85 | "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", 86 | "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" 87 | }, 88 | "array-reduce": { 89 | "version": "0.0.0", 90 | "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", 91 | "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" 92 | }, 93 | "asn1": { 94 | "version": "0.2.4", 95 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 96 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 97 | "requires": { 98 | "safer-buffer": "~2.1.0" 99 | } 100 | }, 101 | "asn1.js": { 102 | "version": "4.10.1", 103 | "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", 104 | "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", 105 | "requires": { 106 | "bn.js": "^4.0.0", 107 | "inherits": "^2.0.1", 108 | "minimalistic-assert": "^1.0.0" 109 | } 110 | }, 111 | "assert": { 112 | "version": "1.5.0", 113 | "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", 114 | "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", 115 | "requires": { 116 | "object-assign": "^4.1.1", 117 | "util": "0.10.3" 118 | }, 119 | "dependencies": { 120 | "inherits": { 121 | "version": "2.0.1", 122 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 123 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 124 | }, 125 | "util": { 126 | "version": "0.10.3", 127 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", 128 | "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", 129 | "requires": { 130 | "inherits": "2.0.1" 131 | } 132 | } 133 | } 134 | }, 135 | "assert-plus": { 136 | "version": "1.0.0", 137 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 138 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 139 | }, 140 | "asynckit": { 141 | "version": "0.4.0", 142 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 143 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 144 | }, 145 | "aws-sign2": { 146 | "version": "0.7.0", 147 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 148 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 149 | }, 150 | "aws4": { 151 | "version": "1.8.0", 152 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 153 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 154 | }, 155 | "balanced-match": { 156 | "version": "1.0.0", 157 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 158 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 159 | }, 160 | "base64-js": { 161 | "version": "1.3.0", 162 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", 163 | "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" 164 | }, 165 | "bcrypt-pbkdf": { 166 | "version": "1.0.2", 167 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 168 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 169 | "requires": { 170 | "tweetnacl": "^0.14.3" 171 | } 172 | }, 173 | "bn.js": { 174 | "version": "4.11.8", 175 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", 176 | "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" 177 | }, 178 | "brace-expansion": { 179 | "version": "1.1.11", 180 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 181 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 182 | "requires": { 183 | "balanced-match": "^1.0.0", 184 | "concat-map": "0.0.1" 185 | } 186 | }, 187 | "brorand": { 188 | "version": "1.1.0", 189 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 190 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" 191 | }, 192 | "browser-pack": { 193 | "version": "6.1.0", 194 | "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", 195 | "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", 196 | "requires": { 197 | "JSONStream": "^1.0.3", 198 | "combine-source-map": "~0.8.0", 199 | "defined": "^1.0.0", 200 | "safe-buffer": "^5.1.1", 201 | "through2": "^2.0.0", 202 | "umd": "^3.0.0" 203 | } 204 | }, 205 | "browser-resolve": { 206 | "version": "1.11.3", 207 | "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", 208 | "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", 209 | "requires": { 210 | "resolve": "1.1.7" 211 | }, 212 | "dependencies": { 213 | "resolve": { 214 | "version": "1.1.7", 215 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 216 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" 217 | } 218 | } 219 | }, 220 | "browserify": { 221 | "version": "16.3.0", 222 | "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.3.0.tgz", 223 | "integrity": "sha512-BWaaD7alyGZVEBBwSTYx4iJF5DswIGzK17o8ai9w4iKRbYpk3EOiprRHMRRA8DCZFmFeOdx7A385w2XdFvxWmg==", 224 | "requires": { 225 | "JSONStream": "^1.0.3", 226 | "assert": "^1.4.0", 227 | "browser-pack": "^6.0.1", 228 | "browser-resolve": "^1.11.0", 229 | "browserify-zlib": "~0.2.0", 230 | "buffer": "^5.0.2", 231 | "cached-path-relative": "^1.0.0", 232 | "concat-stream": "^1.6.0", 233 | "console-browserify": "^1.1.0", 234 | "constants-browserify": "~1.0.0", 235 | "crypto-browserify": "^3.0.0", 236 | "defined": "^1.0.0", 237 | "deps-sort": "^2.0.0", 238 | "domain-browser": "^1.2.0", 239 | "duplexer2": "~0.1.2", 240 | "events": "^2.0.0", 241 | "glob": "^7.1.0", 242 | "has": "^1.0.0", 243 | "htmlescape": "^1.1.0", 244 | "https-browserify": "^1.0.0", 245 | "inherits": "~2.0.1", 246 | "insert-module-globals": "^7.0.0", 247 | "labeled-stream-splicer": "^2.0.0", 248 | "mkdirp": "^0.5.0", 249 | "module-deps": "^6.0.0", 250 | "os-browserify": "~0.3.0", 251 | "parents": "^1.0.1", 252 | "path-browserify": "~0.0.0", 253 | "process": "~0.11.0", 254 | "punycode": "^1.3.2", 255 | "querystring-es3": "~0.2.0", 256 | "read-only-stream": "^2.0.0", 257 | "readable-stream": "^2.0.2", 258 | "resolve": "^1.1.4", 259 | "shasum": "^1.0.0", 260 | "shell-quote": "^1.6.1", 261 | "stream-browserify": "^2.0.0", 262 | "stream-http": "^2.0.0", 263 | "string_decoder": "^1.1.1", 264 | "subarg": "^1.0.0", 265 | "syntax-error": "^1.1.1", 266 | "through2": "^2.0.0", 267 | "timers-browserify": "^1.0.1", 268 | "tty-browserify": "0.0.1", 269 | "url": "~0.11.0", 270 | "util": "~0.10.1", 271 | "vm-browserify": "^1.0.0", 272 | "xtend": "^4.0.0" 273 | }, 274 | "dependencies": { 275 | "punycode": { 276 | "version": "1.4.1", 277 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 278 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 279 | } 280 | } 281 | }, 282 | "browserify-aes": { 283 | "version": "1.2.0", 284 | "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", 285 | "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", 286 | "requires": { 287 | "buffer-xor": "^1.0.3", 288 | "cipher-base": "^1.0.0", 289 | "create-hash": "^1.1.0", 290 | "evp_bytestokey": "^1.0.3", 291 | "inherits": "^2.0.1", 292 | "safe-buffer": "^5.0.1" 293 | } 294 | }, 295 | "browserify-cipher": { 296 | "version": "1.0.1", 297 | "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", 298 | "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", 299 | "requires": { 300 | "browserify-aes": "^1.0.4", 301 | "browserify-des": "^1.0.0", 302 | "evp_bytestokey": "^1.0.0" 303 | } 304 | }, 305 | "browserify-des": { 306 | "version": "1.0.2", 307 | "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", 308 | "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", 309 | "requires": { 310 | "cipher-base": "^1.0.1", 311 | "des.js": "^1.0.0", 312 | "inherits": "^2.0.1", 313 | "safe-buffer": "^5.1.2" 314 | } 315 | }, 316 | "browserify-rsa": { 317 | "version": "4.0.1", 318 | "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", 319 | "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", 320 | "requires": { 321 | "bn.js": "^4.1.0", 322 | "randombytes": "^2.0.1" 323 | } 324 | }, 325 | "browserify-sign": { 326 | "version": "4.0.4", 327 | "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", 328 | "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", 329 | "requires": { 330 | "bn.js": "^4.1.1", 331 | "browserify-rsa": "^4.0.0", 332 | "create-hash": "^1.1.0", 333 | "create-hmac": "^1.1.2", 334 | "elliptic": "^6.0.0", 335 | "inherits": "^2.0.1", 336 | "parse-asn1": "^5.0.0" 337 | } 338 | }, 339 | "browserify-zlib": { 340 | "version": "0.2.0", 341 | "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", 342 | "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", 343 | "requires": { 344 | "pako": "~1.0.5" 345 | } 346 | }, 347 | "buffer": { 348 | "version": "5.2.1", 349 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", 350 | "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", 351 | "requires": { 352 | "base64-js": "^1.0.2", 353 | "ieee754": "^1.1.4" 354 | } 355 | }, 356 | "buffer-from": { 357 | "version": "1.1.1", 358 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 359 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 360 | }, 361 | "buffer-xor": { 362 | "version": "1.0.3", 363 | "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", 364 | "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" 365 | }, 366 | "builtin-status-codes": { 367 | "version": "3.0.0", 368 | "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", 369 | "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" 370 | }, 371 | "cached-path-relative": { 372 | "version": "1.0.2", 373 | "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", 374 | "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" 375 | }, 376 | "caseless": { 377 | "version": "0.12.0", 378 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 379 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 380 | }, 381 | "cipher-base": { 382 | "version": "1.0.4", 383 | "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", 384 | "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", 385 | "requires": { 386 | "inherits": "^2.0.1", 387 | "safe-buffer": "^5.0.1" 388 | } 389 | }, 390 | "combine-source-map": { 391 | "version": "0.8.0", 392 | "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", 393 | "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", 394 | "requires": { 395 | "convert-source-map": "~1.1.0", 396 | "inline-source-map": "~0.6.0", 397 | "lodash.memoize": "~3.0.3", 398 | "source-map": "~0.5.3" 399 | } 400 | }, 401 | "combined-stream": { 402 | "version": "1.0.7", 403 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 404 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 405 | "requires": { 406 | "delayed-stream": "~1.0.0" 407 | } 408 | }, 409 | "concat-map": { 410 | "version": "0.0.1", 411 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 412 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 413 | }, 414 | "concat-stream": { 415 | "version": "1.6.2", 416 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 417 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 418 | "requires": { 419 | "buffer-from": "^1.0.0", 420 | "inherits": "^2.0.3", 421 | "readable-stream": "^2.2.2", 422 | "typedarray": "^0.0.6" 423 | } 424 | }, 425 | "console-browserify": { 426 | "version": "1.1.0", 427 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", 428 | "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", 429 | "requires": { 430 | "date-now": "^0.1.4" 431 | } 432 | }, 433 | "constants-browserify": { 434 | "version": "1.0.0", 435 | "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", 436 | "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" 437 | }, 438 | "convert-source-map": { 439 | "version": "1.1.3", 440 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", 441 | "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" 442 | }, 443 | "core-util-is": { 444 | "version": "1.0.2", 445 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 446 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 447 | }, 448 | "create-ecdh": { 449 | "version": "4.0.3", 450 | "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", 451 | "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", 452 | "requires": { 453 | "bn.js": "^4.1.0", 454 | "elliptic": "^6.0.0" 455 | } 456 | }, 457 | "create-hash": { 458 | "version": "1.2.0", 459 | "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", 460 | "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", 461 | "requires": { 462 | "cipher-base": "^1.0.1", 463 | "inherits": "^2.0.1", 464 | "md5.js": "^1.3.4", 465 | "ripemd160": "^2.0.1", 466 | "sha.js": "^2.4.0" 467 | } 468 | }, 469 | "create-hmac": { 470 | "version": "1.1.7", 471 | "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", 472 | "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", 473 | "requires": { 474 | "cipher-base": "^1.0.3", 475 | "create-hash": "^1.1.0", 476 | "inherits": "^2.0.1", 477 | "ripemd160": "^2.0.0", 478 | "safe-buffer": "^5.0.1", 479 | "sha.js": "^2.4.8" 480 | } 481 | }, 482 | "crypto-browserify": { 483 | "version": "3.12.0", 484 | "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", 485 | "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", 486 | "requires": { 487 | "browserify-cipher": "^1.0.0", 488 | "browserify-sign": "^4.0.0", 489 | "create-ecdh": "^4.0.0", 490 | "create-hash": "^1.1.0", 491 | "create-hmac": "^1.1.0", 492 | "diffie-hellman": "^5.0.0", 493 | "inherits": "^2.0.1", 494 | "pbkdf2": "^3.0.3", 495 | "public-encrypt": "^4.0.0", 496 | "randombytes": "^2.0.0", 497 | "randomfill": "^1.0.3" 498 | } 499 | }, 500 | "dash-ast": { 501 | "version": "1.0.0", 502 | "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", 503 | "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" 504 | }, 505 | "dashdash": { 506 | "version": "1.14.1", 507 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 508 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 509 | "requires": { 510 | "assert-plus": "^1.0.0" 511 | } 512 | }, 513 | "date-now": { 514 | "version": "0.1.4", 515 | "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", 516 | "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" 517 | }, 518 | "defined": { 519 | "version": "1.0.0", 520 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", 521 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" 522 | }, 523 | "delayed-stream": { 524 | "version": "1.0.0", 525 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 526 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 527 | }, 528 | "deps-sort": { 529 | "version": "2.0.0", 530 | "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", 531 | "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", 532 | "requires": { 533 | "JSONStream": "^1.0.3", 534 | "shasum": "^1.0.0", 535 | "subarg": "^1.0.0", 536 | "through2": "^2.0.0" 537 | } 538 | }, 539 | "des.js": { 540 | "version": "1.0.0", 541 | "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", 542 | "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", 543 | "requires": { 544 | "inherits": "^2.0.1", 545 | "minimalistic-assert": "^1.0.0" 546 | } 547 | }, 548 | "detective": { 549 | "version": "5.2.0", 550 | "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", 551 | "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", 552 | "requires": { 553 | "acorn-node": "^1.6.1", 554 | "defined": "^1.0.0", 555 | "minimist": "^1.1.1" 556 | } 557 | }, 558 | "diffie-hellman": { 559 | "version": "5.0.3", 560 | "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", 561 | "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", 562 | "requires": { 563 | "bn.js": "^4.1.0", 564 | "miller-rabin": "^4.0.0", 565 | "randombytes": "^2.0.0" 566 | } 567 | }, 568 | "domain-browser": { 569 | "version": "1.2.0", 570 | "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", 571 | "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" 572 | }, 573 | "duplexer2": { 574 | "version": "0.1.4", 575 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", 576 | "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", 577 | "requires": { 578 | "readable-stream": "^2.0.2" 579 | } 580 | }, 581 | "ecc-jsbn": { 582 | "version": "0.1.2", 583 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 584 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 585 | "requires": { 586 | "jsbn": "~0.1.0", 587 | "safer-buffer": "^2.1.0" 588 | } 589 | }, 590 | "elliptic": { 591 | "version": "6.5.0", 592 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", 593 | "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", 594 | "requires": { 595 | "bn.js": "^4.4.0", 596 | "brorand": "^1.0.1", 597 | "hash.js": "^1.0.0", 598 | "hmac-drbg": "^1.0.0", 599 | "inherits": "^2.0.1", 600 | "minimalistic-assert": "^1.0.0", 601 | "minimalistic-crypto-utils": "^1.0.0" 602 | } 603 | }, 604 | "events": { 605 | "version": "2.1.0", 606 | "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", 607 | "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" 608 | }, 609 | "evp_bytestokey": { 610 | "version": "1.0.3", 611 | "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", 612 | "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", 613 | "requires": { 614 | "md5.js": "^1.3.4", 615 | "safe-buffer": "^5.1.1" 616 | } 617 | }, 618 | "extend": { 619 | "version": "3.0.2", 620 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 621 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 622 | }, 623 | "extsprintf": { 624 | "version": "1.3.0", 625 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 626 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 627 | }, 628 | "fast-deep-equal": { 629 | "version": "2.0.1", 630 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 631 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" 632 | }, 633 | "fast-json-stable-stringify": { 634 | "version": "2.0.0", 635 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 636 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 637 | }, 638 | "forever-agent": { 639 | "version": "0.6.1", 640 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 641 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 642 | }, 643 | "form-data": { 644 | "version": "3.0.0", 645 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", 646 | "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", 647 | "requires": { 648 | "asynckit": "^0.4.0", 649 | "combined-stream": "^1.0.8", 650 | "mime-types": "^2.1.12" 651 | }, 652 | "dependencies": { 653 | "combined-stream": { 654 | "version": "1.0.8", 655 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 656 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 657 | "requires": { 658 | "delayed-stream": "~1.0.0" 659 | } 660 | } 661 | } 662 | }, 663 | "fs.realpath": { 664 | "version": "1.0.0", 665 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 666 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 667 | }, 668 | "function-bind": { 669 | "version": "1.1.1", 670 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 671 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 672 | }, 673 | "get-assigned-identifiers": { 674 | "version": "1.2.0", 675 | "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", 676 | "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" 677 | }, 678 | "getpass": { 679 | "version": "0.1.7", 680 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 681 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 682 | "requires": { 683 | "assert-plus": "^1.0.0" 684 | } 685 | }, 686 | "glob": { 687 | "version": "7.1.4", 688 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 689 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 690 | "requires": { 691 | "fs.realpath": "^1.0.0", 692 | "inflight": "^1.0.4", 693 | "inherits": "2", 694 | "minimatch": "^3.0.4", 695 | "once": "^1.3.0", 696 | "path-is-absolute": "^1.0.0" 697 | } 698 | }, 699 | "har-schema": { 700 | "version": "2.0.0", 701 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 702 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 703 | }, 704 | "har-validator": { 705 | "version": "5.1.3", 706 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 707 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 708 | "requires": { 709 | "ajv": "^6.5.5", 710 | "har-schema": "^2.0.0" 711 | } 712 | }, 713 | "has": { 714 | "version": "1.0.3", 715 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 716 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 717 | "requires": { 718 | "function-bind": "^1.1.1" 719 | } 720 | }, 721 | "hash-base": { 722 | "version": "3.0.4", 723 | "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", 724 | "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", 725 | "requires": { 726 | "inherits": "^2.0.1", 727 | "safe-buffer": "^5.0.1" 728 | } 729 | }, 730 | "hash.js": { 731 | "version": "1.1.7", 732 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 733 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 734 | "requires": { 735 | "inherits": "^2.0.3", 736 | "minimalistic-assert": "^1.0.1" 737 | } 738 | }, 739 | "hmac-drbg": { 740 | "version": "1.0.1", 741 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 742 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 743 | "requires": { 744 | "hash.js": "^1.0.3", 745 | "minimalistic-assert": "^1.0.0", 746 | "minimalistic-crypto-utils": "^1.0.1" 747 | } 748 | }, 749 | "htmlescape": { 750 | "version": "1.1.1", 751 | "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", 752 | "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" 753 | }, 754 | "http-signature": { 755 | "version": "1.2.0", 756 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 757 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 758 | "requires": { 759 | "assert-plus": "^1.0.0", 760 | "jsprim": "^1.2.2", 761 | "sshpk": "^1.7.0" 762 | } 763 | }, 764 | "https-browserify": { 765 | "version": "1.0.0", 766 | "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", 767 | "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" 768 | }, 769 | "ieee754": { 770 | "version": "1.1.13", 771 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 772 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 773 | }, 774 | "inflight": { 775 | "version": "1.0.6", 776 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 777 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 778 | "requires": { 779 | "once": "^1.3.0", 780 | "wrappy": "1" 781 | } 782 | }, 783 | "inherits": { 784 | "version": "2.0.4", 785 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 786 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 787 | }, 788 | "inline-source-map": { 789 | "version": "0.6.2", 790 | "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", 791 | "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", 792 | "requires": { 793 | "source-map": "~0.5.3" 794 | } 795 | }, 796 | "insert-module-globals": { 797 | "version": "7.2.0", 798 | "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", 799 | "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", 800 | "requires": { 801 | "JSONStream": "^1.0.3", 802 | "acorn-node": "^1.5.2", 803 | "combine-source-map": "^0.8.0", 804 | "concat-stream": "^1.6.1", 805 | "is-buffer": "^1.1.0", 806 | "path-is-absolute": "^1.0.1", 807 | "process": "~0.11.0", 808 | "through2": "^2.0.0", 809 | "undeclared-identifiers": "^1.1.2", 810 | "xtend": "^4.0.0" 811 | } 812 | }, 813 | "is-buffer": { 814 | "version": "1.1.6", 815 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 816 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 817 | }, 818 | "is-typedarray": { 819 | "version": "1.0.0", 820 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 821 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 822 | }, 823 | "isarray": { 824 | "version": "1.0.0", 825 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 826 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 827 | }, 828 | "isstream": { 829 | "version": "0.1.2", 830 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 831 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 832 | }, 833 | "jsbn": { 834 | "version": "0.1.1", 835 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 836 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 837 | }, 838 | "json-schema": { 839 | "version": "0.2.3", 840 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 841 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 842 | }, 843 | "json-schema-traverse": { 844 | "version": "0.4.1", 845 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 846 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 847 | }, 848 | "json-stable-stringify": { 849 | "version": "0.0.1", 850 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", 851 | "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", 852 | "requires": { 853 | "jsonify": "~0.0.0" 854 | } 855 | }, 856 | "json-stringify-safe": { 857 | "version": "5.0.1", 858 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 859 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 860 | }, 861 | "jsonify": { 862 | "version": "0.0.0", 863 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 864 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" 865 | }, 866 | "jsonparse": { 867 | "version": "1.3.1", 868 | "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", 869 | "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" 870 | }, 871 | "jsprim": { 872 | "version": "1.4.1", 873 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 874 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 875 | "requires": { 876 | "assert-plus": "1.0.0", 877 | "extsprintf": "1.3.0", 878 | "json-schema": "0.2.3", 879 | "verror": "1.10.0" 880 | } 881 | }, 882 | "labeled-stream-splicer": { 883 | "version": "2.0.2", 884 | "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", 885 | "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", 886 | "requires": { 887 | "inherits": "^2.0.1", 888 | "stream-splicer": "^2.0.0" 889 | } 890 | }, 891 | "lodash.memoize": { 892 | "version": "3.0.4", 893 | "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", 894 | "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" 895 | }, 896 | "lodash.uniqby": { 897 | "version": "4.7.0", 898 | "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", 899 | "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=" 900 | }, 901 | "md5.js": { 902 | "version": "1.3.5", 903 | "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", 904 | "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", 905 | "requires": { 906 | "hash-base": "^3.0.0", 907 | "inherits": "^2.0.1", 908 | "safe-buffer": "^5.1.2" 909 | } 910 | }, 911 | "miller-rabin": { 912 | "version": "4.0.1", 913 | "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", 914 | "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", 915 | "requires": { 916 | "bn.js": "^4.0.0", 917 | "brorand": "^1.0.1" 918 | } 919 | }, 920 | "mime-db": { 921 | "version": "1.40.0", 922 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 923 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 924 | }, 925 | "mime-types": { 926 | "version": "2.1.24", 927 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 928 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 929 | "requires": { 930 | "mime-db": "1.40.0" 931 | } 932 | }, 933 | "minimalistic-assert": { 934 | "version": "1.0.1", 935 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 936 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 937 | }, 938 | "minimalistic-crypto-utils": { 939 | "version": "1.0.1", 940 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 941 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 942 | }, 943 | "minimatch": { 944 | "version": "3.0.4", 945 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 946 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 947 | "requires": { 948 | "brace-expansion": "^1.1.7" 949 | } 950 | }, 951 | "minimist": { 952 | "version": "1.2.0", 953 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 954 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 955 | }, 956 | "mkdirp": { 957 | "version": "0.5.1", 958 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 959 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 960 | "requires": { 961 | "minimist": "0.0.8" 962 | }, 963 | "dependencies": { 964 | "minimist": { 965 | "version": "0.0.8", 966 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 967 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 968 | } 969 | } 970 | }, 971 | "module-deps": { 972 | "version": "6.2.1", 973 | "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.1.tgz", 974 | "integrity": "sha512-UnEn6Ah36Tu4jFiBbJVUtt0h+iXqxpLqDvPS8nllbw5RZFmNJ1+Mz5BjYnM9ieH80zyxHkARGLnMIHlPK5bu6A==", 975 | "requires": { 976 | "JSONStream": "^1.0.3", 977 | "browser-resolve": "^1.7.0", 978 | "cached-path-relative": "^1.0.2", 979 | "concat-stream": "~1.6.0", 980 | "defined": "^1.0.0", 981 | "detective": "^5.0.2", 982 | "duplexer2": "^0.1.2", 983 | "inherits": "^2.0.1", 984 | "parents": "^1.0.0", 985 | "readable-stream": "^2.0.2", 986 | "resolve": "^1.4.0", 987 | "stream-combiner2": "^1.1.1", 988 | "subarg": "^1.0.0", 989 | "through2": "^2.0.0", 990 | "xtend": "^4.0.0" 991 | } 992 | }, 993 | "oauth-sign": { 994 | "version": "0.9.0", 995 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 996 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 997 | }, 998 | "object-assign": { 999 | "version": "4.1.1", 1000 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1001 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1002 | }, 1003 | "once": { 1004 | "version": "1.4.0", 1005 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1006 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1007 | "requires": { 1008 | "wrappy": "1" 1009 | } 1010 | }, 1011 | "os-browserify": { 1012 | "version": "0.3.0", 1013 | "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", 1014 | "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" 1015 | }, 1016 | "pako": { 1017 | "version": "1.0.10", 1018 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", 1019 | "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" 1020 | }, 1021 | "parents": { 1022 | "version": "1.0.1", 1023 | "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", 1024 | "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", 1025 | "requires": { 1026 | "path-platform": "~0.11.15" 1027 | } 1028 | }, 1029 | "parse-asn1": { 1030 | "version": "5.1.4", 1031 | "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", 1032 | "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", 1033 | "requires": { 1034 | "asn1.js": "^4.0.0", 1035 | "browserify-aes": "^1.0.0", 1036 | "create-hash": "^1.1.0", 1037 | "evp_bytestokey": "^1.0.0", 1038 | "pbkdf2": "^3.0.3", 1039 | "safe-buffer": "^5.1.1" 1040 | } 1041 | }, 1042 | "path-browserify": { 1043 | "version": "0.0.1", 1044 | "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", 1045 | "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" 1046 | }, 1047 | "path-is-absolute": { 1048 | "version": "1.0.1", 1049 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1050 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1051 | }, 1052 | "path-parse": { 1053 | "version": "1.0.6", 1054 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1055 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 1056 | }, 1057 | "path-platform": { 1058 | "version": "0.11.15", 1059 | "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", 1060 | "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" 1061 | }, 1062 | "pbkdf2": { 1063 | "version": "3.0.17", 1064 | "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", 1065 | "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", 1066 | "requires": { 1067 | "create-hash": "^1.1.2", 1068 | "create-hmac": "^1.1.4", 1069 | "ripemd160": "^2.0.1", 1070 | "safe-buffer": "^5.0.1", 1071 | "sha.js": "^2.4.8" 1072 | } 1073 | }, 1074 | "performance-now": { 1075 | "version": "2.1.0", 1076 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1077 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1078 | }, 1079 | "process": { 1080 | "version": "0.11.10", 1081 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 1082 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" 1083 | }, 1084 | "process-nextick-args": { 1085 | "version": "2.0.1", 1086 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1087 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1088 | }, 1089 | "psl": { 1090 | "version": "1.1.31", 1091 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", 1092 | "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" 1093 | }, 1094 | "public-encrypt": { 1095 | "version": "4.0.3", 1096 | "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", 1097 | "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", 1098 | "requires": { 1099 | "bn.js": "^4.1.0", 1100 | "browserify-rsa": "^4.0.0", 1101 | "create-hash": "^1.1.0", 1102 | "parse-asn1": "^5.0.0", 1103 | "randombytes": "^2.0.1", 1104 | "safe-buffer": "^5.1.2" 1105 | } 1106 | }, 1107 | "punycode": { 1108 | "version": "2.1.1", 1109 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1110 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 1111 | }, 1112 | "qs": { 1113 | "version": "6.5.2", 1114 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1115 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 1116 | }, 1117 | "querystring": { 1118 | "version": "0.2.0", 1119 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1120 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1121 | }, 1122 | "querystring-es3": { 1123 | "version": "0.2.1", 1124 | "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", 1125 | "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" 1126 | }, 1127 | "randombytes": { 1128 | "version": "2.1.0", 1129 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1130 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1131 | "requires": { 1132 | "safe-buffer": "^5.1.0" 1133 | } 1134 | }, 1135 | "randomfill": { 1136 | "version": "1.0.4", 1137 | "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", 1138 | "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", 1139 | "requires": { 1140 | "randombytes": "^2.0.5", 1141 | "safe-buffer": "^5.1.0" 1142 | } 1143 | }, 1144 | "read-only-stream": { 1145 | "version": "2.0.0", 1146 | "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", 1147 | "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", 1148 | "requires": { 1149 | "readable-stream": "^2.0.2" 1150 | } 1151 | }, 1152 | "readable-stream": { 1153 | "version": "2.3.6", 1154 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1155 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1156 | "requires": { 1157 | "core-util-is": "~1.0.0", 1158 | "inherits": "~2.0.3", 1159 | "isarray": "~1.0.0", 1160 | "process-nextick-args": "~2.0.0", 1161 | "safe-buffer": "~5.1.1", 1162 | "string_decoder": "~1.1.1", 1163 | "util-deprecate": "~1.0.1" 1164 | }, 1165 | "dependencies": { 1166 | "string_decoder": { 1167 | "version": "1.1.1", 1168 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1169 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1170 | "requires": { 1171 | "safe-buffer": "~5.1.0" 1172 | } 1173 | } 1174 | } 1175 | }, 1176 | "request": { 1177 | "version": "2.88.0", 1178 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1179 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1180 | "requires": { 1181 | "aws-sign2": "~0.7.0", 1182 | "aws4": "^1.8.0", 1183 | "caseless": "~0.12.0", 1184 | "combined-stream": "~1.0.6", 1185 | "extend": "~3.0.2", 1186 | "forever-agent": "~0.6.1", 1187 | "form-data": "~2.3.2", 1188 | "har-validator": "~5.1.0", 1189 | "http-signature": "~1.2.0", 1190 | "is-typedarray": "~1.0.0", 1191 | "isstream": "~0.1.2", 1192 | "json-stringify-safe": "~5.0.1", 1193 | "mime-types": "~2.1.19", 1194 | "oauth-sign": "~0.9.0", 1195 | "performance-now": "^2.1.0", 1196 | "qs": "~6.5.2", 1197 | "safe-buffer": "^5.1.2", 1198 | "tough-cookie": "~2.4.3", 1199 | "tunnel-agent": "^0.6.0", 1200 | "uuid": "^3.3.2" 1201 | }, 1202 | "dependencies": { 1203 | "form-data": { 1204 | "version": "2.3.3", 1205 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 1206 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 1207 | "requires": { 1208 | "asynckit": "^0.4.0", 1209 | "combined-stream": "^1.0.6", 1210 | "mime-types": "^2.1.12" 1211 | } 1212 | } 1213 | } 1214 | }, 1215 | "resolve": { 1216 | "version": "1.12.0", 1217 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", 1218 | "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", 1219 | "requires": { 1220 | "path-parse": "^1.0.6" 1221 | } 1222 | }, 1223 | "ripemd160": { 1224 | "version": "2.0.2", 1225 | "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", 1226 | "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", 1227 | "requires": { 1228 | "hash-base": "^3.0.0", 1229 | "inherits": "^2.0.1" 1230 | } 1231 | }, 1232 | "safe-buffer": { 1233 | "version": "5.1.2", 1234 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1235 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1236 | }, 1237 | "safer-buffer": { 1238 | "version": "2.1.2", 1239 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1240 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1241 | }, 1242 | "sax": { 1243 | "version": "1.2.4", 1244 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1245 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1246 | }, 1247 | "sha.js": { 1248 | "version": "2.4.11", 1249 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 1250 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 1251 | "requires": { 1252 | "inherits": "^2.0.1", 1253 | "safe-buffer": "^5.0.1" 1254 | } 1255 | }, 1256 | "shasum": { 1257 | "version": "1.0.2", 1258 | "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", 1259 | "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", 1260 | "requires": { 1261 | "json-stable-stringify": "~0.0.0", 1262 | "sha.js": "~2.4.4" 1263 | } 1264 | }, 1265 | "shell-quote": { 1266 | "version": "1.6.1", 1267 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", 1268 | "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", 1269 | "requires": { 1270 | "array-filter": "~0.0.0", 1271 | "array-map": "~0.0.0", 1272 | "array-reduce": "~0.0.0", 1273 | "jsonify": "~0.0.0" 1274 | } 1275 | }, 1276 | "simple-concat": { 1277 | "version": "1.0.0", 1278 | "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", 1279 | "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" 1280 | }, 1281 | "source-map": { 1282 | "version": "0.5.7", 1283 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1284 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 1285 | }, 1286 | "sshpk": { 1287 | "version": "1.16.1", 1288 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1289 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1290 | "requires": { 1291 | "asn1": "~0.2.3", 1292 | "assert-plus": "^1.0.0", 1293 | "bcrypt-pbkdf": "^1.0.0", 1294 | "dashdash": "^1.12.0", 1295 | "ecc-jsbn": "~0.1.1", 1296 | "getpass": "^0.1.1", 1297 | "jsbn": "~0.1.0", 1298 | "safer-buffer": "^2.0.2", 1299 | "tweetnacl": "~0.14.0" 1300 | } 1301 | }, 1302 | "stream-browserify": { 1303 | "version": "2.0.2", 1304 | "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", 1305 | "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", 1306 | "requires": { 1307 | "inherits": "~2.0.1", 1308 | "readable-stream": "^2.0.2" 1309 | } 1310 | }, 1311 | "stream-combiner2": { 1312 | "version": "1.1.1", 1313 | "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", 1314 | "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", 1315 | "requires": { 1316 | "duplexer2": "~0.1.0", 1317 | "readable-stream": "^2.0.2" 1318 | } 1319 | }, 1320 | "stream-http": { 1321 | "version": "2.8.3", 1322 | "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", 1323 | "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", 1324 | "requires": { 1325 | "builtin-status-codes": "^3.0.0", 1326 | "inherits": "^2.0.1", 1327 | "readable-stream": "^2.3.6", 1328 | "to-arraybuffer": "^1.0.0", 1329 | "xtend": "^4.0.0" 1330 | } 1331 | }, 1332 | "stream-splicer": { 1333 | "version": "2.0.1", 1334 | "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", 1335 | "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", 1336 | "requires": { 1337 | "inherits": "^2.0.1", 1338 | "readable-stream": "^2.0.2" 1339 | } 1340 | }, 1341 | "string_decoder": { 1342 | "version": "1.2.0", 1343 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", 1344 | "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", 1345 | "requires": { 1346 | "safe-buffer": "~5.1.0" 1347 | } 1348 | }, 1349 | "subarg": { 1350 | "version": "1.0.0", 1351 | "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", 1352 | "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", 1353 | "requires": { 1354 | "minimist": "^1.1.0" 1355 | } 1356 | }, 1357 | "syntax-error": { 1358 | "version": "1.4.0", 1359 | "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", 1360 | "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", 1361 | "requires": { 1362 | "acorn-node": "^1.2.0" 1363 | } 1364 | }, 1365 | "through": { 1366 | "version": "2.3.8", 1367 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1368 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 1369 | }, 1370 | "through2": { 1371 | "version": "2.0.5", 1372 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 1373 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 1374 | "requires": { 1375 | "readable-stream": "~2.3.6", 1376 | "xtend": "~4.0.1" 1377 | } 1378 | }, 1379 | "timers-browserify": { 1380 | "version": "1.4.2", 1381 | "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", 1382 | "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", 1383 | "requires": { 1384 | "process": "~0.11.0" 1385 | } 1386 | }, 1387 | "to-arraybuffer": { 1388 | "version": "1.0.1", 1389 | "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", 1390 | "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" 1391 | }, 1392 | "tough-cookie": { 1393 | "version": "2.4.3", 1394 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1395 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1396 | "requires": { 1397 | "psl": "^1.1.24", 1398 | "punycode": "^1.4.1" 1399 | }, 1400 | "dependencies": { 1401 | "punycode": { 1402 | "version": "1.4.1", 1403 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1404 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1405 | } 1406 | } 1407 | }, 1408 | "tty-browserify": { 1409 | "version": "0.0.1", 1410 | "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", 1411 | "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" 1412 | }, 1413 | "tunnel-agent": { 1414 | "version": "0.6.0", 1415 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1416 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1417 | "requires": { 1418 | "safe-buffer": "^5.0.1" 1419 | } 1420 | }, 1421 | "tweetnacl": { 1422 | "version": "0.14.5", 1423 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1424 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 1425 | }, 1426 | "typedarray": { 1427 | "version": "0.0.6", 1428 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1429 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" 1430 | }, 1431 | "typescript": { 1432 | "version": "3.5.3", 1433 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", 1434 | "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==" 1435 | }, 1436 | "umd": { 1437 | "version": "3.0.3", 1438 | "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", 1439 | "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" 1440 | }, 1441 | "undeclared-identifiers": { 1442 | "version": "1.1.3", 1443 | "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", 1444 | "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", 1445 | "requires": { 1446 | "acorn-node": "^1.3.0", 1447 | "dash-ast": "^1.0.0", 1448 | "get-assigned-identifiers": "^1.2.0", 1449 | "simple-concat": "^1.0.0", 1450 | "xtend": "^4.0.1" 1451 | } 1452 | }, 1453 | "uri-js": { 1454 | "version": "4.2.2", 1455 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1456 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1457 | "requires": { 1458 | "punycode": "^2.1.0" 1459 | } 1460 | }, 1461 | "url": { 1462 | "version": "0.11.0", 1463 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 1464 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 1465 | "requires": { 1466 | "punycode": "1.3.2", 1467 | "querystring": "0.2.0" 1468 | }, 1469 | "dependencies": { 1470 | "punycode": { 1471 | "version": "1.3.2", 1472 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1473 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 1474 | } 1475 | } 1476 | }, 1477 | "util": { 1478 | "version": "0.10.4", 1479 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", 1480 | "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", 1481 | "requires": { 1482 | "inherits": "2.0.3" 1483 | }, 1484 | "dependencies": { 1485 | "inherits": { 1486 | "version": "2.0.3", 1487 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1488 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1489 | } 1490 | } 1491 | }, 1492 | "util-deprecate": { 1493 | "version": "1.0.2", 1494 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1495 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1496 | }, 1497 | "uuid": { 1498 | "version": "3.3.2", 1499 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1500 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 1501 | }, 1502 | "verror": { 1503 | "version": "1.10.0", 1504 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1505 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1506 | "requires": { 1507 | "assert-plus": "^1.0.0", 1508 | "core-util-is": "1.0.2", 1509 | "extsprintf": "^1.2.0" 1510 | } 1511 | }, 1512 | "vm-browserify": { 1513 | "version": "1.1.0", 1514 | "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", 1515 | "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==" 1516 | }, 1517 | "webdav-server": { 1518 | "version": "2.4.6", 1519 | "resolved": "https://registry.npmjs.org/webdav-server/-/webdav-server-2.4.6.tgz", 1520 | "integrity": "sha512-YhqjqlQdD4H55UEnRgk99a9epTuulKMW05m6KBTtG6fBXcc4/2H87F2DRJHH7a33PibNn3jWv8u9AgcMHLGUrw==", 1521 | "dev": true, 1522 | "requires": { 1523 | "mime-types": "^2.1.18", 1524 | "xml-js-builder": "^1.0.3" 1525 | } 1526 | }, 1527 | "wrappy": { 1528 | "version": "1.0.2", 1529 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1530 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1531 | }, 1532 | "xml-js": { 1533 | "version": "1.6.11", 1534 | "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", 1535 | "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", 1536 | "requires": { 1537 | "sax": "^1.2.4" 1538 | } 1539 | }, 1540 | "xml-js-builder": { 1541 | "version": "1.0.3", 1542 | "resolved": "https://registry.npmjs.org/xml-js-builder/-/xml-js-builder-1.0.3.tgz", 1543 | "integrity": "sha512-BoLgG/glT45M0jK5PGh9h+iGrQxa8jJk9ofR63GroRifl2tbGB3/yYiVY3wQWHrZgWWfl9+7fhEB/VoD9mWnSg==", 1544 | "requires": { 1545 | "xml-js": "^1.6.2" 1546 | } 1547 | }, 1548 | "xtend": { 1549 | "version": "4.0.2", 1550 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1551 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1552 | } 1553 | } 1554 | } 1555 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "engines": { 3 | "node": ">= 4" 4 | }, 5 | "main": "./lib/index", 6 | "keywords": [ 7 | "webdav-client", 8 | "webdav", 9 | "client" 10 | ], 11 | "scripts": { 12 | "prepare": "npm run build && npm run browserify", 13 | "dev": "cd src && tsc -w", 14 | "browserify": "browserify lib/browser.js > lib/browserified.js", 15 | "build": "cd src && tsc", 16 | "test": "node test/test.js" 17 | }, 18 | "name": "webdav-client", 19 | "version": "1.4.3", 20 | "author": "Adrien Castex ", 21 | "license": "Unlicense", 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/OpenMarshal/npm-WebDAV-Client.git" 25 | }, 26 | "description": "WebDAV Client", 27 | "devDependencies": { 28 | "@types/node": "^7.0.33", 29 | "@types/request": "0.0.46", 30 | "webdav-server": "^2.2.3" 31 | }, 32 | "types": "./lib/index.d.ts", 33 | "dependencies": { 34 | "browserify": "^16.3.0", 35 | "form-data": "^3.0.0", 36 | "lodash.uniqby": "^4.7.0", 37 | "request": "^2.81.0", 38 | "typescript": "^3.5.3", 39 | "xml-js-builder": "^1.0.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/browser.ts: -------------------------------------------------------------------------------- 1 | (window as any).webdavClient = require('./index.js'); 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from 'crypto'; 2 | import * as uniqBy from 'lodash.uniqby'; 3 | import * as Path from 'path'; 4 | import * as Url from 'url'; 5 | 6 | import { 7 | XML, 8 | XMLElement, 9 | XMLElementBuilder, 10 | XMLElementUtil 11 | } from 'xml-js-builder'; 12 | 13 | import { 14 | request, 15 | stream, 16 | Stream, 17 | RequestOptions, 18 | Response, 19 | ContentType, 20 | ResponseCallback 21 | } from './request'; 22 | 23 | export * from './request'; 24 | 25 | export interface Properties 26 | { 27 | [name : string] : { 28 | attributes ?: { 29 | [name : string] : string 30 | } 31 | content ?: string | XMLElement[] 32 | } 33 | } 34 | 35 | export class HTTPError extends Error 36 | { 37 | statusMessage : string 38 | statusCode : number 39 | 40 | constructor(res : Response) 41 | { 42 | super('HTTP error : ' + res.statusCode + ' - ' + res.statusMessage); 43 | 44 | this.statusMessage = res.statusMessage; 45 | this.statusCode = res.statusCode; 46 | } 47 | } 48 | 49 | export interface Lock 50 | { 51 | uid : string 52 | } 53 | 54 | export interface AuthenticatorInformation 55 | { 56 | lastResponse : Response 57 | request : RequestOptions 58 | username : string 59 | password : string 60 | } 61 | 62 | export interface Authenticator 63 | { 64 | getAuthenticationHeader(info : AuthenticatorInformation) : string 65 | isValidResponse(response : Response) : boolean 66 | } 67 | 68 | export interface ConnectionReaddirComplexResult 69 | { 70 | creationDate : Date 71 | lastModified : Date 72 | isDirectory : boolean 73 | isFile : boolean 74 | type : 'directory' | 'file' 75 | size : number 76 | href : string 77 | name : string 78 | extraProperties: { 79 | [name : string] : string | number | boolean 80 | } 81 | } 82 | export interface ConnectionReaddirOptions 83 | { 84 | properties ?: boolean 85 | extraProperties: ConnectionReaddirProperty[] 86 | } 87 | 88 | export interface ConnectionReaddirProperty 89 | { 90 | namespace: string 91 | namespaceShort: string 92 | element: string 93 | default?: any 94 | nativeType?: boolean 95 | } 96 | 97 | export class DigestAuthenticator implements Authenticator 98 | { 99 | md5(value : string) : string 100 | { 101 | return crypto.createHash('md5').update(value).digest('hex'); 102 | } 103 | 104 | find(info : AuthenticatorInformation, rex : RegExp, defaultValue ?: string) : string 105 | { 106 | const auth = info.lastResponse.headers['www-authenticate'] as string; 107 | if(!auth) 108 | return defaultValue; 109 | 110 | const value = rex.exec(auth); 111 | if(!value[1]) 112 | return defaultValue; 113 | 114 | return value[1]; 115 | } 116 | 117 | getRealm(info : AuthenticatorInformation) : string 118 | { 119 | return this.find(info, /[^a-zA-Z0-9-_]realm="([^"]+)"/); 120 | } 121 | 122 | getNonce(info : AuthenticatorInformation) : string 123 | { 124 | return this.find(info, /[^a-zA-Z0-9-_]nonce="([^"]+)"/); 125 | } 126 | 127 | getAuthenticationHeader(info : AuthenticatorInformation) : string 128 | { 129 | const realm = this.getRealm(info); 130 | const nonce = this.getNonce(info); 131 | let url = info.request.url; 132 | if(url.indexOf('://') !== -1) 133 | { 134 | url = url.substring(url.indexOf('://') + 3); 135 | url = url.substring(url.indexOf('/')); 136 | } 137 | 138 | if(!realm || !nonce) 139 | return undefined; 140 | 141 | const ha1 = this.md5(info.username + ':' + realm + ':' + (info.password ? info.password : '')); 142 | const ha2 = this.md5(info.request.method + ':' + url); 143 | const response = this.md5(ha1 + ':' + nonce + ':' + ha2); 144 | 145 | return 'Digest username="' + info.username + '",realm="' + realm + '",nonce="' + nonce + '",uri="' + url + '",response="' + response + '"'; 146 | } 147 | 148 | isValidResponse(response : Response) : boolean 149 | { 150 | return response && response.headers && !!response.headers['www-authenticate']; 151 | } 152 | } 153 | 154 | export class BasicAuthenticator implements Authenticator 155 | { 156 | getAuthenticationHeader(info : AuthenticatorInformation) : string 157 | { 158 | return 'Basic ' + Buffer.from(info.username + ':' + (info.password ? info.password : '')).toString('base64'); 159 | } 160 | 161 | isValidResponse() : boolean 162 | { 163 | return true; 164 | } 165 | } 166 | 167 | export interface ConnectionOptions 168 | { 169 | url : string 170 | authenticator ?: Authenticator 171 | username ?: string 172 | password ?: string 173 | } 174 | 175 | export class Connection 176 | { 177 | options : ConnectionOptions 178 | lastAuthValidResponse : Response 179 | 180 | private root : string 181 | 182 | constructor(url : string) 183 | constructor(options : ConnectionOptions) 184 | constructor(options : string | ConnectionOptions) 185 | { 186 | if(options.constructor === String) 187 | options = { url: options as string }; 188 | this.options = options as ConnectionOptions; 189 | 190 | if(this.options.url.lastIndexOf('/') === this.options.url.length - 1) 191 | this.options.url = this.options.url.substring(0, this.options.url.length - 1); 192 | 193 | this.root = Url.parse(this.options.url).pathname; 194 | 195 | if (this.root.slice(-1)[0] !== '/') { 196 | this.root += '/'; 197 | } 198 | } 199 | 200 | protected wrapRequestOptions(options : RequestOptions, lastResponse ?: Response) : RequestOptions 201 | { 202 | if(!options.headers) 203 | options.headers = {}; 204 | 205 | if(this.options.authenticator) 206 | { 207 | if(this.options.authenticator.isValidResponse(lastResponse)) 208 | this.lastAuthValidResponse = lastResponse; 209 | else 210 | lastResponse = this.lastAuthValidResponse; 211 | 212 | if(this.options.authenticator.isValidResponse(lastResponse)) 213 | { 214 | options.headers['authorization'] = this.options.authenticator.getAuthenticationHeader({ 215 | password: this.options.password, 216 | username: this.options.username, 217 | request: options, 218 | lastResponse 219 | }); 220 | } 221 | } 222 | 223 | if(options.url.indexOf(this.options.url) !== 0) 224 | options.url = this.options.url + options.url; 225 | return options; 226 | } 227 | request(options : RequestOptions, callback : ResponseCallback, lastResponse ?: Response) 228 | { 229 | request(this.wrapRequestOptions(options, lastResponse), (e, res, body) => { 230 | if(this.options.authenticator && this.options.authenticator.isValidResponse(res)) 231 | this.lastAuthValidResponse = res; 232 | 233 | if(lastResponse || e || res && res.statusCode !== 401 || !this.options.authenticator) 234 | return callback(e, res, body); 235 | 236 | this.request(options, callback, res); 237 | }); 238 | } 239 | stream(options : RequestOptions, lastResponse ?: Response) : Stream 240 | { 241 | return stream(this.wrapRequestOptions(options, lastResponse)); 242 | } 243 | protected noBodyRequest(options : RequestOptions, callback : (error ?: Error) => void) : void 244 | { 245 | this.request(options, (e, res, body) => { 246 | if(e) 247 | return callback(e); 248 | if(res.statusCode >= 400) 249 | return callback(new HTTPError(res)); 250 | 251 | callback(); 252 | }) 253 | } 254 | 255 | prepareForStreaming(path : string, callback : (error ?: Error) => void) : void 256 | prepareForStreaming(callback : (error ?: Error) => void) : void 257 | prepareForStreaming(_path : string | ((error ?: Error) => void), _callback ?: (error ?: Error) => void) : void 258 | { 259 | const path = _callback ? _path as string : '/'; 260 | const callback = _callback ? _callback : _path as (error ?: Error) => void; 261 | 262 | this.request({ 263 | url: path, 264 | method: 'PROPFIND' 265 | }, (e, res, body) => { 266 | if(e) 267 | return callback(e); 268 | if(res.statusCode >= 400) 269 | return callback(new HTTPError(res)); 270 | 271 | if(this.options.authenticator && this.options.authenticator.isValidResponse(res)) 272 | this.lastAuthValidResponse = res; 273 | 274 | callback(); 275 | }) 276 | } 277 | 278 | exists(path : string, callback : (error : Error, exists : boolean) => void) : void 279 | { 280 | this.request({ 281 | url: path, 282 | method: 'PROPFIND', 283 | headers: { 284 | depth: '0' 285 | } 286 | }, (e, res, body) => { 287 | callback(e, res.statusCode <= 400); 288 | }) 289 | } 290 | 291 | get(path : string, callback : (error ?: Error, body ?: ContentType) => void) : void 292 | get(path : string) : Stream 293 | get(path : string, callback ?: (error ?: Error, body ?: ContentType) => void) : Stream 294 | { 295 | const options : RequestOptions = { 296 | url: path, 297 | method: 'GET' 298 | }; 299 | 300 | if(callback) 301 | { // Not a stream 302 | this.request(options, (e, res, body) => { 303 | if(e) 304 | return callback(e); 305 | if(res.statusCode >= 400) 306 | return callback(new HTTPError(res)); 307 | 308 | callback(null, body); 309 | }) 310 | } 311 | else 312 | { // Stream 313 | return this.stream(options); 314 | } 315 | } 316 | 317 | getObject(path : string, callback : (error ?: Error, body ?: T) => void) : void 318 | { 319 | this.get(path, (e, content) => { 320 | if(e) 321 | return callback(e); 322 | 323 | let obj : T; 324 | try 325 | { 326 | obj = JSON.parse(content.toString()); 327 | } 328 | catch(ex) 329 | { 330 | return callback(ex); 331 | } 332 | callback(null, obj); 333 | }) 334 | } 335 | 336 | put(path : string, content : ContentType, callback : (error ?: Error) => void) : void 337 | put(path : string) : Stream 338 | put(path : string, content ?: ContentType, callback ?: (error ?: Error) => void) : Stream 339 | { 340 | const options : RequestOptions = { 341 | url: path, 342 | method: 'PUT' 343 | }; 344 | 345 | if(callback) 346 | { // Not a stream 347 | options.body = content as ContentType, 348 | this.request(options, (e, res, body) => { 349 | if(e) 350 | return callback(e); 351 | if(res.statusCode >= 400) 352 | return callback(new HTTPError(res)); 353 | 354 | callback(); 355 | }) 356 | } 357 | else 358 | { // Stream 359 | return this.stream(options); 360 | } 361 | } 362 | 363 | putObject(path : string, content : T, callback : (error ?: Error) => void) : void 364 | { 365 | this.put(path, JSON.stringify(content), callback); 366 | } 367 | 368 | protected moveCopy(method : string, pathSource : string, pathDestination : string, _override : boolean | ((error ?: Error) => void), _callback ?: (error ?: Error) => void) 369 | { 370 | const override = _callback ? _override as boolean : false; 371 | const callback = _callback ? _callback : _override as (error ?: Error) => void; 372 | 373 | this.noBodyRequest({ 374 | url: pathSource, 375 | method: method, 376 | headers: { 377 | destination: pathDestination, 378 | override: override ? 'T' : 'F' 379 | } 380 | }, callback) 381 | } 382 | 383 | move(pathSource : string, pathDestination : string, override : boolean, callback : (error ?: Error) => void) : void 384 | move(pathSource : string, pathDestination : string, callback : (error ?: Error) => void) : void 385 | move(pathSource : string, pathDestination : string, _override : boolean | ((error ?: Error) => void), _callback ?: (error ?: Error) => void) : void 386 | { 387 | this.moveCopy('MOVE', pathSource, pathDestination, _override, _callback); 388 | } 389 | 390 | copy(pathSource : string, pathDestination : string, override : boolean, callback : (error ?: Error) => void) : void 391 | copy(pathSource : string, pathDestination : string, callback : (error ?: Error) => void) : void 392 | copy(pathSource : string, pathDestination : string, _override : boolean | ((error ?: Error) => void), _callback ?: (error ?: Error) => void) : void 393 | { 394 | this.moveCopy('COPY', pathSource, pathDestination, _override, _callback); 395 | } 396 | 397 | mkdir(path : string, callback : (error ?: Error) => void) : void 398 | { 399 | this.noBodyRequest({ 400 | url: path, 401 | method: 'MKCOL' 402 | }, callback) 403 | } 404 | 405 | delete(path : string, callback : (error ?: Error) => void) : void 406 | { 407 | this.noBodyRequest({ 408 | url: path, 409 | method: 'DELETE' 410 | }, callback) 411 | } 412 | 413 | lock(path : string, callback : (error ?: Error, lockUID ?: Lock) => void) : void 414 | { 415 | const lockinfo = new XMLElementBuilder('D:lockinfo', { 416 | 'xmlns:D': 'DAV:' 417 | }); 418 | lockinfo.ele('D:lockscope').ele('D:exclusive'); 419 | lockinfo.ele('D:locktype').ele('D:write'); 420 | 421 | this.request({ 422 | url: path, 423 | method: 'LOCK', 424 | body: lockinfo.toXML() 425 | }, (e, res, body) => { 426 | if(e) 427 | return callback(e); 428 | if(res.statusCode >= 400) 429 | return callback(new HTTPError(res)); 430 | 431 | const xml = XML.parse(Buffer.isBuffer(body) ? Int8Array.from(body) : body); 432 | try 433 | { 434 | callback(null, { 435 | uid: xml.find('DAV:prop').find('DAV:lockdiscovery').find('DAV:activelock').find('DAV:locktoken').find('DAV:href').findText() 436 | }); 437 | } 438 | catch(ex) 439 | { 440 | callback(ex); 441 | } 442 | }) 443 | } 444 | 445 | refreshLock(path : string, lock : string | Lock, callback : (error ?: Error) => void) : void 446 | { 447 | const uid = lock.constructor === String ? (lock as string) : (lock as Lock).uid; 448 | 449 | this.noBodyRequest({ 450 | url: path, 451 | method: 'LOCK', 452 | headers: { 453 | 'If': '(<' + uid + '>)' 454 | } 455 | }, callback) 456 | } 457 | 458 | unlock(path : string, lock : string | Lock, callback : (error ?: Error) => void) : void 459 | { 460 | const uid = lock.constructor === String ? (lock as string) : (lock as Lock).uid; 461 | 462 | this.noBodyRequest({ 463 | url: path, 464 | method: 'UNLOCK', 465 | headers: { 466 | 'Lock-Token': '<' + uid + '>' 467 | } 468 | }, callback) 469 | } 470 | 471 | readdir(path : string, callback : (error : Error, files ?: string[]) => void) : void 472 | readdir(path : string, options : ConnectionReaddirOptions, callback : (error : Error, files ?: string[] | ConnectionReaddirComplexResult[]) => void) : void 473 | readdir(path : string, _options : ConnectionReaddirOptions | ((error : Error, files ?: string[] | ConnectionReaddirComplexResult[]) => void), _callback ?: (error : Error, files ?: string[] | ConnectionReaddirComplexResult[]) => void) : void 474 | { 475 | const options = _callback ? _options as ConnectionReaddirOptions : {} as ConnectionReaddirOptions; 476 | const callback = _callback ? _callback : _options as ((error : Error, files ?: string[]) => void); 477 | 478 | if(options.properties === undefined || options.properties === null) 479 | options.properties = false; 480 | 481 | const [findProps, extraProperties] = createPropFindBody(options); 482 | 483 | this.request({ 484 | url: path, 485 | method: 'PROPFIND', 486 | headers: { 487 | depth: '1' 488 | }, 489 | body: (options.properties ? findProps.toXML() : '') 490 | }, (e, res, body) => { 491 | if(e) 492 | return callback(e); 493 | if(res.statusCode >= 400) 494 | return callback(new HTTPError(res)); 495 | 496 | try 497 | { 498 | const decodedPath = decodeURIComponent(path); 499 | 500 | const results = XML.parse(Buffer.isBuffer(body) ? Int8Array.from(body) : body) 501 | .find('DAV:multistatus') 502 | .findMany('DAV:response') 503 | .map(el => { 504 | const fullPathStart = this.root.length - 1; 505 | 506 | const href = el.find('DAV:href').findText(), 507 | pathname = Url.parse(href).pathname, 508 | fullPath = decodeURIComponent(pathname.slice(fullPathStart)), 509 | hrefWithoutTrailingSlash = (href.lastIndexOf('/') === href.length - 1 ? href.slice(0, -1) : href), 510 | name = Path.basename(fullPath); 511 | 512 | return { el, hrefWithoutTrailingSlash, fullPath, name }; 513 | }) 514 | .filter(({ fullPath }) => fullPath !== decodedPath && fullPath !== `${decodedPath}/`) 515 | .map(({ el, hrefWithoutTrailingSlash, name }) => { 516 | if(options.properties) 517 | { 518 | const props = el.find('DAV:propstat').find('DAV:prop'); 519 | const type = props.find('DAV:resourcetype').findIndex('DAV:collection') !== -1 ? 'directory' : 'file'; 520 | 521 | const result = { 522 | name, 523 | 524 | creationDate: props.findIndex('DAV:creationdate') !== -1 ? new Date(props.find('DAV:creationdate').findText()) : undefined, 525 | lastModified: new Date(props.find('DAV:getlastmodified').findText()), 526 | type: type, 527 | isFile: type === 'file', 528 | isDirectory: type === 'directory', 529 | size: props.findIndex('DAV:getcontentlength') !== -1 ? parseInt(props.find('DAV:getcontentlength').findText()) : 0, 530 | href: hrefWithoutTrailingSlash, 531 | } as ConnectionReaddirComplexResult; 532 | 533 | if (extraProperties.length > 0) { 534 | result.extraProperties = {}; 535 | extraProperties.forEach(extraProperty => { 536 | if (props.findIndex(`${extraProperty.namespace}${extraProperty.element}`) !== -1) { 537 | result.extraProperties[extraProperty.element] = (extraProperty.nativeType ? 538 | toNativeType(props.find(`${extraProperty.namespace}${extraProperty.element}`).findText()) : 539 | props.find(`${extraProperty.namespace}${extraProperty.element}`).findText() 540 | ); 541 | } else if (extraProperty.default) { 542 | result.extraProperties[extraProperty.element] = extraProperty.default; 543 | } 544 | }); 545 | } 546 | 547 | return result; 548 | } 549 | 550 | return name; 551 | }); 552 | 553 | callback(null, results as any); 554 | } 555 | catch(ex) 556 | { 557 | callback(ex); 558 | } 559 | }) 560 | } 561 | 562 | setProperties(path : string, properties : Properties, callback : (error ?: Error) => void) : void 563 | { 564 | const propertyupdate = new XMLElementBuilder('D:propertyupdate', { 565 | 'xmlns:D': 'DAV:' 566 | }); 567 | const prop = propertyupdate.ele('D:set').ele('D:prop'); 568 | for(const name in properties) 569 | prop.ele(name, properties[name].attributes).add(properties[name].content); 570 | 571 | this.request({ 572 | url: path, 573 | method: 'PROPPATCH', 574 | body: propertyupdate.toXML() 575 | }, (e, res, body) => { 576 | if(e) 577 | return callback(e); 578 | if(res.statusCode >= 400) 579 | return callback(new HTTPError(res)); 580 | 581 | callback(); 582 | }) 583 | } 584 | 585 | removeProperties(path : string, properties : string[], callback : (error ?: Error) => void) : void 586 | { 587 | const propertyupdate = new XMLElementBuilder('D:propertyupdate', { 588 | 'xmlns:D': 'DAV:' 589 | }); 590 | const prop = propertyupdate.ele('D:remove').ele('D:prop'); 591 | properties.forEach((p) => prop.ele(p)); 592 | 593 | this.request({ 594 | url: path, 595 | method: 'PROPPATCH', 596 | body: propertyupdate.toXML() 597 | }, (e, res, body) => { 598 | if(e) 599 | return callback(e); 600 | if(res.statusCode >= 400) 601 | return callback(new HTTPError(res)); 602 | 603 | callback(); 604 | }) 605 | } 606 | 607 | getProperties(path : string, callback : (error ?: Error, properties ?: Properties) => void) : void 608 | getProperties(path : string, options : ConnectionReaddirOptions, callback : (error : Error, properties ?: Properties) => void) : void 609 | getProperties(path : string, _options : ConnectionReaddirOptions | ((error : Error, properties ?: Properties) => void), _callback ?: (error : Error, properties ?: Properties) => void) : void 610 | { 611 | const options = _callback ? _options as ConnectionReaddirOptions : {} as ConnectionReaddirOptions; 612 | const callback = _callback ? _callback : _options as ((error : Error, properties ?: Properties) => void); 613 | 614 | let [findProps, extraProperties] = createPropFindBody(options); 615 | 616 | this.request({ 617 | url: path, 618 | method: 'PROPFIND', 619 | headers: { 620 | depth: '0' 621 | }, 622 | body: (extraProperties.length > 0 ? findProps.toXML() : '') 623 | }, (e, res, body) => { 624 | if(e) 625 | return callback(e); 626 | if(res.statusCode >= 400) 627 | return callback(new HTTPError(res)); 628 | 629 | try 630 | { 631 | const properties = XML.parse(Buffer.isBuffer(body) ? Int8Array.from(body) : body) 632 | .find('DAV:multistatus') 633 | .find('DAV:response') 634 | .findMany('DAV:propstat') 635 | .map(el => { 636 | return el.find('DAV:prop') 637 | .elements 638 | .map((el) => { 639 | let name = el.name; 640 | for (const extraProperty of extraProperties) { 641 | if (name && name === `${extraProperty.namespace}${extraProperty.element}`) { 642 | name = `${extraProperty.namespaceShort}:${extraProperty.element}`; 643 | break; 644 | } 645 | } 646 | 647 | return { 648 | name: name, 649 | attributes: el.attributes, 650 | value: el.elements.length === 0 ? undefined : el.elements.length === 1 && el.elements[0].type === 'text' ? (el.elements[0] as any).text : el.elements 651 | } 652 | }) 653 | }) 654 | 655 | const result : Properties = {}; 656 | for (const propArr of properties) { 657 | for (const prop of propArr) { 658 | result[prop.name] = { 659 | content: prop.value, 660 | attributes: prop.attributes 661 | } 662 | } 663 | } 664 | 665 | callback(null, result); 666 | } 667 | catch(ex) 668 | { 669 | callback(ex); 670 | } 671 | }) 672 | } 673 | } 674 | 675 | function createPropFindBody(options: ConnectionReaddirOptions): [XMLElementBuilder, ConnectionReaddirProperty[]] { 676 | const findProps = new XMLElementBuilder( 677 | 'd:propfind', 678 | { 'xmlns:d': 'DAV:' } 679 | ); 680 | 681 | const xmlProp = findProps.ele('d:prop'); 682 | xmlProp.ele('d:resourcetype'); 683 | xmlProp.ele('d:creationdate'); 684 | xmlProp.ele('d:getlastmodified'); 685 | xmlProp.ele('d:getcontentlength'); 686 | 687 | let extraProperties: ConnectionReaddirProperty[] = []; 688 | 689 | if (options && options.extraProperties && options.extraProperties.length > 0) { 690 | extraProperties = options.extraProperties.filter(extraProperty => { 691 | return extraProperty.namespaceShort 692 | && extraProperty.namespaceShort.length > 0 693 | && extraProperty.namespace 694 | && extraProperty.namespace.length > 0 695 | && extraProperty.element 696 | && extraProperty.element.length > 0; 697 | }); 698 | 699 | if (extraProperties.length > 0) { 700 | uniqBy(options.extraProperties, extraProperty => extraProperty.namespaceShort) 701 | .forEach(extraProperty => { 702 | if (extraProperty.namespaceShort !== 'd') { 703 | findProps.attributes[`xmlns:${extraProperty.namespaceShort}`] = extraProperty.namespace; 704 | } 705 | }); 706 | 707 | options.extraProperties.forEach(extraProperty => { 708 | xmlProp.ele(`${extraProperty.namespaceShort}:${extraProperty.element}`); 709 | }); 710 | } 711 | } 712 | 713 | return [findProps, extraProperties]; 714 | } 715 | 716 | function toNativeType(value: string) { 717 | let numValue = Number(value); 718 | 719 | if (!isNaN(numValue)) { 720 | return numValue; 721 | } 722 | 723 | let boolValue = value.toLowerCase(); 724 | 725 | if (boolValue === 'true') { 726 | return true; 727 | } else if (boolValue === 'false') { 728 | return false; 729 | } 730 | 731 | return value; 732 | } 733 | -------------------------------------------------------------------------------- /src/request.ts: -------------------------------------------------------------------------------- 1 | import { Readable, Writable } from 'stream' 2 | import * as req from 'request' 3 | import * as http from 'http' 4 | 5 | export type ContentType = Buffer | string; 6 | 7 | export interface RequestOptions 8 | { 9 | url : string 10 | method : string 11 | headers ?: { 12 | [name : string] : string 13 | } 14 | body ?: ContentType 15 | } 16 | 17 | export interface Response 18 | { 19 | statusCode : number 20 | statusMessage : string 21 | headers : { 22 | [name : string] : string | string[] 23 | } 24 | } 25 | 26 | export type ResponseCallback = (error : Error, response ?: Response, body ?: ContentType) => void; 27 | 28 | export function request(options : RequestOptions, callback : ResponseCallback) : void 29 | { 30 | req(options, (e, res, body) => { 31 | callback(e, e ? null : { 32 | headers: res.headers, 33 | statusCode: res.statusCode, 34 | statusMessage: res.statusMessage 35 | }, body); 36 | }) 37 | } 38 | 39 | export interface Stream extends req.Request 40 | { 41 | on(event: string, listener: Function): this; 42 | on(event: 'request', listener: (req: http.ClientRequest) => void): this; 43 | on(event: 'response' | 'finish', listener: (resp: http.IncomingMessage) => void): this; 44 | on(event: 'data', listener: (data: Buffer | string) => void): this; 45 | on(event: 'error', listener: (e: Error) => void): this; 46 | on(event: 'complete', listener: (resp: http.IncomingMessage, body?: string | Buffer) => void): this; 47 | on(event: 'end', listener: () => void): this; 48 | } 49 | 50 | //export type Stream = req.Request 51 | 52 | export function stream(options : RequestOptions) : Stream 53 | { 54 | const stream = req(options); 55 | stream.on('response', (resp) => { 56 | stream.emit('finish', resp); 57 | }) 58 | 59 | return stream; 60 | } 61 | -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitAny": false, 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "outDir": "../lib", 10 | "typeRoots": [ 11 | "../node_modules/@types" 12 | ], 13 | "target": "ES5" 14 | } 15 | } -------------------------------------------------------------------------------- /test/a.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 16 | 17 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const client = require('../lib/index'), 4 | webdav = require('webdav-server').v2; 5 | 6 | const servers = []; 7 | 8 | const subTree = { 9 | 'folder1': { 10 | 'file2': webdav.ResourceType.File, 11 | 'file2.2': webdav.ResourceType.File, 12 | 'file2.3': webdav.ResourceType.File 13 | }, 14 | 'folder test é &': { 15 | 'file1': webdav.ResourceType.File 16 | }, 17 | 'file1': webdav.ResourceType.File, 18 | 'file1.2': webdav.ResourceType.File, 19 | 'file1.3': webdav.ResourceType.File, 20 | 'file1.5': webdav.ResourceType.File, 21 | 'file.lock': webdav.ResourceType.File, 22 | 'file.lock2': webdav.ResourceType.File, 23 | 'file.move.1': webdav.ResourceType.File, 24 | 'file.move.2': webdav.ResourceType.File, 25 | 'file.move.3': webdav.ResourceType.File, 26 | 'file.copy.1': webdav.ResourceType.File, 27 | 'file.copy.2': webdav.ResourceType.File, 28 | 'file.copy.3': webdav.ResourceType.File, 29 | 'fileToDelete': webdav.ResourceType.File, 30 | 'file.pipe.in': webdav.ResourceType.File, 31 | 'file.new': webdav.ResourceType.File, 32 | 'file1.new': webdav.ResourceType.File 33 | }; 34 | 35 | const server = new webdav.WebDAVServer(); 36 | servers.push(server); 37 | const ctx = server.createExternalContext(); 38 | 39 | const ANY = 15546213556767.1; 40 | const errors = []; 41 | let nbTests = 0; 42 | function done(text, error) 43 | { 44 | --nbTests; 45 | if(error) 46 | { 47 | process.exitCode = 1; 48 | console.error(text, '::', error); 49 | errors.push(error); 50 | } 51 | 52 | if(nbTests === 0) 53 | { 54 | if(errors.length === 0) 55 | console.log(' All tests passed!'); 56 | else 57 | console.error(' ' + errors.length + ' error(s) occured!'); 58 | servers.forEach((s) => s.stop()); 59 | } 60 | } 61 | function start(text, fn) 62 | { 63 | ++nbTests; 64 | const next = (error) => { 65 | done(text, error); 66 | }; 67 | fn(next, (value, expected) => { 68 | ++nbTests; 69 | let failed; 70 | if(expected === ANY) 71 | { 72 | failed = value === undefined || value === null; 73 | next(failed ? 'Expected any value but got "' + value + '"' : null); 74 | } 75 | else if(Array.isArray(expected) && Array.isArray(value)) 76 | { 77 | const working = expected.map((x) => x); 78 | for(const v of value) 79 | { 80 | let found = false; 81 | for(const index in working) 82 | if(working[index] == v) 83 | { 84 | found = true; 85 | working.splice(index, 1); 86 | break; 87 | } 88 | 89 | if(!found) 90 | { 91 | failed = true; 92 | break; 93 | } 94 | } 95 | 96 | failed = failed || working.length > 0; 97 | next(failed ? 'Expected "[ ' + expected + ' ]" but got "[ ' + value + ' ]"' : null); 98 | } 99 | else 100 | { 101 | failed = expected != value; 102 | next(failed ? 'Expected "' + expected + '" but got "' + value + '"' : null); 103 | } 104 | return !failed; 105 | }) 106 | } 107 | 108 | let connection = true ? null : new client.Connection(''); 109 | 110 | function testAuthenticators(type) 111 | { 112 | start(type + ' authentication', (end, expected) => { 113 | const userManager = new webdav.SimpleUserManager(); 114 | const user = userManager.addUser('toto', 'password', true); 115 | 116 | const privileges = new webdav.SimplePathPrivilegeManager(); 117 | privileges.setRights(user, '/', [ 'all' ]); 118 | 119 | const server = new webdav.WebDAVServer({ 120 | httpAuthentication: type === 'digest' ? new webdav.HTTPDigestAuthentication(userManager) : new webdav.HTTPBasicAuthentication(userManager), 121 | privilegeManager: privileges, 122 | port: 1900 + servers.length 123 | }); 124 | servers.push(server); 125 | const ctx = server.createExternalContext(); 126 | server.rootFileSystem().addSubTree(ctx, { 127 | 'file': webdav.ResourceType.File 128 | }, (e) => { 129 | if(e) 130 | throw e; 131 | 132 | server.start((s) => { 133 | const connection = new client.Connection({ 134 | url: 'http://localhost:' + s.address().port, 135 | authenticator: type === 'digest' ? new client.DigestAuthenticator() : new client.BasicAuthenticator(), 136 | username: 'toto', 137 | password: 'password' 138 | }); 139 | 140 | start('"getProperties" on "/file" being authenticated (digest)', (end, expected) => { 141 | connection.getProperties('/file', (e, props) => { 142 | expected(e); 143 | end(); 144 | }) 145 | }) 146 | 147 | const connection2 = new client.Connection({ 148 | url: 'http://localhost:' + s.address().port 149 | }); 150 | 151 | start('"getProperties" on "/file" without being authenticated (digest)', (end, expected) => { 152 | connection2.getProperties('/file', (e, props) => { 153 | expected(e, ANY); 154 | end(); 155 | }) 156 | }) 157 | 158 | start('"prepareForStreaming" on "/file"', (end) => { 159 | connection.prepareForStreaming((e) => { 160 | expected(e); 161 | 162 | start('"put" as stream on "/file" while being authenticated', (end, expected) => { 163 | const content = 'This is the content'; 164 | const wStream = connection.put('/file'); 165 | wStream.on('error', (e) => expected(e)) 166 | wStream.on('finish', () => { 167 | 168 | wStream.on('complete', (res) => { 169 | expected(res.statusCode, 200) // 200 - OK 170 | }); 171 | 172 | start('"get" as stream on "/file" while being authenticated', (end, expected) => { 173 | const rStream = connection.get('/file'); 174 | let data = ''; 175 | 176 | rStream.on('error', (e) => expected(e)) 177 | rStream.on('end', () => { 178 | expected(data, content); 179 | end() 180 | }) 181 | rStream.on('data', (chunk) => { 182 | data += chunk.toString(); 183 | }) 184 | }) 185 | 186 | end(); 187 | }); 188 | wStream.end(content, (e) => { 189 | expected(e); 190 | }); 191 | }) 192 | 193 | end(); 194 | }) 195 | }) 196 | 197 | end(); 198 | }) 199 | }) 200 | }) 201 | } 202 | 203 | server.rootFileSystem().addSubTree(ctx, subTree, (e) => { 204 | if(e) 205 | throw e; 206 | 207 | server.start((s) => { 208 | connection = new client.Connection('http://localhost:' + s.address().port); 209 | 210 | testAuthenticators('basic'); 211 | testAuthenticators('digest'); 212 | 213 | testExists(); 214 | testGetPut(); 215 | testReadDir(); 216 | testReadDirQueriedPathEntryBug(); 217 | testProperties(); 218 | testMkDir(); 219 | testDelete(); 220 | testLockUnlock(); 221 | testMoveCopy('move'); 222 | testMoveCopy('copy'); 223 | }) 224 | }) 225 | 226 | function testExists() 227 | { 228 | start('"exists" on "/file1"', (end, expected) => { 229 | connection.exists('/file1', (e, exists) => { 230 | expected(e) && expected(exists, true); 231 | end(); 232 | }) 233 | }) 234 | 235 | start('"exists" on undefined', (end, expected) => { 236 | connection.exists('/fileX', (e, exists) => { 237 | expected(e) && expected(exists, false); 238 | end(); 239 | }) 240 | }) 241 | } 242 | 243 | function testGetPut() 244 | { 245 | start('"putObject" on "/file1.5"', (end, expected) => { 246 | connection.putObject('/file1.5', { 247 | prop1: 'ok' 248 | }, (e) => { 249 | expected(e); 250 | 251 | start('"getObject" on "/file1.5" after "putObject"', (end, expected) => { 252 | connection.getObject('/file1.5', (e, obj) => { 253 | expected(e) && expected(obj, ANY) && expected(obj.prop1, 'ok'); 254 | end(); 255 | }) 256 | }) 257 | 258 | end(); 259 | }) 260 | }) 261 | 262 | start('"get" on "/file1"', (end, expected) => { 263 | connection.get('/file1', (e, body) => { 264 | expected(e) && expected(body.toString(), ''); 265 | end(); 266 | }) 267 | }) 268 | 269 | start('"get" on undefined', (end, expected) => { 270 | connection.get('/fileX', (e, body) => { 271 | expected(e, ANY); 272 | end(); 273 | }) 274 | }) 275 | 276 | start('"put" on "/file1.2"', (end, expected) => { 277 | const content = 'This is the content'; 278 | connection.put('/file1.2', content, (e, body) => { 279 | expected(e); 280 | 281 | start('"get" on "/file1.2"', (end, expected) => { 282 | connection.get('/file1.2', (e, body) => { 283 | expected(e) && expected(body.toString(), content); 284 | end(); 285 | }) 286 | }) 287 | 288 | start('"getObject" on "/file1.2" after "put" of no-JSON content', (end, expected) => { 289 | connection.getObject('/file1.2', (e, obj) => { 290 | expected(e, ANY); 291 | end(); 292 | }) 293 | }) 294 | 295 | end(); 296 | }) 297 | }) 298 | 299 | start('"put" on undefined "/file1.new"', (end, expected) => { 300 | const content = 'This is the content'; 301 | connection.put('/file1.new', content, (e, body) => { 302 | expected(e); 303 | 304 | start('"get" on newly "/file1.new"', (end, expected) => { 305 | connection.get('/file1.new', (e, body) => { 306 | expected(e) && expected(body.toString(), content); 307 | end(); 308 | }) 309 | }) 310 | 311 | end(); 312 | }) 313 | }) 314 | 315 | start('"put" as stream on "/file1.3"', (end, expected) => { 316 | const content = 'This is the content'; 317 | const wStream = connection.put('/file1.3'); 318 | wStream.on('error', (e) => expected(e)) 319 | wStream.on('finish', () => { 320 | 321 | start('"get" as stream on "/file1.3"', (end, expected) => { 322 | const rStream = connection.get('/file1.3'); 323 | let data = ''; 324 | 325 | rStream.on('error', (e) => expected(e)) 326 | rStream.on('end', () => { 327 | expected(data, content); 328 | end() 329 | }) 330 | rStream.on('data', (chunk) => { 331 | data += chunk.toString(); 332 | }) 333 | }) 334 | 335 | end(); 336 | }); 337 | wStream.end(content); 338 | }) 339 | 340 | start('"put" on "/file.pipe.in"', (end, expected) => { 341 | const content = 'This is the content'; 342 | connection.put('/file.pipe.in', content, (e, body) => { 343 | expected(e); 344 | 345 | start('"put" as stream on "/file.pipe.out"', (end, expected) => { 346 | const wStream = connection.put('/file.pipe.out'); 347 | 348 | start('"get" as stream on "/file.pipe.in"', (end2, expected) => { 349 | const rStream = connection.get('/file.pipe.in'); 350 | 351 | rStream.pipe(wStream); 352 | rStream.on('error', (e) => expected(e)) 353 | 354 | wStream.on('finish', () => { 355 | start('"get" on "/file.pipe.out"', (end, expected) => { 356 | connection.get('/file.pipe.out', (e, body) => { 357 | expected(e) && expected(body.toString(), content); 358 | end(); 359 | }) 360 | }) 361 | 362 | end() 363 | end2() 364 | }) 365 | }) 366 | }) 367 | 368 | end(); 369 | }) 370 | }) 371 | } 372 | 373 | function testReadDirQueriedPathEntryBug() { 374 | start('"readdir" on "/"', (end, expected) => { 375 | connection.readdir('/', (e, files) => { 376 | expected(e) && expected(files, Object.keys(subTree)); 377 | end(); 378 | }) 379 | }) 380 | 381 | start('"readdir" on "/test folder é &"', (end, expected) => { 382 | connection.readdir('/folder test é &', (e, files) => { 383 | expected(e) && expected(files, [ 'file1' ]); 384 | end(); 385 | }) 386 | }) 387 | 388 | // Some WebDAV implementation will return 404s if the 389 | // URL is not escaped, so this needs to work too. 390 | start('"readdir" on escaped-"/test folder é &"', (end, expected) => { 391 | connection.readdir('/folder%20test%20%C3%A9%20%26', (e, files) => { 392 | expected(e) && expected(files, [ 'file1' ]); 393 | end(); 394 | }) 395 | }) 396 | } 397 | 398 | function testReadDir() 399 | { 400 | start('"readdir" on "/folder1"', (end, expected) => { 401 | connection.readdir('/folder1', (e, files) => { 402 | expected(e) && expected(files, [ 'file2', 'file2.2', 'file2.3' ]); 403 | end(); 404 | }) 405 | }) 406 | 407 | start('"readdir" on "/folder1"', (end, expected) => { 408 | connection.readdir('/folder1', { 409 | properties: true 410 | }, (e, files) => { 411 | expected(e) && expected(Array.isArray(files), true) && expected(files.length, 3); 412 | files.forEach((file) => { 413 | expected(!!file.creationDate, true); 414 | expected(!!file.lastModified, true); 415 | expected(file.isFile === true || file.isFile === false, true); 416 | expected(file.isDirectory === true || file.isDirectory === false, true); 417 | expected(!!file.type, true); 418 | expected(!!file.href, true); 419 | expected(!!file.name, true); 420 | }); 421 | 422 | end(); 423 | }) 424 | }) 425 | 426 | start('"readdir" on undefined', (end, expected) => { 427 | connection.readdir('/folderX', (e, files) => { 428 | expected(e, ANY); 429 | end(); 430 | }) 431 | }) 432 | 433 | start('"readdir" on undefined', (end, expected) => { 434 | connection.readdir('/folderX', { 435 | properties: true 436 | }, (e, files) => { 437 | expected(e, ANY); 438 | end(); 439 | }) 440 | }) 441 | 442 | start('"readdir" on "/file1"', (end, expected) => { 443 | connection.readdir('/file1', (e, files) => { 444 | expected(e) && expected(files, [ ]); 445 | end(); 446 | }) 447 | }) 448 | 449 | start('"readdir" on "/file1"', (end, expected) => { 450 | connection.readdir('/file1', { 451 | properties: true 452 | }, (e, files) => { 453 | expected(e) && expected(files, [ ]); 454 | end(); 455 | }) 456 | }) 457 | } 458 | 459 | function testProperties() 460 | { 461 | start('"getProperties" on "/file1"', (end, expected) => { 462 | connection.getProperties('/file1', (e, props) => { 463 | expected(e); 464 | end(); 465 | }) 466 | }) 467 | 468 | start('"getProperties" on undefined', (end, expected) => { 469 | connection.getProperties('/fileX', (e, props) => { 470 | expected(e, ANY); 471 | end(); 472 | }) 473 | }) 474 | 475 | start('"removeProperties" on undefined', (end, expected) => { 476 | connection.removeProperties('/folderX', [ 'prop1' ], (e) => { 477 | expected(e, ANY); 478 | end(); 479 | }) 480 | }) 481 | 482 | start('"setProperties" on undefined', (end, expected) => { 483 | connection.setProperties('/folderX', { 484 | 'prop1': { 485 | content: 'value value' 486 | } 487 | }, (e) => { 488 | expected(e, ANY); 489 | end(); 490 | }) 491 | }) 492 | 493 | start('"setProperties" on "/file1"', (end, expected) => { 494 | connection.setProperties('/file1', { 495 | 'prop1': { 496 | content: 'value value' 497 | } 498 | }, (e) => { 499 | expected(e); 500 | 501 | start('"getProperties" on "/file1" after "setProperties"', (end, expected) => { 502 | connection.getProperties('/file1', (e, props) => { 503 | expected(e) && expected(props, ANY) && expected(props['prop1'], ANY) && expected(props['prop1'].content, 'value value'); 504 | end(); 505 | }) 506 | }) 507 | 508 | end(); 509 | }) 510 | }) 511 | 512 | start('"setProperties" on "/file1.2"', (end, expected) => { 513 | connection.setProperties('/file1.2', { 514 | 'prop1': { 515 | content: 'value value' 516 | } 517 | }, (e) => { 518 | expected(e); 519 | 520 | start('"removeProperties" on "/file1.2" after "setProperties"', (end, expected) => { 521 | connection.removeProperties('/file1.2', [ 'prop1' ], (e) => { 522 | expected(e); 523 | 524 | start('"getProperties" on "/file1.2" after "removeProperties"', (end, expected) => { 525 | connection.getProperties('/file1.2', (e, props) => { 526 | expected(e) && expected(props, ANY) && expected(props['prop1']); 527 | end(); 528 | }) 529 | }) 530 | 531 | end(); 532 | }) 533 | }) 534 | 535 | end(); 536 | }) 537 | }) 538 | } 539 | 540 | function testMkDir() 541 | { 542 | start('"mkdir" on "/folder2"', (end, expected) => { 543 | connection.mkdir('/folder2', (e) => { 544 | expected(e); 545 | 546 | start('"exists" on "/folder2" after "mkdir"', (end, expected) => { 547 | connection.exists('/folder2', (e, exists) => { 548 | expected(e) && expected(exists, true); 549 | end(); 550 | }) 551 | }) 552 | 553 | end(); 554 | }) 555 | }) 556 | 557 | start('"mkdir" on existing "/folder1"', (end, expected) => { 558 | connection.mkdir('/folder1', (e) => { 559 | expected(e, ANY); 560 | end(); 561 | }) 562 | }) 563 | } 564 | 565 | function testMoveCopy(method) 566 | { 567 | start('"' + method + '" on undefined "/file.undefined"', (end, expected) => { 568 | connection[method]('/file.undefined', '/file2.undefined', (e) => { 569 | expected(e, ANY); 570 | end(); 571 | }) 572 | }) 573 | 574 | start('"' + method + '" from "/file.' + method + '.1" to "/file.' + method + '.1.2"', (end, expected) => { 575 | connection[method]('/file.' + method + '.1', '/file.' + method + '.1.2', (e) => { 576 | expected(e); 577 | 578 | start('"exists" on "/file.' + method + '.1" (source of ' + method + ') after "' + method + '"', (end, expected) => { 579 | connection.exists('/file.' + method + '.1', (e, exists) => { 580 | expected(e) && expected(exists, method === 'copy'); 581 | end(); 582 | }) 583 | }) 584 | 585 | start('"exists" on "/file.' + method + '.1.2" (destination of ' + method + ') after "' + method + '"', (end, expected) => { 586 | connection.exists('/file.' + method + '.1.2', (e, exists) => { 587 | expected(e) && expected(exists, true); 588 | end(); 589 | }) 590 | }) 591 | 592 | end(); 593 | }) 594 | }) 595 | 596 | start('"' + method + '" from "/file.' + method + '.2" to itself ("/file.' + method + '.2")', (end, expected) => { 597 | connection[method]('/file.' + method + '.2', '/file.' + method + '.2', (e) => { 598 | expected(e, ANY); 599 | end(); 600 | }) 601 | }) 602 | 603 | start('"' + method + '" from "/file.' + method + '.2" to existing "/file.' + method + '.3"', (end, expected) => { 604 | connection[method]('/file.' + method + '.2', '/file.' + method + '.3', (e) => { 605 | expected(e, ANY); 606 | end(); 607 | }) 608 | }) 609 | } 610 | 611 | function testDelete() 612 | { 613 | start('"delete" on existing "/fileToDelete"', (end, expected) => { 614 | connection.delete('/fileToDelete', (e) => { 615 | expected(e); 616 | 617 | start('"exists" on "/fileToDelete" after "delete"', (end, expected) => { 618 | connection.exists('/fileToDelete', (e, exists) => { 619 | expected(e) && expected(exists, false); 620 | end(); 621 | }) 622 | }) 623 | 624 | end(); 625 | }) 626 | }) 627 | 628 | start('"delete" on undefined', (end, expected) => { 629 | connection.delete('/fileX', (e) => { 630 | expected(e, ANY); 631 | end(); 632 | }) 633 | }) 634 | } 635 | 636 | function testLockUnlock() 637 | { 638 | start('"lock" on undefined "/file.lock.new"', (end, expected) => { 639 | connection.lock('/file.lock.new', (e, lock) => { 640 | expected(e) && expected(lock, ANY); 641 | 642 | start('"exists" on "/file.lock.new" after "lock"', (end, expected) => { 643 | connection.exists('/file.lock.new', (e, exists) => { 644 | expected(e) && expected(exists, true); 645 | end(); 646 | }) 647 | }) 648 | 649 | end(); 650 | }) 651 | }) 652 | 653 | start('"lock" on "/file.lock"', (end, expected) => { 654 | connection.lock('/file.lock', (e, lock) => { 655 | expected(e) && expected(lock, ANY); 656 | 657 | start('"unlock" on "/file.lock" after a "lock"', (end, expected) => { 658 | connection.unlock('/file.lock', lock, (e) => { 659 | expected(e); 660 | end(); 661 | }) 662 | }) 663 | 664 | end(); 665 | }) 666 | }) 667 | 668 | start('"lock" on "/file.lock2"', (end, expected) => { 669 | connection.lock('/file.lock2', (e, lock) => { 670 | expected(e) && expected(lock, ANY); 671 | 672 | start('"unlock" on "/file.lock2" after a "lock" with the wrong lock uid', (end, expected) => { 673 | connection.unlock('/file.lock2', 'xxxxxxx', (e) => { 674 | expected(e, ANY); 675 | end(); 676 | }) 677 | }) 678 | 679 | end(); 680 | }) 681 | }) 682 | 683 | start('"lock" on "/file.lock3"', (end, expected) => { 684 | connection.lock('/file.lock3', (e, lock) => { 685 | expected(e) && expected(lock, ANY); 686 | 687 | start('"refreshLock" on "/file.lock3" after a "lock"', (end, expected) => { 688 | connection.refreshLock('/file.lock3', lock, (e) => { 689 | expected(e); 690 | end(); 691 | }) 692 | }) 693 | 694 | end(); 695 | }) 696 | }) 697 | 698 | start('"unlock" on unlocked "/file1.2"', (end, expected) => { 699 | connection.unlock('/file1.2', 'xxxxxxxxxxxx', (e) => { 700 | expected(e, ANY); 701 | end(); 702 | }) 703 | }) 704 | 705 | start('"unlock" on undefined "/file.undefined"', (end, expected) => { 706 | connection.unlock('/file.undefined', 'xxxxxxxxxxxxxx', (e) => { 707 | expected(e, ANY); 708 | end(); 709 | }) 710 | }) 711 | } 712 | --------------------------------------------------------------------------------