diff --git a/README.md b/README.md index 500dd91..d2a00b7 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ * @azure/storage-blob [![npm version](https://badge.fury.io/js/%40azure%2Fstorage-blob.svg)](https://badge.fury.io/js/%40azure%2Fstorage-blob) * @azure/storage-file [![npm version](https://badge.fury.io/js/%40azure%2Fstorage-file.svg)](https://badge.fury.io/js/%40azure%2Fstorage-file) +* @azure/storage-queue [![npm version](https://badge.fury.io/js/%40azure%2Fstorage-queue.svg)](https://badge.fury.io/js/%40azure%2Fstorage-queue) * [API Reference documentation](https://docs.microsoft.com/en-us/javascript/api/overview/azure/storage/client?view=azure-node-preview) ## Introduction @@ -23,6 +24,10 @@ Please note that this version of the SDK is a compete overhaul of the current [A * Create/List/Delete File Shares * Create/List/Delete File Directories * Create/Read/List/Update/Delete Files +* Queue Storage + * Get/Set Queue Service Properties + * Create/List/Delete Queues + * Enqueue/Dequeue/Peek/Clear/Update/Delete Queue Messages * Features new * Asynchronous I/O for all operations using the async methods * HttpPipeline which enables a high degree of per-request configurability @@ -56,6 +61,7 @@ There are differences between Node.js and browsers runtime. When getting start w * `generateAccountSASQueryParameters()` * `generateBlobSASQueryParameters()` * `generateFileSASQueryParameters()` + * `generateQueueSASQueryParameters()` * Parallel uploading and downloading * `uploadFileToBlockBlob()` * `uploadStreamToBlockBlob()` @@ -101,12 +107,14 @@ To use the SDK with JS bundle in the browsers, simply add a script tag to your H ```html + ``` The JS bundled file is compatible with [UMD](https://github.com/umdjs/umd) standard, if no module system found, following global variable(s) will be exported: * `azblob` * `azfile` +* `azqueue` #### Download @@ -114,6 +122,7 @@ Download latest released JS bundles from links in the [GitHub release page](http * Blob [https://aka.ms/downloadazurestoragejsblob](https://aka.ms/downloadazurestoragejsblob) * File [https://aka.ms/downloadazurestoragejsfile](https://aka.ms/downloadazurestoragejsfile) +* Queue [https://aka.ms/downloadazurestoragejsqueue](https://aka.ms/downloadazurestoragejsqueue) ### CORS @@ -272,6 +281,8 @@ main() * [Blob Storage Examples - Test Cases](https://github.com/azure/azure-storage-js/tree/master/blob/test/) * [File Storage Examples](https://github.com/azure/azure-storage-js/tree/master/file/samples) * [File Storage Examples - Test Cases](https://github.com/azure/azure-storage-js/tree/master/file/test/) +* [Queue Storage Examples](https://github.com/azure/azure-storage-js/tree/master/queue/samples) +* [Queue Storage Examples - Test Cases](https://github.com/azure/azure-storage-js/tree/master/queue/test/) ## License diff --git a/blob/lib/StorageURL.ts b/blob/lib/StorageURL.ts index 46af1b4..32f98ef 100644 --- a/blob/lib/StorageURL.ts +++ b/blob/lib/StorageURL.ts @@ -58,14 +58,15 @@ export abstract class StorageURL { // Order is important. Closer to the API at the top & closer to the network at the bottom. // The credential's policy factory must appear close to the wire so it can sign any // changes made by other factories (like UniqueRequestIDPolicyFactory) - const factories: RequestPolicyFactory[] = []; - factories.push(new TelemetryPolicyFactory(pipelineOptions.telemetry)); - factories.push(new UniqueRequestIDPolicyFactory()); - factories.push(new BrowserPolicyFactory()); - factories.push(deserializationPolicy()); // Default deserializationPolicy is provided by protocol layer - factories.push(new RetryPolicyFactory(pipelineOptions.retryOptions)); - factories.push(new LoggingPolicyFactory()); - factories.push(credential); + const factories: RequestPolicyFactory[] = [ + new TelemetryPolicyFactory(pipelineOptions.telemetry), + new UniqueRequestIDPolicyFactory(), + new BrowserPolicyFactory(), + deserializationPolicy(), // Default deserializationPolicy is provided by protocol layer + new RetryPolicyFactory(pipelineOptions.retryOptions), + new LoggingPolicyFactory(), + credential + ]; return new Pipeline(factories, { HTTPClient: pipelineOptions.httpClient, diff --git a/queue/.npmignore b/queue/.npmignore new file mode 100644 index 0000000..2101725 --- /dev/null +++ b/queue/.npmignore @@ -0,0 +1,50 @@ +# browser # +browser/azure-storage.queue.js + +# dist-esm # +!dist-esm/lib/**/*.js +dist-esm/test +dist-esm/samples + +# dist-test # +dist-test/ + +# Node # +node_modules/ + +# Samples # +samples/ + +# Swagger # +swagger/ + +# typings # +!typings/lib/**/*.d.ts +typings/test +typings/samples + +# git # +.git* + +# Test # +test/ + +# Others # +.vscode/ +.idea/ +.travis.yml +.gitignore +gulpfile.js +.git +.DS_Store +tsconfig.json +tslint.json +*.js.map +*.zip +package-lock.json +karma.conf.js +temp +gulpfile.js +rollup.config.js +rollup.test.config.js +*.html \ No newline at end of file diff --git a/queue/BreakingChanges.md b/queue/BreakingChanges.md new file mode 100644 index 0000000..4554245 --- /dev/null +++ b/queue/BreakingChanges.md @@ -0,0 +1 @@ +# Breaking Changes diff --git a/queue/ChangeLog.md b/queue/ChangeLog.md new file mode 100644 index 0000000..c106f60 --- /dev/null +++ b/queue/ChangeLog.md @@ -0,0 +1,5 @@ +# Changelog + +2018.12 Version 10.0.0-preview + +* Initial Release. API version 2018-03-28 supported. Please see the README for information on the new design. \ No newline at end of file diff --git a/queue/LICENSE b/queue/LICENSE new file mode 100644 index 0000000..2107107 --- /dev/null +++ b/queue/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/queue/README.md b/queue/README.md new file mode 100644 index 0000000..2bba7c1 --- /dev/null +++ b/queue/README.md @@ -0,0 +1,235 @@ +# Azure Storage SDK V10 for JavaScript - Queue + +[![npm version](https://badge.fury.io/js/%40azure%2Fstorage-queue.svg)](https://badge.fury.io/js/%40azure%2Fstorage-queue) + +## Introduction + +This project provides a SDK in JavaScript that makes it easy to consume Microsoft Azure Storage services. + +Please note that this version of the SDK is a compete overhaul of the current [Azure Storage SDK for Node.js and JavaScript in Browsers](https://github.com/azure/azure-storage-node), and is based on the new Storage SDK architecture. + +### Features + +* Queue Storage + * Get/Set Queue Service Properties + * Create/List/Delete Queues + * Enqueue/Dequeue/Peek/Clear/Update/Delete Queue Messages +* Features new + * Asynchronous I/O for all operations using the async methods + * HttpPipeline which enables a high degree of per-request configurability + * 1-to-1 correlation with the Storage REST API for clarity and simplicity + +### Compatibility + +This SDK is compatible with Node.js and browsers, and validated against LTS Node.js versions (>=6.5) and latest versions of Chrome, Firefox and Edge. + +#### Compatible with IE11 + +You need polyfills to make this library work with IE11. The easiest way is to use [@babel/polyfill](https://babeljs.io/docs/en/babel-polyfill), or [polyfill service](https://polyfill.io/v2/docs/). +Or you can load separate polyfills for missed ES feature(s). +This library depends on following ES6 features which need external polyfills loaded. + +* `Promise` +* `String.prototype.startsWith` +* `String.prototype.endsWith` +* `String.prototype.repeat` +* `String.prototype.includes` + +#### Differences between Node.js and browsers + +There are differences between Node.js and browsers runtime. When getting start with this SDK, pay attention to APIs or classes marked with _"ONLY AVAILABLE IN NODE.JS RUNTIME"_ or _"ONLY AVAILABLE IN BROWSERS"_. + +##### Following features, interfaces, classes or functions are only available in Node.js + +* Shared Key Authorization based on account name and account key + * `SharedKeyCredential` +* Shared Access Signature(SAS) generation + * `generateAccountSASQueryParameters()` + * `generateQueueSASQueryParameters()` + +## Getting Started + +### NPM + +The preferred way to install the Azure Storage SDK for JavaScript is to use the npm package manager. Simply type the following into a terminal window: + +```bash +npm install @azure/storage-queue +``` + +In your TypeScript or JavaScript file, import via following: + +```JavaScript +import * as Azure from "@azure/storage-queue"; +``` + +Or + +```JavaScript +const Azure = require("@azure/storage-queue"); +``` + +### JavaScript Bundle + +To use the SDK with JS bundle in the browsers, simply add a script tag to your HTML pages pointing to the downloaded JS bundle file(s): + +```html + +``` + +The JS bundled file is compatible with [UMD](https://github.com/umdjs/umd) standard, if no module system found, following global variable(s) will be exported: + +* `azqueue` + +#### Download + +Download latest released JS bundles from links in the [GitHub release page](https://github.com/Azure/azure-storage-js/releases). Or from following links directly: + +* Queue [https://aka.ms/downloadazurestoragejsqueue](https://aka.ms/downloadazurestoragejsqueue) + +### CORS + +You need to set up [Cross-Origin Resource Sharing (CORS)](https://docs.microsoft.com/zh-cn/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services) rules for your storage account if you need to develop for browsers. Go to Azure portal and Azure Storage Explorer, find your storage account, create new CORS rules for blob/queue/file/table service(s). + +For example, you can create following CORS settings for debugging. But please customize the settings carefully according to your requirements in production environment. + +* Allowed origins: \* +* Allowed verbs: DELETE,GET,HEAD,MERGE,POST,OPTIONS,PUT +* Allowed headers: \* +* Exposed headers: \* +* Maximum age (seconds): 86400 + +## SDK Architecture + +The Azure Storage SDK for JavaScript provides low-level and high-level APIs. + +* ServiceURL, QueueURL, MessagesURL and MessageIdURL objects provide the low-level API functionality and map one-to-one to the [Azure Storage Queue REST APIs](https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api). + +## Code Samples + +```javascript +const { + Aborter, + QueueURL, + MessagesURL, + MessageIdURL, + ServiceURL, + StorageURL, + SharedKeyCredential, + AnonymousCredential, + TokenCredential +} = require(".."); // Change to "@azure/storage-queue" in your package + +async function main() { + // Enter your storage account name and shared key + const account = ""; + const accountKey = ""; + + // Use SharedKeyCredential with storage account and account key + const sharedKeyCredential = new SharedKeyCredential(account, accountKey); + + // Use TokenCredential with OAuth token + const tokenCredential = new TokenCredential("token"); + tokenCredential.token = "renewedToken"; // Renew the token by updating token field of token credential + + // Use AnonymousCredential when url already includes a SAS signature + const anonymousCredential = new AnonymousCredential(); + + // Use sharedKeyCredential, tokenCredential or anonymousCredential to create a pipeline + const pipeline = StorageURL.newPipeline(sharedKeyCredential, { + // httpClient: MyHTTPClient, // A customized HTTP client implementing IHttpClient interface + // logger: MyLogger, // A customized logger implementing IHttpPipelineLogger interface + retryOptions: { maxTries: 4 }, // Retry options + telemetry: { value: "BasicSample V10.0.0" } // Customized telemetry string + }); + + // List queues + const serviceURL = new ServiceURL( + // When using AnonymousCredential, following url should include a valid SAS or support public access + `https://${account}.queue.core.windows.net`, + pipeline + ); + + console.log(`List queues`); + let marker; + do { + const listQueuesResponse = await serviceURL.listQueuesSegment( + Aborter.none, + marker + ); + + marker = listQueuesResponse.nextMarker; + for (const queue of listQueuesResponse.queueItems) { + console.log(`Queue: ${queue.name}`); + } + } while (marker); + + // Create a new queue + const queueName = `newqueue${new Date().getTime()}`; + const queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + const createQueueResponse = await queueURL.create(Aborter.none); + console.log( + `Create queue ${queueName} successfully, service assigned request Id: ${createQueueResponse.requestId}` + ); + + // Enqueue a message into the queue using the enqueue method. + const messagesURL = MessagesURL.fromQueueURL(queueURL); + const enqueueQueueResponse = await messagesURL.enqueue(Aborter.none, "Hello World!"); + console.log( + `Enqueue message successfully, service assigned message Id: ${enqueueQueueResponse.messageId}, service assigned request Id: ${enqueueQueueResponse.requestId}` + ); + + // Peek a message using peek method. + const peekQueueResponse = await messagesURL.peek(Aborter.none); + console.log(`The peeked message is: ${peekQueueResponse.peekedMessageItems[0].messageText}`); + + // You de-queue a message in two steps. Call GetMessage at which point the message becomes invisible to any other code reading messages + // from this queue for a default period of 30 seconds. To finish removing the message from the queue, you call DeleteMessage. + // This two-step process ensures that if your code fails to process a message due to hardware or software failure, another instance + // of your code can get the same message and try again. + const dequeueResponse = await messagesURL.dequeue(Aborter.none); + if (dequeueResponse.dequeuedMessageItems.length == 1) { + const dequeueMessageItem = dequeueResponse.dequeuedMessageItems[0]; + console.log(`Processing & deleting message with content: ${dequeueMessageItem.messageText}`); + const messageIdURL = MessageIdURL.fromMessagesURL(messagesURL, dequeueMessageItem.messageId); + const deleteMessageResponse = await messageIdURL.delete(Aborter.none, dequeueMessageItem.popReceipt); + console.log(`Delete message succesfully, service assigned request Id: ${deleteMessageResponse.requestId}`); + } + + // Delete the queue. + const deleteQueueResponse = await queueURL.delete(Aborter.none); + console.log(`Delete queue successfully, service assigned request Id: ${deleteQueueResponse.requestId}`); +} + +// An async method returns a Promise object, which is compatible with then().catch() coding style. +main() + .then(() => { + console.log("Successfully executed sample."); + }) + .catch(err => { + console.log(err.message); + }); +``` + +## More Code Samples + +* [Queue Storage Examples](https://github.com/azure/azure-storage-js/tree/master/queue/samples) +* [Queue Storage Examples - Test Cases](https://github.com/azure/azure-storage-js/tree/master/queue/test/) + +## License + +This project is licensed under MIT. + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/queue/browser/ThirdPartyNotices.txt b/queue/browser/ThirdPartyNotices.txt new file mode 100644 index 0000000..d042b33 --- /dev/null +++ b/queue/browser/ThirdPartyNotices.txt @@ -0,0 +1,29 @@ +------------------------------------------- START OF THIRD PARTY NOTICE ----------------------------------------- +This file is based on or incorporates material from the projects listed below (Third Party Programs). The original copyright notice and the license under which Microsoft received such Third Party Programs, are set forth below. Such licenses and notices are provided for informational purposes only. +********** + +uuid 3.2.2, Copyright (c) 2010-2016 Robert Kieffer and other contributors + + +The MIT License (MIT) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +********** + +----------------------------------------------- END OF THIRD PARTY NOTICE ------------------------------------------ + diff --git a/queue/gulpfile.js b/queue/gulpfile.js new file mode 100644 index 0000000..f71c26c --- /dev/null +++ b/queue/gulpfile.js @@ -0,0 +1,16 @@ +const gulp = require("gulp"); +const zip = require("gulp-zip"); + +const version = require("./package.json").version; +const zipFileName = `azurestoragejs.queue-${version}.zip`; + +gulp.task("zip", async() => { + return gulp + .src([ + "browser/azure-storage.queue.js", + "browser/azure-storage.queue.min.js", + "browser/*.txt" + ]) + .pipe(zip(zipFileName)) + .pipe(gulp.dest("browser")); +}); \ No newline at end of file diff --git a/queue/karma.conf.js b/queue/karma.conf.js new file mode 100644 index 0000000..ece2a53 --- /dev/null +++ b/queue/karma.conf.js @@ -0,0 +1,82 @@ +module.exports = function(config) { + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: "./", + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ["mocha"], + + plugins: [ + "karma-mocha", + "karma-mocha-reporter", + "karma-chrome-launcher", + "karma-edge-launcher", + "karma-firefox-launcher", + "karma-ie-launcher", + "karma-env-preprocessor" + ], + + // list of files / patterns to load in the browser + files: [ + // polyfill service supporting IE11 missing features + "https://cdn.polyfill.io/v2/polyfill.min.js?features=Promise,String.prototype.startsWith,String.prototype.endsWith,String.prototype.repeat,String.prototype.includes", + "dist-test/index.browser.js" + ], + + // list of files / patterns to exclude + exclude: [], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + "**/*.js": ["env"] + }, + + // inject following environment values into browser testing with window.__env__ + // environment values MUST be exported or set with same console running "karma start" + // https://www.npmjs.com/package/karma-env-preprocessor + envPreprocessor: ["ACCOUNT_NAME", "ACCOUNT_SAS"], + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ["mocha"], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + // 'Chrome', 'Firefox', 'Edge', 'IE' + browsers: ["Chrome"], + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: 1, + + browserNoActivityTimeout: 600000, + + client: { + mocha: { + // change Karma's debug.html to the mocha web reporter + reporter: "html", + timeout: "600000" + } + } + }); +}; diff --git a/queue/lib/Aborter.ts b/queue/lib/Aborter.ts new file mode 100644 index 0000000..1a6251b --- /dev/null +++ b/queue/lib/Aborter.ts @@ -0,0 +1,266 @@ +import { AbortSignalLike, isNode } from "ms-rest-js"; + +/** + * An aborter instance implements AbortSignal interface, can abort HTTP requests. + * + * - Call Aborter.none to create a new Aborter instance without timeout. + * - Call Aborter.timeout() to create a new Aborter instance with timeout. + * + * For an existing instance aborter: + * - Call aborter.withTimeout() to create and return a child Aborter instance with timeout. + * - Call aborter.withValue(key, value) to create and return a child Aborter instance with key/value pair. + * - Call aborter.abort() to abort current instance and all children instances. + * - Call aborter.getValue(key) to search and get value with corresponding key from current aborter to all parents. + * + * @export + * @class Aborter + * @implements {AbortSignalLike} + */ + +export class Aborter implements AbortSignalLike { + /** + * Status of whether aborted or not. + * + * @readonly + * @type {boolean} + * @memberof Aborter + */ + public get aborted(): boolean { + return this._aborted; + } + + /** + * Creates a new Aborter instance without timeout. + * + * @readonly + * @static + * @type {Aborter} + * @memberof Aborter + */ + public static get none(): Aborter { + return new Aborter(undefined, 0); + } + + /** + * Creates a new Aborter instance with timeout in million-seconds. + * Set parameter timeout to 0 will not create a timer. + * + * @static + * @param {number} {timeout} in million-seconds + * @returns {Aborter} + * @memberof Aborter + */ + public static timeout(timeout: number): Aborter { + return new Aborter(undefined, timeout); + } + + /** + * onabort event listener. + * + * @memberof Aborter + */ + public onabort?: ((ev?: Event) => any); + + // tslint:disable-next-line:variable-name + private _aborted: boolean = false; + private timer?: any; + private readonly parent?: Aborter; + private readonly children: Aborter[] = []; // When child object calls dispose(), remove child from here + private readonly abortEventListeners: Array< + (this: AbortSignalLike, ev: any) => any + > = []; + // Pipeline proxies need to use "abortSignal as Aborter" in order to access non AbortSignalLike methods + // immutable primitive types + private readonly key?: string; + private readonly value?: string | number | boolean | null; + // private disposed: boolean = false; + + /** + * Private constructor for internal usage, creates an instance of Aborter. + * + * @param {Aborter} [parent] Optional. Parent aborter. + * @param {number} [timeout=0] Optional. Timeout before abort in millisecond, 0 means no timeout. + * @param {string} [key] Optional. Immutable key in string. + * @param {(string | number | boolean | null)} [value] Optional. Immutable value. + * @memberof Aborter + */ + private constructor( + parent?: Aborter, + timeout: number = 0, + key?: string, + value?: string | number | boolean | null + ) { + this.parent = parent; + this.key = key; + this.value = value; + + if (timeout > 0) { + this.timer = setTimeout(() => { + this.abort.call(this); + }, timeout); + + // When called, the active Timeout object will not require the Node.js event loop + // to remain active. If there is no other activity keeping the event loop running, + // the process may exit before the Timeout object's callback is invoked. + if (this.timer && isNode) { + this.timer!.unref(); + } + } + } + + /** + * Create and return a new Aborter instance, which will be appended as a child node of current Aborter. + * Current Aborter instance becomes father node of the new instance. When current or father Aborter node + * triggers timeout event, all children nodes abort event will be triggered too. + * + * When timeout parameter (in millisecond) is larger than 0, the abort event will be triggered when timeout. + * Otherwise, call abort() method to manually abort. + * + * @param {number} {timeout} Timeout in millisecond. + * @returns {Aborter} The new Aborter instance created. + * @memberof Aborter + */ + public withTimeout(timeout: number): Aborter { + const childCancelContext = new Aborter(this, timeout); + this.children.push(childCancelContext); + return childCancelContext; + } + + /** + * Create and return a new Aborter instance, which will be appended as a child node of current Aborter. + * Current Aborter instance becomes father node of the new instance. When current or father Aborter node + * triggers timeout event, all children nodes abort event will be triggered too. + * + * Immutable key value pair will be set into the new created Aborter instance. + * Call getValue() to find out latest value with corresponding key in the chain of + * [current node] -> [parent node] and [grand parent node].... + * + * @param {string} key + * @param {(string | number | boolean | null)} [value] + * @returns {Aborter} + * @memberof Aborter + */ + public withValue( + key: string, + value?: string | number | boolean | null + ): Aborter { + const childCancelContext = new Aborter(this, 0, key, value); + this.children.push(childCancelContext); + return childCancelContext; + } + + /** + * Find out latest value with corresponding key in the chain of + * [current node] -> [parent node] -> [grand parent node] -> ... -> [root node]. + * + * If key is not found, undefined will be returned. + * + * @param {string} key + * @returns {(string | number | boolean | null | undefined)} + * @memberof Aborter + */ + public getValue(key: string): string | number | boolean | null | undefined { + for ( + let parent: Aborter | undefined = this; + parent; + parent = parent.parent + ) { + if (parent.key === key) { + return parent.value; + } + } + return undefined; + } + + /** + * Trigger abort event immediately, the onabort and all abort event listeners will be triggered. + * Will try to trigger abort event for all children Aborter nodes. + * + * - If there is a timeout, the timer will be cancelled. + * - If aborted is true, nothing will happen. + * + * @returns + * @memberof Aborter + */ + public abort() { + if (this.aborted) { + return; + } + this.cancelTimer(); + + if (this.onabort) { + this.onabort.call(this); + } + + this.abortEventListeners.forEach(listener => { + listener.call(this, undefined); + }); + + this.children.forEach(child => child.cancelByParent()); + + this._aborted = true; + } + + // public dispose() { + // if (this.disposed || this.aborted) { + // return; + // } + + // this.cancelTimer(); + + // // (parent)A <- B <- C(child), if B disposes, when A abort, C will not abort + // if (this.parent) { + // const index = this.parent.children.indexOf(this); + // if (index > -1) { + // this.parent.children.splice(index, 1); + // } + // } + + // this.disposed = true; + // } + + /** + * Added new "abort" event listener, only support "abort" event. + * + * @param {"abort"} _type Only support "abort" event + * @param {(this: AbortSignalLike, ev: any) => any} listener + * @memberof Aborter + */ + public addEventListener( + // tslint:disable-next-line:variable-name + _type: "abort", + listener: (this: AbortSignalLike, ev: any) => any + ): void { + this.abortEventListeners.push(listener); + } + + /** + * Remove "abort" event listener, only support "abort" event. + * + * @param {"abort"} _type Only support "abort" event + * @param {(this: AbortSignalLike, ev: any) => any} listener + * @memberof Aborter + */ + public removeEventListener( + // tslint:disable-next-line:variable-name + _type: "abort", + listener: (this: AbortSignalLike, ev: any) => any + ): void { + const index = this.abortEventListeners.indexOf(listener); + if (index > -1) { + this.abortEventListeners.splice(index, 1); + } + } + + private cancelByParent() { + // if (!this.disposed) { + this.abort(); + // } + } + + private cancelTimer() { + if (this.timer) { + clearTimeout(this.timer); + } + } +} diff --git a/queue/lib/AccountSASPermissions.ts b/queue/lib/AccountSASPermissions.ts new file mode 100644 index 0000000..3a25106 --- /dev/null +++ b/queue/lib/AccountSASPermissions.ts @@ -0,0 +1,166 @@ +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * This is a helper class to construct a string representing the permissions granted by an AccountSAS. Setting a value + * to true means that any SAS which uses these permissions will grant permissions for that operation. Once all the + * values are set, this should be serialized with toString and set as the permissions field on an + * {@link AccountSASSignatureValues} object. It is possible to construct the permissions string without this class, but + * the order of the permissions is particular and this class guarantees correctness. + * + * @export + * @class AccountSASPermissions + */ +export class AccountSASPermissions { + /** + * Parse initializes the AccountSASPermissions fields from a string. + * + * @static + * @param {string} permissions + * @returns {AccountSASPermissions} + * @memberof AccountSASPermissions + */ + public static parse(permissions: string): AccountSASPermissions { + const accountSASPermissions = new AccountSASPermissions(); + + for (const c of permissions) { + switch (c) { + case "r": + accountSASPermissions.read = true; + break; + case "w": + accountSASPermissions.write = true; + break; + case "d": + accountSASPermissions.delete = true; + break; + case "l": + accountSASPermissions.list = true; + break; + case "a": + accountSASPermissions.add = true; + break; + case "c": + accountSASPermissions.create = true; + break; + case "u": + accountSASPermissions.update = true; + break; + case "p": + accountSASPermissions.process = true; + break; + default: + throw new RangeError(`Invalid permission character: ${c}`); + } + } + + return accountSASPermissions; + } + + /** + * Permission to read resources granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public read: boolean = false; + + /** + * Permission to write resources granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public write: boolean = false; + + /** + * Permission to delete queues and messages granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public delete: boolean = false; + + /** + * Permission to list queues granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public list: boolean = false; + + /** + * Permission to add messages, table entities, and append to blobs granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public add: boolean = false; + + /** + * Permission to create queues, blobs and files granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public create: boolean = false; + + /** + * Permissions to update messages and table entities granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public update: boolean = false; + + /** + * Permission to get and delete messages granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public process: boolean = false; + + /** + * Produces the SAS permissions string for an Azure Storage account. + * Call this method to set AccountSASSignatureValues Permissions field. + * + * Using this method will guarantee the resource types are in + * an order accepted by the service. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * + * @returns {string} + * @memberof AccountSASPermissions + */ + public toString(): string { + // The order of the characters should be as specified here to ensure correctness: + // https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + // Use a string array instead of string concatenating += operator for performance + const permissions: string[] = []; + if (this.read) { + permissions.push("r"); + } + if (this.write) { + permissions.push("w"); + } + if (this.delete) { + permissions.push("d"); + } + if (this.list) { + permissions.push("l"); + } + if (this.add) { + permissions.push("a"); + } + if (this.create) { + permissions.push("c"); + } + if (this.update) { + permissions.push("u"); + } + if (this.process) { + permissions.push("p"); + } + return permissions.join(""); + } +} diff --git a/queue/lib/AccountSASResourceTypes.ts b/queue/lib/AccountSASResourceTypes.ts new file mode 100644 index 0000000..55defd0 --- /dev/null +++ b/queue/lib/AccountSASResourceTypes.ts @@ -0,0 +1,90 @@ +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * This is a helper class to construct a string representing the resources accessible by an AccountSAS. Setting a value + * to true means that any SAS which uses these permissions will grant access to that resource type. Once all the + * values are set, this should be serialized with toString and set as the resources field on an + * {@link AccountSASSignatureValues} object. It is possible to construct the resources string without this class, but + * the order of the resources is particular and this class guarantees correctness. + * + * @export + * @class AccountSASResourceTypes + */ +export class AccountSASResourceTypes { + /** + * Creates an {@link AccountSASResourceType} from the specified resource types string. This method will throw an + * Error if it encounters a character that does not correspond to a valid resource type. + * + * @static + * @param {string} resourceTypes + * @returns {AccountSASResourceTypes} + * @memberof AccountSASResourceTypes + */ + public static parse(resourceTypes: string): AccountSASResourceTypes { + const accountSASResourceTypes = new AccountSASResourceTypes(); + + for (const c of resourceTypes) { + switch (c) { + case "s": + accountSASResourceTypes.service = true; + break; + case "c": + accountSASResourceTypes.container = true; + break; + case "o": + accountSASResourceTypes.object = true; + break; + default: + throw new RangeError(`Invalid resource type: ${c}`); + } + } + + return accountSASResourceTypes; + } + + /** + * Permission to access service level APIs granted. + * + * @type {boolean} + * @memberof AccountSASResourceTypes + */ + public service: boolean = false; + + /** + * Permission to access container level APIs (Blob Containers, Tables, Queues, File Shares) granted. + * + * @type {boolean} + * @memberof AccountSASResourceTypes + */ + public container: boolean = false; + + /** + * Permission to access object level APIs (Blobs, Table Entities, Queue Messages, Files) granted. + * + * @type {boolean} + * @memberof AccountSASResourceTypes + */ + public object: boolean = false; + + /** + * Converts the given resource types to a string. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * + * @returns {string} + * @memberof AccountSASResourceTypes + */ + public toString(): string { + const resourceTypes: string[] = []; + if (this.service) { + resourceTypes.push("s"); + } + if (this.container) { + resourceTypes.push("c"); + } + if (this.object) { + resourceTypes.push("o"); + } + return resourceTypes.join(""); + } +} diff --git a/queue/lib/AccountSASServices.ts b/queue/lib/AccountSASServices.ts new file mode 100644 index 0000000..1dc9f5e --- /dev/null +++ b/queue/lib/AccountSASServices.ts @@ -0,0 +1,102 @@ +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * This is a helper class to construct a string representing the services accessible by an AccountSAS. Setting a value + * to true means that any SAS which uses these permissions will grant access to that service. Once all the + * values are set, this should be serialized with toString and set as the services field on an + * {@link AccountSASSignatureValues} object. It is possible to construct the services string without this class, but + * the order of the services is particular and this class guarantees correctness. + * + * @export + * @class AccountSASServices + */ +export class AccountSASServices { + /** + * Creates an {@link AccountSASServices} from the specified services string. This method will throw an + * Error if it encounters a character that does not correspond to a valid service. + * + * @static + * @param {string} services + * @returns {AccountSASServices} + * @memberof AccountSASServices + */ + public static parse(services: string): AccountSASServices { + const accountSASServices = new AccountSASServices(); + + for (const c of services) { + switch (c) { + case "b": + accountSASServices.blob = true; + break; + case "f": + accountSASServices.file = true; + break; + case "q": + accountSASServices.queue = true; + break; + case "t": + accountSASServices.table = true; + break; + default: + throw new RangeError(`Invalid service character: ${c}`); + } + } + + return accountSASServices; + } + + /** + * Permission to access blob resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public blob: boolean = false; + + /** + * Permission to access file resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public file: boolean = false; + + /** + * Permission to access queue resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public queue: boolean = false; + + /** + * Permission to access table resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public table: boolean = false; + + /** + * Converts the given services to a string. + * + * @returns {string} + * @memberof AccountSASServices + */ + public toString(): string { + const services: string[] = []; + if (this.blob) { + services.push("b"); + } + if (this.table) { + services.push("t"); + } + if (this.queue) { + services.push("q"); + } + if (this.file) { + services.push("f"); + } + return services.join(""); + } +} diff --git a/queue/lib/BrowserPolicyFactory.ts b/queue/lib/BrowserPolicyFactory.ts new file mode 100644 index 0000000..db09627 --- /dev/null +++ b/queue/lib/BrowserPolicyFactory.ts @@ -0,0 +1,23 @@ +import { + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions +} from "ms-rest-js"; + +import { BrowserPolicy } from "./policies/BrowserPolicy"; + +/** + * BrowserPolicyFactory is a factory class helping generating BrowserPolicy objects. + * + * @export + * @class BrowserPolicyFactory + * @implements {RequestPolicyFactory} + */ +export class BrowserPolicyFactory implements RequestPolicyFactory { + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): BrowserPolicy { + return new BrowserPolicy(nextPolicy, options); + } +} diff --git a/queue/lib/IAccountSASSignatureValues.ts b/queue/lib/IAccountSASSignatureValues.ts new file mode 100644 index 0000000..8cc4ce2 --- /dev/null +++ b/queue/lib/IAccountSASSignatureValues.ts @@ -0,0 +1,159 @@ +import { AccountSASPermissions } from "./AccountSASPermissions"; +import { AccountSASResourceTypes } from "./AccountSASResourceTypes"; +import { AccountSASServices } from "./AccountSASServices"; +import { SharedKeyCredential } from "./credentials/SharedKeyCredential"; +import { IIPRange, ipRangeToString } from "./IIPRange"; +import { SASProtocol, SASQueryParameters } from "./SASQueryParameters"; +import { SERVICE_VERSION } from "./utils/constants"; +import { truncatedISO8061Date } from "./utils/utils.common"; + +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * IAccountSASSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage account. Once + * all the values here are set appropriately, call generateSASQueryParameters() to obtain a representation of the SAS + * which can actually be applied to queue urls. Note: that both this class and {@link SASQueryParameters} exist because + * the former is mutable and a logical representation while the latter is immutable and used to generate actual REST + * requests. + * + * @see https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1 + * for more conceptual information on SAS + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * for descriptions of the parameters, including which are required + * + * @export + * @class IAccountSASSignatureValues + */ +export interface IAccountSASSignatureValues { + /** + * If not provided, this defaults to the service version targeted by this version of the library. + * + * @type {string} + * @memberof IAccountSASSignatureValues + */ + version?: string; + + /** + * Optional. SAS protocols allowed. + * + * @type {SASProtocol} + * @memberof IAccountSASSignatureValues + */ + protocol?: SASProtocol; + + /** + * Optional. When the SAS will take effect. + * + * @type {Date} + * @memberof IAccountSASSignatureValues + */ + startTime?: Date; + + /** + * The time after which the SAS will no longer work. + * + * @type {Date} + * @memberof IAccountSASSignatureValues + */ + expiryTime: Date; + + /** + * Specifies which operations the SAS user may perform. Please refer to {@link AccountSASPermissions} for help + * constructing the permissions string. + * + * @type {string} + * @memberof IAccountSASSignatureValues + */ + permissions: string; + + /** + * Optional. IP range allowed. + * + * @type {IIPRange} + * @memberof IAccountSASSignatureValues + */ + ipRange?: IIPRange; + + /** + * The values that indicate the services accessible with this SAS. Please refer to {@link AccountSASService} to + * construct this value. + * + * @type {string} + * @memberof IAccountSASSignatureValues + */ + services: string; + + /** + * The values that indicate the resource types accessible with this SAS. Please refer + * to {@link AccountSASResourceType} to construct this value. + * + * @type {string} + * @memberof IAccountSASSignatureValues + */ + resourceTypes: string; +} + +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * Generates a {@link SASQueryParameters} object which contains all SAS query parameters needed to make an actual + * REST request. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * + * @param {SharedKeyCredential} sharedKeyCredential + * @returns {SASQueryParameters} + * @memberof IAccountSASSignatureValues + */ +export function generateAccountSASQueryParameters( + accountSASSignatureValues: IAccountSASSignatureValues, + sharedKeyCredential: SharedKeyCredential +): SASQueryParameters { + const version = accountSASSignatureValues.version + ? accountSASSignatureValues.version + : SERVICE_VERSION; + + const parsedPermissions = AccountSASPermissions.parse( + accountSASSignatureValues.permissions + ).toString(); + const parsedServices = AccountSASServices.parse( + accountSASSignatureValues.services + ).toString(); + const parsedResourceTypes = AccountSASResourceTypes.parse( + accountSASSignatureValues.resourceTypes + ).toString(); + + const stringToSign = [ + sharedKeyCredential.accountName, + parsedPermissions, + parsedServices, + parsedResourceTypes, + accountSASSignatureValues.startTime + ? truncatedISO8061Date(accountSASSignatureValues.startTime, false) + : "", + truncatedISO8061Date(accountSASSignatureValues.expiryTime, false), + accountSASSignatureValues.ipRange + ? ipRangeToString(accountSASSignatureValues.ipRange) + : "", + accountSASSignatureValues.protocol + ? accountSASSignatureValues.protocol + : "", + version, + "" // Account SAS requires an additional newline character + ].join("\n"); + + const signature: string = sharedKeyCredential.computeHMACSHA256(stringToSign); + + return new SASQueryParameters( + version, + signature, + parsedPermissions, + parsedServices, + parsedResourceTypes, + accountSASSignatureValues.protocol, + accountSASSignatureValues.startTime, + accountSASSignatureValues.expiryTime, + accountSASSignatureValues.ipRange + ); +} diff --git a/queue/lib/IIPRange.ts b/queue/lib/IIPRange.ts new file mode 100644 index 0000000..aa15037 --- /dev/null +++ b/queue/lib/IIPRange.ts @@ -0,0 +1,37 @@ +/** + * Allowed IP range for a SAS. + * + * @export + * @interface IIPRange + */ +export interface IIPRange { + /** + * Starting IP address in the IP range. + * If end IP doesn't provide, start IP will the only IP allowed. + * + * @type {string} + * @memberof IPRange + */ + start: string; + /** + * Optional. IP address that ends the IP range. + * If not provided, start IP will the only IP allowed. + * + * @type {string} + * @memberof IPRange + */ + end?: string; +} + +/** + * Generate IPRange format string. For example: + * + * "8.8.8.8" or "1.1.1.1-255.255.255.255" + * + * @export + * @param {IIPRange} ipRange + * @returns {string} + */ +export function ipRangeToString(ipRange: IIPRange): string { + return ipRange.end ? `${ipRange.start}-${ipRange.end}` : ipRange.start; +} diff --git a/queue/lib/IQueueSASSignatureValues.ts b/queue/lib/IQueueSASSignatureValues.ts new file mode 100644 index 0000000..f62a9d7 --- /dev/null +++ b/queue/lib/IQueueSASSignatureValues.ts @@ -0,0 +1,173 @@ +import { QueueSASPermissions } from "./QueueSASPermissions"; +import { SharedKeyCredential } from "./credentials/SharedKeyCredential"; +import { IIPRange, ipRangeToString } from "./IIPRange"; +import { SASProtocol } from "./SASQueryParameters"; +import { SASQueryParameters } from "./SASQueryParameters"; +import { SERVICE_VERSION } from "./utils/constants"; +import { truncatedISO8061Date } from "./utils/utils.common"; + +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * IQueueSASSignatureValues is used to help generating Queue service SAS tokens for queues. + * + * @export + * @class IQueueSASSignatureValues + */ +export interface IQueueSASSignatureValues { + /** + * The version of the service this SAS will target. If not specified, it will default to the version targeted by the + * library. + * + * @type {string} + * @memberof IQueueSASSignatureValues + */ + version?: string; + + /** + * Optional. SAS protocols, HTTPS only or HTTPSandHTTP + * + * @type {SASProtocol} + * @memberof IQueueSASSignatureValues + */ + protocol?: SASProtocol; + + /** + * Optional. When the SAS will take effect. + * + * @type {Date} + * @memberof IQueueSASSignatureValues + */ + startTime?: Date; + + /** + * Optional only when identifier is provided. The time after which the SAS will no longer work. + * + * @type {Date} + * @memberof IQueueSASSignatureValues + */ + expiryTime?: Date; + + /** + * Optional only when identifier is provided. + * Please refer to {@link QueueSASPermissions} + * being accessed for help constructing the permissions string. + * + * @type {string} + * @memberof IQueueSASSignatureValues + */ + permissions?: string; + + /** + * Optional. IP ranges allowed in this SAS. + * + * @type {IIPRange} + * @memberof IQueueSASSignatureValues + */ + ipRange?: IIPRange; + + /** + * The name of the queue the SAS user may access. + * + * @type {string} + * @memberof IQueueSASSignatureValues + */ + queueName: string; + + /** + * Optional. The name of the access policy on the queue this SAS references if any. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/establishing-a-stored-access-policy + * + * @type {string} + * @memberof IQueueSASSignatureValues + */ + identifier?: string; +} + +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * Creates an instance of SASQueryParameters. + * + * Only accepts required settings needed to create a SAS. For optional settings please + * set corresponding properties directly, such as permissions, startTime and identifier. + * + * WARNING: When identifier is not provided, permissions and expiryTime are required. + * You MUST assign value to identifier or expiryTime & permissions manually if you initial with + * this constructor. + * + * @export + * @param {IQueueSASSignatureValues} queueSASSignatureValues + * @param {SharedKeyCredential} sharedKeyCredential + * @returns {SASQueryParameters} + */ +export function generateQueueSASQueryParameters( + queueSASSignatureValues: IQueueSASSignatureValues, + sharedKeyCredential: SharedKeyCredential +): SASQueryParameters { + if ( + !queueSASSignatureValues.identifier && + (!queueSASSignatureValues.permissions && !queueSASSignatureValues.expiryTime) + ) { + throw new RangeError( + "Must provide 'permissions' and 'expiryTime' for Queue SAS generation when 'identifier' is not provided." + ); + } + + const version = queueSASSignatureValues.version + ? queueSASSignatureValues.version + : SERVICE_VERSION; + let verifiedPermissions: string | undefined; + + // Calling parse and toString guarantees the proper ordering and throws on invalid characters. + if (queueSASSignatureValues.permissions) { + verifiedPermissions = QueueSASPermissions.parse( + queueSASSignatureValues.permissions + ).toString(); + } + + // Signature is generated on the un-url-encoded values. + const stringToSign = [ + verifiedPermissions ? verifiedPermissions : "", + queueSASSignatureValues.startTime + ? truncatedISO8061Date(queueSASSignatureValues.startTime, false) + : "", + queueSASSignatureValues.expiryTime + ? truncatedISO8061Date(queueSASSignatureValues.expiryTime, false) + : "", + getCanonicalName( + sharedKeyCredential.accountName, + queueSASSignatureValues.queueName + ), + queueSASSignatureValues.identifier, + queueSASSignatureValues.ipRange + ? ipRangeToString(queueSASSignatureValues.ipRange) + : "", + queueSASSignatureValues.protocol ? queueSASSignatureValues.protocol : "", + version + ].join("\n"); + + const signature = sharedKeyCredential.computeHMACSHA256(stringToSign); + + return new SASQueryParameters( + version, + signature, + verifiedPermissions, + undefined, + undefined, + queueSASSignatureValues.protocol, + queueSASSignatureValues.startTime, + queueSASSignatureValues.expiryTime, + queueSASSignatureValues.ipRange, + queueSASSignatureValues.identifier + ); +} + +function getCanonicalName( + accountName: string, + queueName: string +): string { + // Queue: "/queue/account/queueName" + return `/queue/${accountName}/${queueName}`; +} diff --git a/queue/lib/LoggingPolicyFactory.ts b/queue/lib/LoggingPolicyFactory.ts new file mode 100644 index 0000000..7120bb8 --- /dev/null +++ b/queue/lib/LoggingPolicyFactory.ts @@ -0,0 +1,45 @@ +import { + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions +} from "ms-rest-js"; + +import { LoggingPolicy } from "./policies/LoggingPolicy"; + +/** + * RequestLogOptions configures the retry policy's behavior. + * + * @export + * @interface IRequestLogOptions + */ +export interface IRequestLogOptions { + /** + * LogWarningIfTryOverThreshold logs a warning if a tried operation takes longer than the specified + * duration in ms. Default is 3000ms. + * @type {number} + * @memberof IRequestLogOptions + */ + logWarningIfTryOverThreshold: number; +} + +/** + * LoggingPolicyFactory is a factory class helping generating LoggingPolicy objects. + * + * @export + * @class LoggingPolicyFactory + * @implements {RequestPolicyFactory} + */ +export class LoggingPolicyFactory implements RequestPolicyFactory { + private readonly loggingOptions?: IRequestLogOptions; + + constructor(loggingOptions?: IRequestLogOptions) { + this.loggingOptions = loggingOptions; + } + + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): LoggingPolicy { + return new LoggingPolicy(nextPolicy, options, this.loggingOptions); + } +} diff --git a/queue/lib/MessageIDURL.ts b/queue/lib/MessageIDURL.ts new file mode 100644 index 0000000..7e56881 --- /dev/null +++ b/queue/lib/MessageIDURL.ts @@ -0,0 +1,121 @@ +import * as Models from "./generated/models"; +import { Aborter } from "./Aborter"; +import { MessageId } from "./generated/operations"; +import { Pipeline } from "./Pipeline"; +import { MessagesURL } from "./MessagesURL"; +import { StorageURL } from "./StorageURL"; +import { appendToURLPath } from "./utils/utils.common"; + +/** + * A MessageIdURL represents a URL to a specific Azure Storage Queue message allowing you to manipulate the message. + * + * @export + * @class MessageIdURL + * @extends {StorageURL} + */ +export class MessageIdURL extends StorageURL { + /** + * Creates a MessageIdURL object from MessagesURL + * @param messagesURL + * @param messageId + */ + public static fromMessagesURL( + messagesURL: MessagesURL, + messageId: string + ): MessageIdURL { + return new MessageIdURL( + appendToURLPath(messagesURL.url, messageId), + messagesURL.pipeline + ); + } + + /** + * messageIdContext provided by protocol layer. + * + * @private + * @type {MessageId} + * @memberof MessageIdURL + */ + private messageIdContext: MessageId; + + /** + * Creates an instance of MessageIdURL. + * @param {string} url A URL string pointing to Azure Storage queue's message, such as + * "https://myaccount.queue.core.windows.net/myqueue/messages/messageid". You can + * append a SAS if using AnonymousCredential, such as + * "https://myaccount.queue.core.windows.net/myqueue/messages/messageid?sasString". + * @param {Pipeline} pipeline Call StorageURL.newPipeline() to create a default + * pipeline, or provide a customized pipeline. + * @memberof MessageIdURL + */ + constructor(url: string, pipeline: Pipeline) { + super(url, pipeline); + this.messageIdContext = new MessageId(this.storageClientContext); + } + + /** + * Creates a new MessageIdURL object identical to the source but with the + * specified request policy pipeline. + * + * @param {Pipeline} pipeline + * @returns {MessageIdURL} + * @memberof MessageIdURL + */ + public withPipeline(pipeline: Pipeline): MessageIdURL { + return new MessageIdURL(this.url, pipeline); + } + + /** + * Delete permanently removes the specified message from its queue. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/delete-message2 + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {string} popReceipt A valid pop receipt value returned from an earlier call to the dequeue messages or update message operation. + * @returns {Promise} + * @memberof MessageIdURL + */ + public async delete( + aborter: Aborter, + popReceipt: string + ): Promise { + return this.messageIdContext.deleteMethod(popReceipt, { + abortSignal: aborter + }); + } + + /** + * Update changes a message's visibility timeout and contents. + * The message content must be a UTF-8 encoded string that is up to 64KB in size. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/update-message + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {string} popReceipt A valid pop receipt value returned from an earlier call to the dequeue messages or update message operation. + * @param {number} visibilityTimeout Specifies the new visibility timeout value, in seconds, + * relative to server time. The new value must be larger than or equal to 0, + * and cannot be larger than 7 days. The visibility timeout of a message cannot + * be set to a value later than the expiry time. + * A message can be updated until it has been deleted or has expired. + * @param {string} message Message to update. + * @returns {Promise} + * @memberof MessageIdURL + */ + public async update( + aborter: Aborter, + popReceipt: string, + visibilityTimeout: number, + message: string + ): Promise { + return this.messageIdContext.update( + { + messageText: message + }, + popReceipt, + visibilityTimeout, + { + abortSignal: aborter + } + ); + } +} diff --git a/queue/lib/MessagesURL.ts b/queue/lib/MessagesURL.ts new file mode 100644 index 0000000..bfef7b5 --- /dev/null +++ b/queue/lib/MessagesURL.ts @@ -0,0 +1,282 @@ +import { HttpResponse } from "ms-rest-js"; +import * as Models from "../lib/generated/models"; +import { Aborter } from "./Aborter"; +import { Messages } from "./generated/operations"; +import { Pipeline } from "./Pipeline"; +import { QueueURL } from "./QueueURL"; +import { StorageURL } from "./StorageURL"; +import { appendToURLPath } from "./utils/utils.common"; + +export declare type MessagesEnqueueResponse = { + /** + * @member {string} messageId The ID of the enqueued Message. + */ + messageId: string; + /** + * @member {string} popReceipt This value is required to delete the Message. + * If deletion fails using this popreceipt then the message has been dequeued + * by another client. + */ + popReceipt: string; + /** + * @member {Date} insertionTime The time that the message was inserted into the + * Queue. + */ + insertionTime: Date; + /** + * @member {Date} expirationTime The time that the message will expire and be + * automatically deleted. + */ + expirationTime: Date; + /** + * @member {Date} timeNextVisible The time that the message will again become + * visible in the Queue. + */ + timeNextVisible: Date; +} & Models.MessagesEnqueueHeaders & { + /** + * The underlying HTTP response. + */ + _response: HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: Models.MessagesEnqueueHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: Models.EnqueuedMessage[]; + }; + }; + +export declare type MessagesDequeueResponse = { + dequeuedMessageItems: Models.DequeuedMessageItem[]; +} & Models.MessagesDequeueHeaders & { + /** + * The underlying HTTP response. + */ + _response: HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: Models.MessagesDequeueHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: Models.DequeuedMessageItem[]; + }; + }; + +export declare type MessagesPeekResponse = { + peekedMessageItems: Models.PeekedMessageItem[]; +} & Models.MessagesPeekHeaders & { + /** + * The underlying HTTP response. + */ + _response: HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: Models.MessagesPeekHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: Models.PeekedMessageItem[]; + }; + }; + +/** + * A MessagesURL represents a URL to an Azure Storage Queue's messages allowing you to manipulate its messages. + * + * @export + * @class MessagesURL + * @extends {StorageURL} + */ +export class MessagesURL extends StorageURL { + /** + * Creates a MessagesURL object from QueueURL + * @param queueURL + * @param queueName + */ + public static fromQueueURL(queueURL: QueueURL): MessagesURL { + return new MessagesURL( + appendToURLPath(queueURL.url, "messages"), + queueURL.pipeline + ); + } + + /** + * messagesContext provided by protocol layer. + * + * @private + * @type {Messages} + * @memberof MessagesURL + */ + private messagesContext: Messages; + + /** + * Creates an instance of MessagesURL. + * @param {string} url A URL string pointing to Azure Storage queue's messages, such as + * "https://myaccount.queue.core.windows.net/myqueue/messages". You can + * append a SAS if using AnonymousCredential, such as + * "https://myaccount.queue.core.windows.net/myqueue/messages?sasString". + * @param {Pipeline} pipeline Call StorageURL.newPipeline() to create a default + * pipeline, or provide a customized pipeline. + * @memberof MessagesURL + */ + constructor(url: string, pipeline: Pipeline) { + super(url, pipeline); + this.messagesContext = new Messages(this.storageClientContext); + } + + /** + * Creates a new MessagesURL object identical to the source but with the + * specified request policy pipeline. + * + * @param {Pipeline} pipeline + * @returns {MessagesURL} + * @memberof MessagesURL + */ + public withPipeline(pipeline: Pipeline): MessagesURL { + return new MessagesURL(this.url, pipeline); + } + + /** + * Clear deletes all messages from a queue. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/clear-messages + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @returns {Promise} + * @memberof MessagesURL + */ + public async clear(aborter: Aborter): Promise { + return this.messagesContext.clear({ + abortSignal: aborter + }); + } + + /** + * Enqueue adds a new message to the back of a queue. The visibility timeout specifies how long + * the message should be invisible to Dequeue and Peek operations. + * The message content must be a UTF-8 encoded string that is up to 64KB in size. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/put-message + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {string} messageText + * @param {Models.MessagesEnqueueOptionalParams} [options] + * @returns {Promise} + * @memberof MessagesURL + */ + public async enqueue( + aborter: Aborter, + messageText: string, + options: Models.MessagesEnqueueOptionalParams = {} + ): Promise { + const response = await this.messagesContext.enqueue( + { + messageText: messageText + }, + { + abortSignal: aborter, + ...options + } + ); + const item = response[0]; + return { + _response: response._response, + date: response.date, + requestId: response.requestId, + version: response.version, + errorCode: response.errorCode, + messageId: item.messageId, + popReceipt: item.popReceipt, + timeNextVisible: item.timeNextVisible, + insertionTime: item.insertionTime, + expirationTime: item.expirationTime + }; + } + + /** + * Dequeue retrieves one or more messages from the front of the queue. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-messages + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {Models.MessagesDequeueOptionalParams} [options] + * @returns {Promise} + * @memberof MessagesURL + */ + public async dequeue( + aborter: Aborter, + options: Models.MessagesDequeueOptionalParams = {} + ): Promise { + const response = await this.messagesContext.dequeue({ + abortSignal: aborter, + ...options + }); + + const res: MessagesDequeueResponse = { + _response: response._response, + date: response.date, + requestId: response.requestId, + dequeuedMessageItems: [], + version: response.version, + errorCode: response.errorCode + }; + + for (const item of response) { + res.dequeuedMessageItems.push(item); + } + + return res; + } + + /** + * Peek retrieves one or more messages from the front of the queue but does not alter the visibility of the message. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/peek-messages + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {Models.MessagesPeekOptionalParams} [options] + * @returns {Promise} + * @memberof MessagesURL + */ + public async peek( + aborter: Aborter, + options: Models.MessagesPeekOptionalParams = {} + ): Promise { + const response = await this.messagesContext.peek({ + abortSignal: aborter, + ...options + }); + + const res: MessagesPeekResponse = { + _response: response._response, + date: response.date, + requestId: response.requestId, + peekedMessageItems: [], + version: response.version, + errorCode: response.errorCode + }; + + for (const item of response) { + res.peekedMessageItems.push(item); + } + + return res; + } +} diff --git a/queue/lib/Pipeline.ts b/queue/lib/Pipeline.ts new file mode 100644 index 0000000..69b78a0 --- /dev/null +++ b/queue/lib/Pipeline.ts @@ -0,0 +1,84 @@ +import { + BaseRequestPolicy, + HttpClient as IHttpClient, + HttpHeaders, + HttpOperationResponse, + HttpPipelineLogger as IHttpPipelineLogger, + HttpPipelineLogLevel, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions, + ServiceClientOptions, + WebResource +} from "ms-rest-js"; + +// Export following interfaces and types for customers who want to implement their +// own RequestPolicy or HTTPClient +export { + IHttpClient, + IHttpPipelineLogger, + HttpHeaders, + HttpPipelineLogLevel, + HttpOperationResponse, + WebResource, + BaseRequestPolicy, + RequestPolicyFactory, + RequestPolicy, + RequestPolicyOptions +}; + +/** + * Option interface for Pipeline constructor. + * + * @export + * @interface IPipelineOptions + */ +export interface IPipelineOptions { + logger?: IHttpPipelineLogger; + HTTPClient?: IHttpClient; +} + +/** + * A Pipeline class containing HTTP request policies. + * You can create a default Pipeline by calling StorageURL.newPipeline(). + * Or you can create a Pipeline with your own policies by the constructor of Pipeline. + * Refer to StorageURL.newPipeline() and provided policies as reference before + * implementing your customized Pipeline. + * + * @export + * @class Pipeline + */ +export class Pipeline { + public readonly factories: RequestPolicyFactory[]; + public readonly options: IPipelineOptions; + + /** + * Creates an instance of Pipeline. Customize HTTPClient by implementing IHttpClient interface. + * + * @param {RequestPolicyFactory[]} factories + * @param {IPipelineOptions} [options={}] + * @memberof Pipeline + */ + constructor( + factories: RequestPolicyFactory[], + options: IPipelineOptions = {} + ) { + this.factories = factories; + this.options = options; + } + + /** + * Transfer Pipeline object to ServiceClientOptions object which required by + * ServiceClient constructor. + * + * @returns {ServiceClientOptions} + * @memberof Pipeline + */ + public toServiceClientOptions(): ServiceClientOptions { + return { + httpClient: this.options.HTTPClient, + httpPipelineLogger: this.options.logger, + requestPolicyFactories: this.factories + }; + } +} diff --git a/queue/lib/QueueSASPermissions.ts b/queue/lib/QueueSASPermissions.ts new file mode 100644 index 0000000..6113bd5 --- /dev/null +++ b/queue/lib/QueueSASPermissions.ts @@ -0,0 +1,103 @@ +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * This is a helper class to construct a string representing the permissions granted by a ServiceSAS to a Queue. Setting + * a value to true means that any SAS which uses these permissions will grant permissions for that operation. Once all + * the values are set, this should be serialized with toString and set as the permissions field on a + * {@link ServiceSASSignatureValues} object. It is possible to construct the permissions string without this class, but + * the order of the permissions is particular and this class guarantees correctness. + * + * @export + * @class QueueSASPermissions + */ +export class QueueSASPermissions { + /** + * Creates a {@link QueueSASPermission} from the specified permissions string. This method will throw an + * Error if it encounters a character that does not correspond to a valid permission. + * + * @static + * @param {string} permissions + * @returns {QueueSASPermissions} + * @memberof QueueSASPermissions + */ + public static parse(permissions: string): QueueSASPermissions { + const queueSASPermissions = new QueueSASPermissions(); + + for (const char of permissions) { + switch (char) { + case "r": + queueSASPermissions.read = true; + break; + case "a": + queueSASPermissions.add = true; + break; + case "u": + queueSASPermissions.update = true; + break; + case "p": + queueSASPermissions.process = true; + break; + default: + throw new RangeError(`Invalid permission: ${char}`); + } + } + + return queueSASPermissions; + } + + /** + * Specifies Read access granted. + * + * @type {boolean} + * @memberof QueueSASPermissions + */ + public read: boolean = false; + + /** + * Specifies Add access granted. + * + * @type {boolean} + * @memberof QueueSASPermissions + */ + public add: boolean = false; + + /** + * Specifies Update access granted. + * + * @type {boolean} + * @memberof QueueSASPermissions + */ + public update: boolean = false; + + /** + * Specifies Process access granted. + * + * @type {boolean} + * @memberof QueueSASPermissions + */ + public process: boolean = false; + + /** + * Converts the given permissions to a string. Using this method will guarantee the permissions are in an + * order accepted by the service. + * + * @returns {string} A string which represents the QueueSASPermissions + * @memberof QueueSASPermissions + */ + public toString(): string { + const permissions: string[] = []; + if (this.read) { + permissions.push("r"); + } + if (this.add) { + permissions.push("a"); + } + if (this.update) { + permissions.push("u"); + } + if (this.process) { + permissions.push("p"); + } + return permissions.join(""); + } +} diff --git a/queue/lib/QueueURL.ts b/queue/lib/QueueURL.ts new file mode 100644 index 0000000..d8dc8dd --- /dev/null +++ b/queue/lib/QueueURL.ts @@ -0,0 +1,274 @@ +import { HttpResponse } from "ms-rest-js"; +import * as Models from "../lib/generated/models"; +import { Aborter } from "./Aborter"; +import { Queue } from "./generated/operations"; +import { IMetadata } from "./models"; +import { Pipeline } from "./Pipeline"; +import { ServiceURL } from "./ServiceURL"; +import { StorageURL } from "./StorageURL"; +import { appendToURLPath, truncatedISO8061Date } from "./utils/utils.common"; + +export interface IQueueCreateOptions { + metadata?: IMetadata; +} + +export interface ISignedIdentifier { + /** + * @member {string} id a unique id + */ + id: string; + /** + * @member {AccessPolicy} accessPolicy + */ + accessPolicy: { + /** + * @member {Date} start the date-time the policy is active. + */ + start: Date; + /** + * @member {string} expiry the date-time the policy expires. + */ + expiry: Date; + /** + * @member {string} permission the permissions for the acl policy + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/set-queue-acl + */ + permission: string; + }; +} + +export declare type QueueGetAccessPolicyResponse = { + signedIdentifiers: ISignedIdentifier[]; +} & Models.QueueGetAccessPolicyHeaders & { + /** + * The underlying HTTP response. + */ + _response: HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: Models.QueueGetAccessPolicyHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: Models.SignedIdentifier[]; + }; + }; + +/** + * A QueueURL represents a URL to the Azure Storage queue. + * + * @export + * @class QueueURL + * @extends {StorageURL} + */ +export class QueueURL extends StorageURL { + /** + * Creates a QueueURL object from ServiceURL + * @param serviceURL + * @param queueName + */ + public static fromServiceURL( + serviceURL: ServiceURL, + queueName: string + ): QueueURL { + return new QueueURL( + appendToURLPath(serviceURL.url, queueName), + serviceURL.pipeline + ); + } + + /** + * queueContext provided by protocol layer. + * + * @private + * @type {Queue} + * @memberof QueueURL + */ + private queueContext: Queue; + + /** + * Creates an instance of QueueURL. + * @param {string} url A URL string pointing to Azure Storage queue, such as + * "https://myaccount.queue.core.windows.net/myqueue". You can + * append a SAS if using AnonymousCredential, such as + * "https://myaccount.queue.core.windows.net/myqueue?sasString". + * @param {Pipeline} pipeline Call StorageURL.newPipeline() to create a default + * pipeline, or provide a customized pipeline. + * @memberof QueueURL + */ + constructor(url: string, pipeline: Pipeline) { + super(url, pipeline); + this.queueContext = new Queue(this.storageClientContext); + } + + /** + * Creates a new QueueURL object identical to the source but with the + * specified request policy pipeline. + * + * @param {Pipeline} pipeline + * @returns {QueueURL} + * @memberof QueueURL + */ + public withPipeline(pipeline: Pipeline): QueueURL { + return new QueueURL(this.url, pipeline); + } + + /** + * Creates a new queue under the specified account. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/create-queue4 + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {IQueueCreateOptions} [options] + * @returns {Promise} + * @memberof QueueURL + */ + public async create( + aborter: Aborter, + options: IQueueCreateOptions = {} + ): Promise { + return this.queueContext.create({ + ...options, + abortSignal: aborter + }); + } + + /** + * Gets all user-defined metadata and system properties for the specified + * queue. Metadata is associated with the queue as name-values pairs. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-queue-metadata + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @returns {Promise} + * @memberof QueueURL + */ + public async getProperties( + aborter: Aborter + ): Promise { + return this.queueContext.getProperties({ + abortSignal: aborter + }); + } + + /** + * Deletes the specified queue permanently. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/delete-queue3 + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @returns {Promise} + * @memberof QueueURL + */ + public async delete(aborter: Aborter): Promise { + return this.queueContext.deleteMethod({ + abortSignal: aborter + }); + } + + /** + * Sets one or more user-defined name-value pairs for the specified queue. + * + * If no option provided, or no metadata defined in the option parameter, the queue + * metadata will be removed. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/set-queue-metadata + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {IMetadata} [metadata] If no metadata provided, all existing metadata will be removed. + * @returns {Promise} + * @memberof QueueURL + */ + public async setMetadata( + aborter: Aborter, + metadata?: IMetadata + ): Promise { + return this.queueContext.setMetadata({ + abortSignal: aborter, + metadata + }); + } + + /** + * Gets details about any stored access policies specified on the queue that may be used with Shared Access Signatures. + * + * WARNING: JavaScript Date will potential lost precision when parsing start and expiry string. + * For example, new Date("2018-12-31T03:44:23.8827891Z").toISOString() will get "2018-12-31T03:44:23.882Z". + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-queue-acl + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {IQueueGetAccessPolicyOptions} [options] + * @returns {Promise} + * @memberof QueueURL + */ + public async getAccessPolicy( + aborter: Aborter + ): Promise { + const response = await this.queueContext.getAccessPolicy({ + abortSignal: aborter + }); + + const res: QueueGetAccessPolicyResponse = { + _response: response._response, + date: response.date, + requestId: response.requestId, + signedIdentifiers: [], + version: response.version, + errorCode: response.errorCode + }; + + for (const identifier of response) { + res.signedIdentifiers.push({ + accessPolicy: { + expiry: new Date(identifier.accessPolicy.expiry), + permission: identifier.accessPolicy.permission, + start: new Date(identifier.accessPolicy.start) + }, + id: identifier.id + }); + } + + return res; + } + + /** + * Sets stored access policies for the queue that may be used with Shared Access Signatures. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/set-queue-acl + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {PublicAccessType} [access] + * @param {ISignedIdentifier[]} [queueAcl] + * @param {IQueueSetAccessPolicyOptions} [options] + * @returns {Promise} + * @memberof QueueURL + */ + public async setAccessPolicy( + aborter: Aborter, + queueAcl?: ISignedIdentifier[] + ): Promise { + const acl: Models.SignedIdentifier[] = []; + for (const identifier of queueAcl || []) { + acl.push({ + accessPolicy: { + expiry: truncatedISO8061Date(identifier.accessPolicy.expiry), + permission: identifier.accessPolicy.permission, + start: truncatedISO8061Date(identifier.accessPolicy.start) + }, + id: identifier.id + }); + } + + return this.queueContext.setAccessPolicy({ + abortSignal: aborter, + queueAcl: acl + }); + } +} diff --git a/queue/lib/RetryPolicyFactory.ts b/queue/lib/RetryPolicyFactory.ts new file mode 100644 index 0000000..9b6b588 --- /dev/null +++ b/queue/lib/RetryPolicyFactory.ts @@ -0,0 +1,106 @@ +import { + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions +} from "ms-rest-js"; + +import { RetryPolicy, RetryPolicyType } from "./policies/RetryPolicy"; + +/** + * Retry options interface. + * + * @export + * @interface IRetryOptions + */ +export interface IRetryOptions { + /** + * Optional. RetryPolicyType, default is exponential retry policy. + * + * @type {RetryPolicyType} + * @memberof RetryOptions + */ + readonly retryPolicyType?: RetryPolicyType; + + /** + * Optional. Max try number of attempts, default is 4. + * A value of 1 means 1 try and no retries. + * A value smaller than 1 means default retry number of attempts. + * + * @type {number} + * @memberof IRetryOptions + */ + readonly maxTries?: number; + + /** + * Optional. Indicates the maximum time in ms allowed for any single try of an HTTP request. + * A value of zero or undefined means that you accept our default timeout, 60s or 60 * 1000ms. + * + * NOTE: When transferring large amounts of data, the default TryTimeout will probably + * not be sufficient. You should override this value based on the bandwidth available to + * the host machine and proximity to the Storage service. A good starting point may be something + * like (60 seconds per MB of anticipated-payload-size) + * + * @type {number} + * @memberof IRetryOptions + */ + readonly tryTimeoutInMs?: number; + + /** + * Optional. Specifies the amount of delay to use before retrying an operation (default is 4s or 4 * 1000ms). + * The delay increases (exponentially or linearly) with each retry up to a maximum specified by + * maxRetryDelayInMs. If you specify 0, then you must also specify 0 for maxRetryDelayInMs. + * + * @type {number} + * @memberof IRetryOptions + */ + readonly retryDelayInMs?: number; + + /** + * Optional. Specifies the maximum delay allowed before retrying an operation (default is 120s or 120 * 1000ms). + * If you specify 0, then you must also specify 0 for retryDelayInMs. + * + * @type {number} + * @memberof IRetryOptions + */ + readonly maxRetryDelayInMs?: number; + + /** + * If a secondaryHost is specified, retries will be tried against this host. If secondaryHost is undefined + * (the default) then operations are not retried against another host. + * + * NOTE: Before setting this field, make sure you understand the issues around + * reading stale and potentially-inconsistent data at + * {@link https://docs.microsoft.com/en-us/azure/storage/common/storage-designing-ha-apps-with-ragrs} + * + * @type {string} + * @memberof IRetryOptions + */ + readonly secondaryHost?: string; +} + +/** + * RetryPolicyFactory is a factory class helping generating RetryPolicy objects. + * + * @export + * @class RetryPolicyFactory + * @implements {RequestPolicyFactory} + */ +export class RetryPolicyFactory implements RequestPolicyFactory { + private retryOptions?: IRetryOptions; + + /** + * Creates an instance of RetryPolicyFactory. + * @param {IRetryOptions} [retryOptions] + * @memberof RetryPolicyFactory + */ + constructor(retryOptions?: IRetryOptions) { + this.retryOptions = retryOptions; + } + + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): RetryPolicy { + return new RetryPolicy(nextPolicy, options, this.retryOptions); + } +} diff --git a/queue/lib/SASQueryParameters.ts b/queue/lib/SASQueryParameters.ts new file mode 100644 index 0000000..24187ea --- /dev/null +++ b/queue/lib/SASQueryParameters.ts @@ -0,0 +1,291 @@ +import { IIPRange, ipRangeToString } from "./IIPRange"; +import { truncatedISO8061Date } from "./utils/utils.common"; + +/** + * Protocols for generated SAS. + * + * @export + * @enum {number} + */ +export enum SASProtocol { + /** + * Protocol that allows HTTPS only + */ + HTTPS = "https", + + /** + * Protocol that allows both HTTPS and HTTP + */ + HTTPSandHTTP = "https,http" +} + +/** + * Represents the components that make up an Azure Storage SAS' query parameters. This type is not constructed directly + * by the user; it is only generated by the {@link AccountSASSignatureValues} and {@link ServiceSASSignatureValues} + * types. Once generated, it can be encoded into a {@code String} and appended to a URL directly (though caution should + * be taken here in case there are existing query parameters, which might affect the appropriate means of appending + * these query parameters). + * + * NOTE: Instances of this class are immutable. + * + * @export + * @class SASQueryParameters + */ +export class SASQueryParameters { + /** + * The storage API version. + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly version: string; + + /** + * Optional. The allowed HTTP protocol(s). + * + * @type {SASProtocol} + * @memberof SASQueryParameters + */ + public readonly protocol?: SASProtocol; + + /** + * Optional. The start time for this SAS token. + * + * @type {Date} + * @memberof SASQueryParameters + */ + public readonly startTime?: Date; + + /** + * Optional only when identifier is provided. The expiry time for this SAS token. + * + * @type {Date} + * @memberof SASQueryParameters + */ + public readonly expiryTime?: Date; + + /** + * Optional only when identifier is provided. + * Please refer to {@link AccountSASPermission}, {@link QueueSASPermissions} for more details. + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly permissions?: string; + + /** + * Optional. The storage services being accessed (only for Account SAS). Please refer to {@link AccountSASServices} + * for more details. + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly services?: string; + + /** + * Optional. The storage resource types being accessed (only for Account SAS). Please refer to + * {@link AccountSASResourceTypes} for more details. + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly resourceTypes?: string; + + /** + * Optional. The signed identifier (only for {@link ServiceSASSignatureValues}). + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/establishing-a-stored-access-policy + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly identifier?: string; + + /** + * Optional. The storage queue (only for {@link ServiceSASSignatureValues}). + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly resource?: string; + + /** + * The signature for the SAS token. + * + * @type {string} + * @memberof SASQueryParameters + */ + public readonly signature: string; + + /** + * Inner value of getter ipRange. + * + * @private + * @type {IIPRange} + * @memberof SASQueryParameters + */ + private readonly ipRangeInner?: IIPRange; + + /** + * Optional. IP range allowed for this SAS. + * + * @readonly + * @type {(IIPRange | undefined)} + * @memberof SASQueryParameters + */ + public get ipRange(): IIPRange | undefined { + if (this.ipRangeInner) { + return { + end: this.ipRangeInner.end, + start: this.ipRangeInner.start + }; + } + return undefined; + } + + /** + * Creates an instance of SASQueryParameters. + * + * @param {string} version Representing the storage version + * @param {string} signature Representing the signature for the SAS token + * @param {string} [permissions] Representing the storage permissions + * @param {string} [services] Representing the storage services being accessed (only for Account SAS) + * @param {string} [resourceTypes] Representing the storage resource types being accessed (only for Account SAS) + * @param {SASProtocol} [protocol] Representing the allowed HTTP protocol(s) + * @param {Date} [startTime] Representing the start time for this SAS token + * @param {Date} [expiryTime] Representing the expiry time for this SAS token + * @param {IIPRange} [ipRange] Representing the range of valid IP addresses for this SAS token + * @param {string} [identifier] Representing the signed identifier (only for Service SAS) + * @param {string} [resource] Representing the storage queue (only for Service SAS) + * @memberof SASQueryParameters + */ + constructor( + version: string, + signature: string, + permissions?: string, + services?: string, + resourceTypes?: string, + protocol?: SASProtocol, + startTime?: Date, + expiryTime?: Date, + ipRange?: IIPRange, + identifier?: string, + resource?: string + ) { + this.version = version; + this.services = services; + this.resourceTypes = resourceTypes; + this.expiryTime = expiryTime; + this.permissions = permissions; + this.protocol = protocol; + this.startTime = startTime; + this.ipRangeInner = ipRange; + this.identifier = identifier; + this.resource = resource; + this.signature = signature; + } + + /** + * Encodes all SAS query parameters into a string that can be appended to a URL. + * + * @returns {string} + * @memberof SASQueryParameters + */ + public toString(): string { + const params: string[] = [ + "sv", + "ss", + "srt", + "spr", + "st", + "se", + "sip", + "si", + "sr", + "sp", + "sig" + ]; + const queries: string[] = []; + + for (const param of params) { + switch (param) { + case "sv": + this.tryAppendQueryParameter(queries, param, this.version); + break; + case "ss": + this.tryAppendQueryParameter(queries, param, this.services); + break; + case "srt": + this.tryAppendQueryParameter(queries, param, this.resourceTypes); + break; + case "spr": + this.tryAppendQueryParameter(queries, param, this.protocol); + break; + case "st": + this.tryAppendQueryParameter( + queries, + param, + this.startTime + ? truncatedISO8061Date(this.startTime, false) + : undefined + ); + break; + case "se": + this.tryAppendQueryParameter( + queries, + param, + this.expiryTime + ? truncatedISO8061Date(this.expiryTime, false) + : undefined + ); + break; + case "sip": + this.tryAppendQueryParameter( + queries, + param, + this.ipRange ? ipRangeToString(this.ipRange) : undefined + ); + break; + case "si": + this.tryAppendQueryParameter(queries, param, this.identifier); + break; + case "sr": + this.tryAppendQueryParameter(queries, param, this.resource); + break; + case "sp": + this.tryAppendQueryParameter(queries, param, this.permissions); + break; + case "sig": + this.tryAppendQueryParameter(queries, param, this.signature); + break; + } + } + return queries.join("&"); + } + + /** + * A private helper method used to filter and append query key/value pairs into an array. + * + * @private + * @param {string[]} queries + * @param {string} key + * @param {string} [value] + * @returns {void} + * @memberof SASQueryParameters + */ + private tryAppendQueryParameter( + queries: string[], + key: string, + value?: string + ): void { + if (!value) { + return; + } + + key = encodeURIComponent(key); + value = encodeURIComponent(value); + if (key.length > 0 && value.length > 0) { + queries.push(`${key}=${value}`); + } + } +} diff --git a/queue/lib/ServiceURL.ts b/queue/lib/ServiceURL.ts new file mode 100644 index 0000000..a6e1512 --- /dev/null +++ b/queue/lib/ServiceURL.ts @@ -0,0 +1,161 @@ +import * as Models from "../lib/generated/models"; +import { Aborter } from "./Aborter"; +import { ListQueuesIncludeType } from "./generated/models/index"; +import { Service } from "./generated/operations"; +import { Pipeline } from "./Pipeline"; +import { StorageURL } from "./StorageURL"; + +export interface IServiceListQueuesSegmentOptions { + /** + * @member {string} [prefix] Filters the results to return only queues + * whose name begins with the specified prefix. + */ + prefix?: string; + /** + * @member {number} [maxresults] Specifies the maximum number of queues + * to return. If the request does not specify maxresults, or specifies a + * value greater than 5000, the server will return up to 5000 items. Note + * that if the listing operation crosses a partition boundary, then the + * service will return a continuation token for retrieving the remainder of + * the results. For this reason, it is possible that the service will return + * fewer results than specified by maxresults, or than the default of 5000. + */ + maxresults?: number; + /** + * @member {ListQueuesIncludeType} [include] Include this parameter to + * specify that the queue's metadata be returned as part of the response + * body. Possible values include: 'metadata' + */ + include?: ListQueuesIncludeType; +} + +/** + * A ServiceURL represents a URL to the Azure Storage Queue service allowing you + * to manipulate queues. + * + * @export + * @class ServiceURL + * @extends {StorageURL} + */ +export class ServiceURL extends StorageURL { + /** + * serviceContext provided by protocol layer. + * + * @private + * @type {Service} + * @memberof ServiceURL + */ + private serviceContext: Service; + + /** + * Creates an instance of ServiceURL. + * @param {string} url A URL string pointing to Azure Storage queue service, such as + * "https://myaccount.queue.core.windows.net". You can Append a SAS + * if using AnonymousCredential, such as "https://myaccount.queue.core.windows.net?sasString". + * @param {Pipeline} pipeline Call StorageURL.newPipeline() to create a default + * pipeline, or provide a customized pipeline. + * @memberof ServiceURL + */ + constructor(url: string, pipeline: Pipeline) { + super(url, pipeline); + this.serviceContext = new Service(this.storageClientContext); + } + + /** + * Creates a new ServiceURL object identical to the source but with the + * specified request policy pipeline. + * + * @param {Pipeline} pipeline + * @returns {ServiceURL} + * @memberof ServiceURL + */ + public withPipeline(pipeline: Pipeline): ServiceURL { + return new ServiceURL(this.url, pipeline); + } + + /** + * Gets the properties of a storage account’s Queue service, including properties + * for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-queue-service-properties + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @returns {Promise} + * @memberof ServiceURL + */ + public async getProperties( + aborter: Aborter + ): Promise { + return this.serviceContext.getProperties({ + abortSignal: aborter + }); + } + + /** + * Sets properties for a storage account’s Queue service endpoint, including properties + * for Storage Analytics, CORS (Cross-Origin Resource Sharing) rules and soft delete settings. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/set-queue-service-properties + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {Models.StorageServiceProperties} properties + * @returns {Promise} + * @memberof ServiceURL + */ + public async setProperties( + aborter: Aborter, + properties: Models.StorageServiceProperties + ): Promise { + return this.serviceContext.setProperties(properties, { + abortSignal: aborter + }); + } + + /** + * Retrieves statistics related to replication for the Queue service. It is only + * available on the secondary location endpoint when read-access geo-redundant + * replication is enabled for the storage account. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-queue-service-stats + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @returns {Promise} + * @memberof ServiceURL + */ + public async getStatistics( + aborter: Aborter + ): Promise { + return this.serviceContext.getStatistics({ + abortSignal: aborter + }); + } + + /** + * Returns a list of the queues under the specified account. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/list-queues1 + * + * @param {Aborter} aborter Create a new Aborter instance with Aborter.none or Aborter.timeout(), + * goto documents of Aborter for more examples about request cancellation + * @param {string} [marker] A string value that identifies the portion of + * the list of queues to be returned with the next listing operation. The + * operation returns the NextMarker value within the response body if the + * listing operation did not return all queues remaining to be listed + * with the current page. The NextMarker value can be used as the value for + * the marker parameter in a subsequent call to request the next page of list + * items. The marker value is opaque to the client. + * @param {IServiceListQueuesSegmentOptions} [options] + * @returns {Promise} + * @memberof ServiceURL + */ + public async listQueuesSegment( + aborter: Aborter, + marker?: string, + options: IServiceListQueuesSegmentOptions = {} + ): Promise { + return this.serviceContext.listQueuesSegment({ + abortSignal: aborter, + marker, + ...options + }); + } +} diff --git a/queue/lib/StorageURL.ts b/queue/lib/StorageURL.ts new file mode 100644 index 0000000..429b1a7 --- /dev/null +++ b/queue/lib/StorageURL.ts @@ -0,0 +1,117 @@ +import { deserializationPolicy, RequestPolicyFactory } from "ms-rest-js"; + +import { BrowserPolicyFactory } from "./BrowserPolicyFactory"; +import { Credential } from "./credentials/Credential"; +import { StorageClientContext } from "./generated/storageClientContext"; +import { LoggingPolicyFactory } from "./LoggingPolicyFactory"; +import { IHttpClient, IHttpPipelineLogger, Pipeline } from "./Pipeline"; +import { IRetryOptions, RetryPolicyFactory } from "./RetryPolicyFactory"; +import { + ITelemetryOptions, + TelemetryPolicyFactory +} from "./TelemetryPolicyFactory"; +import { UniqueRequestIDPolicyFactory } from "./UniqueRequestIDPolicyFactory"; + +export { deserializationPolicy }; + +/** + * Option interface for Pipeline.newPipeline method. + * + * @export + * @interface INewPipelineOptions + */ +export interface INewPipelineOptions { + /** + * Telemetry configures the built-in telemetry policy behavior. + * + * @type {ITelemetryOptions} + * @memberof INewPipelineOptions + */ + telemetry?: ITelemetryOptions; + retryOptions?: IRetryOptions; + + logger?: IHttpPipelineLogger; + httpClient?: IHttpClient; +} + +/** + * A ServiceURL represents a based URL class for ServiceURL, QueueURL and etc. + * + * @export + * @class StorageURL + */ +export abstract class StorageURL { + /** + * A static method used to create a new Pipeline object with Credential provided. + * + * @static + * @param {Credential} credential Such as AnonymousCredential, SharedKeyCredential or TokenCredential. + * @param {INewPipelineOptions} [pipelineOptions] Optional. Options. + * @returns {Pipeline} A new Pipeline object. + * @memberof Pipeline + */ + public static newPipeline( + credential: Credential, + pipelineOptions: INewPipelineOptions = {} + ): Pipeline { + // Order is important. Closer to the API at the top & closer to the network at the bottom. + // The credential's policy factory must appear close to the wire so it can sign any + // changes made by other factories (like UniqueRequestIDPolicyFactory) + const factories: RequestPolicyFactory[] = [ + new TelemetryPolicyFactory(pipelineOptions.telemetry), + new UniqueRequestIDPolicyFactory(), + new BrowserPolicyFactory(), + deserializationPolicy(), // Default deserializationPolicy is provided by protocol layer + new RetryPolicyFactory(pipelineOptions.retryOptions), + new LoggingPolicyFactory(), + credential + ]; + + return new Pipeline(factories, { + HTTPClient: pipelineOptions.httpClient, + logger: pipelineOptions.logger + }); + } + + /** + * Request policy pipeline. + * + * @internal + * @type {Pipeline} + * @memberof StorageURL + */ + public readonly pipeline: Pipeline; + + /** + * URL string value. + * + * @type {string} + * @memberof StorageURL + */ + public readonly url: string; + + /** + * StorageClient is a reference to protocol layer operations entry, which is + * generated by AutoRest generator. + * + * @protected + * @type {StorageClient} + * @memberof StorageURL + */ + protected readonly storageClientContext: StorageClientContext; + + /** + * Creates an instance of StorageURL. + * @param {string} url + * @param {Pipeline} pipeline + * @memberof StorageURL + */ + protected constructor(url: string, pipeline: Pipeline) { + this.url = url; + this.pipeline = pipeline; + this.storageClientContext = new StorageClientContext( + url, + pipeline.toServiceClientOptions() + ); + } +} diff --git a/queue/lib/TelemetryPolicyFactory.ts b/queue/lib/TelemetryPolicyFactory.ts new file mode 100644 index 0000000..53a80a0 --- /dev/null +++ b/queue/lib/TelemetryPolicyFactory.ts @@ -0,0 +1,75 @@ +import { + isNode, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions +} from "ms-rest-js"; +import * as os from "os"; + +import { TelemetryPolicy } from "./policies/TelemetryPolicy"; +import { SDK_VERSION } from "./utils/constants"; + +/** + * Interface of TelemetryPolicy options. + * + * @export + * @interface ITelemetryOptions + */ +export interface ITelemetryOptions { + value: string; +} + +/** + * TelemetryPolicyFactory is a factory class helping generating TelemetryPolicy objects. + * + * @export + * @class TelemetryPolicyFactory + * @implements {RequestPolicyFactory} + */ +export class TelemetryPolicyFactory implements RequestPolicyFactory { + private telemetryString: string; + + /** + * Creates an instance of TelemetryPolicyFactory. + * @param {ITelemetryOptions} [telemetry] + * @memberof TelemetryPolicyFactory + */ + constructor(telemetry?: ITelemetryOptions) { + const userAgentInfo: string[] = []; + + if (isNode) { + if (telemetry) { + const telemetryString = telemetry.value; + if ( + telemetryString.length > 0 && + userAgentInfo.indexOf(telemetryString) === -1 + ) { + userAgentInfo.push(telemetryString); + } + } + + // e.g. Azure-Storage/10.0.0 + const libInfo = `Azure-Storage/${SDK_VERSION}`; + if (userAgentInfo.indexOf(libInfo) === -1) { + userAgentInfo.push(libInfo); + } + + // e.g. (NODE-VERSION 4.9.1; Windows_NT 10.0.16299) + const runtimeInfo = `(NODE-VERSION ${ + process.version + }; ${os.type()} ${os.release()})`; + if (userAgentInfo.indexOf(runtimeInfo) === -1) { + userAgentInfo.push(runtimeInfo); + } + } + + this.telemetryString = userAgentInfo.join(" "); + } + + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): TelemetryPolicy { + return new TelemetryPolicy(nextPolicy, options, this.telemetryString); + } +} diff --git a/queue/lib/UniqueRequestIDPolicyFactory.ts b/queue/lib/UniqueRequestIDPolicyFactory.ts new file mode 100644 index 0000000..9ccf429 --- /dev/null +++ b/queue/lib/UniqueRequestIDPolicyFactory.ts @@ -0,0 +1,23 @@ +import { + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions +} from "ms-rest-js"; + +import { UniqueRequestIDPolicy } from "./policies/UniqueRequestIDPolicy"; + +/** + * UniqueRequestIDPolicyFactory is a factory class helping generating UniqueRequestIDPolicy objects. + * + * @export + * @class UniqueRequestIDPolicyFactory + * @implements {RequestPolicyFactory} + */ +export class UniqueRequestIDPolicyFactory implements RequestPolicyFactory { + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): UniqueRequestIDPolicy { + return new UniqueRequestIDPolicy(nextPolicy, options); + } +} diff --git a/queue/lib/credentials/AnonymousCredential.ts b/queue/lib/credentials/AnonymousCredential.ts new file mode 100644 index 0000000..63d3a98 --- /dev/null +++ b/queue/lib/credentials/AnonymousCredential.ts @@ -0,0 +1,31 @@ +import { RequestPolicy, RequestPolicyOptions } from "ms-rest-js"; + +import { AnonymousCredentialPolicy } from "../policies/AnonymousCredentialPolicy"; +import { Credential } from "./Credential"; + +/** + * AnonymousCredential provides a credentialPolicyCreator member used to create + * AnonymousCredentialPolicy objects. AnonymousCredentialPolicy is used with + * HTTP(S) requests that read public resources or for use with Shared Access + * Signatures (SAS). + * + * @export + * @class AnonymousCredential + * @extends {Credential} + */ +export class AnonymousCredential extends Credential { + /** + * Creates an AnonymousCredentialPolicy object. + * + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @returns {AnonymousCredentialPolicy} + * @memberof AnonymousCredential + */ + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): AnonymousCredentialPolicy { + return new AnonymousCredentialPolicy(nextPolicy, options); + } +} diff --git a/queue/lib/credentials/Credential.ts b/queue/lib/credentials/Credential.ts new file mode 100644 index 0000000..c157d52 --- /dev/null +++ b/queue/lib/credentials/Credential.ts @@ -0,0 +1,42 @@ +import { + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions +} from "ms-rest-js"; + +import { CredentialPolicy } from "../policies/CredentialPolicy"; + +/** + * Credential is an abstract class for Azure Storage HTTP requests signing. This + * class will host an credentialPolicyCreator factory which generates CredentialPolicy. + * + * @export + * @abstract + * @class Credential + */ +export abstract class Credential implements RequestPolicyFactory { + /** + * Creates a RequestPolicy object. + * + * @param {RequestPolicy} _nextPolicy + * @param {RequestPolicyOptions} _options + * @returns {RequestPolicy} + * @memberof Credential + */ + public create( + // tslint:disable-next-line:variable-name + _nextPolicy: RequestPolicy, + // tslint:disable-next-line:variable-name + _options: RequestPolicyOptions + ): RequestPolicy { + throw new Error("Method should be implemented in children classes."); + } +} + +/** + * A factory function that creates a new CredentialPolicy that uses the provided nextPolicy. + */ +export type CredentialPolicyCreator = ( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions +) => CredentialPolicy; diff --git a/queue/lib/credentials/SharedKeyCredential.ts b/queue/lib/credentials/SharedKeyCredential.ts new file mode 100644 index 0000000..0db8299 --- /dev/null +++ b/queue/lib/credentials/SharedKeyCredential.ts @@ -0,0 +1,72 @@ +import * as Crypto from "crypto"; +import { RequestPolicy, RequestPolicyOptions } from "ms-rest-js"; + +import { SharedKeyCredentialPolicy } from "../policies/SharedKeyCredentialPolicy"; +import { Credential } from "./Credential"; + +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * SharedKeyCredential for account key authorization of Azure Storage service. + * + * @export + * @class SharedKeyCredential + * @extends {Credential} + */ +export class SharedKeyCredential extends Credential { + /** + * Azure Storage account name; readonly. + * + * @type {string} + * @memberof SharedKeyCredential + */ + public readonly accountName: string; + + /** + * Azure Storage account key; readonly. + * + * @type {Buffer} + * @memberof SharedKeyCredential + */ + private readonly accountKey: Buffer; + + /** + * Creates an instance of SharedKeyCredential. + * @param {string} accountName + * @param {string} accountKey + * @memberof SharedKeyCredential + */ + constructor(accountName: string, accountKey: string) { + super(); + this.accountName = accountName; + this.accountKey = Buffer.from(accountKey, "base64"); + } + + /** + * Creates a SharedKeyCredentialPolicy object. + * + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @returns {SharedKeyCredentialPolicy} + * @memberof SharedKeyCredential + */ + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): SharedKeyCredentialPolicy { + return new SharedKeyCredentialPolicy(nextPolicy, options, this); + } + + /** + * Generates a hash signature for an HTTP request or for a SAS. + * + * @param {string} stringToSign + * @returns {string} + * @memberof SharedKeyCredential + */ + public computeHMACSHA256(stringToSign: string): string { + return Crypto.createHmac("sha256", this.accountKey) + .update(stringToSign, "utf8") + .digest("base64"); + } +} diff --git a/queue/lib/credentials/TokenCredential.ts b/queue/lib/credentials/TokenCredential.ts new file mode 100644 index 0000000..d6044d5 --- /dev/null +++ b/queue/lib/credentials/TokenCredential.ts @@ -0,0 +1,64 @@ +import { RequestPolicy, RequestPolicyOptions } from "ms-rest-js"; + +import { Credential } from "../credentials/Credential"; +import { TokenCredentialPolicy } from "../policies/TokenCredentialPolicy"; + +/** + * TokenCredential is a Credential used to generate a TokenCredentialPolicy. + * Renew token by setting a new token string value to token property. + * + * @example + * const tokenCredential = new TokenCredential("token"); + * const pipeline = StorageURL.newPipeline(tokenCredential); + * + * const serviceURL = new ServiceURL("https://mystorageaccount.queue.core.windows.net", pipeline); + * + * // Set up a timer to refresh the token + * const timerID = setInterval(() => { + * // Update token by accessing to public tokenCredential.token + * tokenCredential.token = "updatedToken"; + * // WARNING: Timer must be manually stopped! It will forbid GC of tokenCredential + * if (shouldStop()) { + * clearInterval(timerID); + * } + * }, 60 * 60 * 1000); // Set an interval time before your token expired + * @export + * @class TokenCredential + * @extends {Credential} + * + */ +export class TokenCredential extends Credential { + /** + * Mutable token value. You can set a renewed token value to this property, + * for example, when an OAuth token is expired. + * + * @type {string} + * @memberof TokenCredential + */ + public token: string; + + /** + * Creates an instance of TokenCredential. + * @param {string} token + * @memberof TokenCredential + */ + constructor(token: string) { + super(); + this.token = token; + } + + /** + * Creates a TokenCredentialPolicy object. + * + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @returns {TokenCredentialPolicy} + * @memberof TokenCredential + */ + public create( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): TokenCredentialPolicy { + return new TokenCredentialPolicy(nextPolicy, options, this); + } +} diff --git a/queue/lib/generated/models/index.ts b/queue/lib/generated/models/index.ts new file mode 100644 index 0000000..19bc45a --- /dev/null +++ b/queue/lib/generated/models/index.ts @@ -0,0 +1,1760 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; + + +/** + * @interface + * An interface representing AccessPolicy. + * An Access policy + * + */ +export interface AccessPolicy { + /** + * @member {string} start the date-time the policy is active + * **NOTE: This entity will be treated as a string instead of a Date because + * the API can potentially deal with a higher precision value than what is + * supported by JavaScript.** + */ + start: string; + /** + * @member {string} expiry the date-time the policy expires + * **NOTE: This entity will be treated as a string instead of a Date because + * the API can potentially deal with a higher precision value than what is + * supported by JavaScript.** + */ + expiry: string; + /** + * @member {string} permission the permissions for the acl policy + */ + permission: string; +} + +/** + * @interface + * An interface representing QueueItem. + * An Azure Storage Queue. + * + */ +export interface QueueItem { + /** + * @member {string} name The name of the Queue. + */ + name: string; + /** + * @member {{ [propertyName: string]: string }} [metadata] + */ + metadata?: { [propertyName: string]: string }; +} + +/** + * @interface + * An interface representing ListQueuesSegmentResponse. + * The object returned when calling List Queues on a Queue Service. + * + */ +export interface ListQueuesSegmentResponse { + /** + * @member {string} serviceEndpoint + */ + serviceEndpoint: string; + /** + * @member {string} prefix + */ + prefix: string; + /** + * @member {string} [marker] + */ + marker?: string; + /** + * @member {number} maxResults + */ + maxResults: number; + /** + * @member {QueueItem[]} [queueItems] + */ + queueItems?: QueueItem[]; + /** + * @member {string} nextMarker + */ + nextMarker: string; +} + +/** + * @interface + * An interface representing CorsRule. + * CORS is an HTTP feature that enables a web application running under one + * domain to access resources in another domain. Web browsers implement a + * security restriction known as same-origin policy that prevents a web page + * from calling APIs in a different domain; CORS provides a secure way to allow + * one domain (the origin domain) to call APIs in another domain + * + */ +export interface CorsRule { + /** + * @member {string} allowedOrigins The origin domains that are permitted to + * make a request against the storage service via CORS. The origin domain is + * the domain from which the request originates. Note that the origin must be + * an exact case-sensitive match with the origin that the user age sends to + * the service. You can also use the wildcard character '*' to allow all + * origin domains to make requests via CORS. + */ + allowedOrigins: string; + /** + * @member {string} allowedMethods The methods (HTTP request verbs) that the + * origin domain may use for a CORS request. (comma separated) + */ + allowedMethods: string; + /** + * @member {string} allowedHeaders the request headers that the origin domain + * may specify on the CORS request. + */ + allowedHeaders: string; + /** + * @member {string} exposedHeaders The response headers that may be sent in + * the response to the CORS request and exposed by the browser to the request + * issuer + */ + exposedHeaders: string; + /** + * @member {number} maxAgeInSeconds The maximum amount time that a browser + * should cache the preflight OPTIONS request. + */ + maxAgeInSeconds: number; +} + +/** + * @interface + * An interface representing GeoReplication. + */ +export interface GeoReplication { + /** + * @member {GeoReplicationStatusType} status The status of the secondary + * location. Possible values include: 'live', 'bootstrap', 'unavailable' + */ + status: GeoReplicationStatusType; + /** + * @member {Date} lastSyncTime A GMT date/time value, to the second. All + * primary writes preceding this value are guaranteed to be available for + * read operations at the secondary. Primary writes after this point in time + * may or may not be available for reads. + */ + lastSyncTime: Date; +} + +/** + * @interface + * An interface representing RetentionPolicy. + * the retention policy + * + */ +export interface RetentionPolicy { + /** + * @member {boolean} enabled Indicates whether a retention policy is enabled + * for the storage service + */ + enabled: boolean; + /** + * @member {number} [days] Indicates the number of days that metrics or + * logging or soft-deleted data should be retained. All data older than this + * value will be deleted + */ + days?: number; +} + +/** + * @interface + * An interface representing Logging. + * Azure Analytics Logging settings. + * + */ +export interface Logging { + /** + * @member {string} version The version of Storage Analytics to configure. + */ + version: string; + /** + * @member {boolean} deleteProperty Indicates whether all delete requests + * should be logged. + */ + deleteProperty: boolean; + /** + * @member {boolean} read Indicates whether all read requests should be + * logged. + */ + read: boolean; + /** + * @member {boolean} write Indicates whether all write requests should be + * logged. + */ + write: boolean; + /** + * @member {RetentionPolicy} retentionPolicy + */ + retentionPolicy: RetentionPolicy; +} + +/** + * @interface + * An interface representing StorageError. + */ +export interface StorageError { + /** + * @member {string} [message] + */ + message?: string; +} + +/** + * @interface + * An interface representing Metrics. + */ +export interface Metrics { + /** + * @member {string} [version] The version of Storage Analytics to configure. + */ + version?: string; + /** + * @member {boolean} enabled Indicates whether metrics are enabled for the + * Queue service. + */ + enabled: boolean; + /** + * @member {boolean} [includeAPIs] Indicates whether metrics should generate + * summary statistics for called API operations. + */ + includeAPIs?: boolean; + /** + * @member {RetentionPolicy} [retentionPolicy] + */ + retentionPolicy?: RetentionPolicy; +} + +/** + * @interface + * An interface representing QueueMessage. + * A Message object which can be stored in a Queue + * + */ +export interface QueueMessage { + /** + * @member {string} messageText The content of the message + */ + messageText: string; +} + +/** + * @interface + * An interface representing DequeuedMessageItem. + * The object returned in the QueueMessageList array when calling Get Messages + * on a Queue. + * + */ +export interface DequeuedMessageItem { + /** + * @member {string} messageId The Id of the Message. + */ + messageId: string; + /** + * @member {Date} insertionTime The time the Message was inserted into the + * Queue. + */ + insertionTime: Date; + /** + * @member {Date} expirationTime The time that the Message will expire and be + * automatically deleted. + */ + expirationTime: Date; + /** + * @member {string} popReceipt This value is required to delete the Message. + * If deletion fails using this popreceipt then the message has been dequeued + * by another client. + */ + popReceipt: string; + /** + * @member {Date} timeNextVisible The time that the message will again become + * visible in the Queue. + */ + timeNextVisible: Date; + /** + * @member {number} dequeueCount The number of times the message has been + * dequeued. + */ + dequeueCount: number; + /** + * @member {string} messageText The content of the Message. + */ + messageText: string; +} + +/** + * @interface + * An interface representing PeekedMessageItem. + * The object returned in the QueueMessageList array when calling Peek Messages + * on a Queue + * + */ +export interface PeekedMessageItem { + /** + * @member {string} messageId The Id of the Message. + */ + messageId: string; + /** + * @member {Date} insertionTime The time the Message was inserted into the + * Queue. + */ + insertionTime: Date; + /** + * @member {Date} expirationTime The time that the Message will expire and be + * automatically deleted. + */ + expirationTime: Date; + /** + * @member {number} dequeueCount The number of times the message has been + * dequeued. + */ + dequeueCount: number; + /** + * @member {string} messageText The content of the Message. + */ + messageText: string; +} + +/** + * @interface + * An interface representing EnqueuedMessage. + * The object returned in the QueueMessageList array when calling Put Message + * on a Queue + * + */ +export interface EnqueuedMessage { + /** + * @member {string} messageId The Id of the Message. + */ + messageId: string; + /** + * @member {Date} insertionTime The time the Message was inserted into the + * Queue. + */ + insertionTime: Date; + /** + * @member {Date} expirationTime The time that the Message will expire and be + * automatically deleted. + */ + expirationTime: Date; + /** + * @member {string} popReceipt This value is required to delete the Message. + * If deletion fails using this popreceipt then the message has been dequeued + * by another client. + */ + popReceipt: string; + /** + * @member {Date} timeNextVisible The time that the message will again become + * visible in the Queue. + */ + timeNextVisible: Date; +} + +/** + * @interface + * An interface representing SignedIdentifier. + * signed identifier + * + */ +export interface SignedIdentifier { + /** + * @member {string} id a unique id + */ + id: string; + /** + * @member {AccessPolicy} accessPolicy The access policy + */ + accessPolicy: AccessPolicy; +} + +/** + * @interface + * An interface representing StorageServiceProperties. + * Storage Service Properties. + * + */ +export interface StorageServiceProperties { + /** + * @member {Logging} [logging] Azure Analytics Logging settings + */ + logging?: Logging; + /** + * @member {Metrics} [hourMetrics] A summary of request statistics grouped by + * API in hourly aggregates for queues + */ + hourMetrics?: Metrics; + /** + * @member {Metrics} [minuteMetrics] a summary of request statistics grouped + * by API in minute aggregates for queues + */ + minuteMetrics?: Metrics; + /** + * @member {CorsRule[]} [cors] The set of CORS rules. + */ + cors?: CorsRule[]; +} + +/** + * @interface + * An interface representing StorageServiceStats. + * Stats for the storage service. + * + */ +export interface StorageServiceStats { + /** + * @member {GeoReplication} [geoReplication] Geo-Replication information for + * the Secondary Storage Service + */ + geoReplication?: GeoReplication; +} + +/** + * @interface + * An interface representing ServiceSetPropertiesOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface ServiceSetPropertiesOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing ServiceGetStatisticsOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface ServiceGetStatisticsOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing QueueCreateOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface QueueCreateOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing QueueGetPropertiesOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface QueueGetPropertiesOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {{ [propertyName: string]: string }} [metadata] Optional. Include + * this parameter to specify that the queue's metadata be returned as part of + * the response body. Note that metadata requested with this parameter must + * be stored in accordance with the naming restrictions imposed by the + * 2009-09-19 version of the Queue service. Beginning with this version, all + * metadata names must adhere to the naming conventions for C# identifiers. + */ + metadata?: { [propertyName: string]: string }; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing QueueGetAccessPolicyOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface QueueGetAccessPolicyOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing MessagesDequeueOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface MessagesDequeueOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [numberOfMessages] Optional. A nonzero integer value that + * specifies the number of messages to retrieve from the queue, up to a + * maximum of 32. If fewer are visible, the visible messages are returned. By + * default, a single message is retrieved from the queue with this operation. + */ + numberOfMessages?: number; + /** + * @member {number} [visibilitytimeout] Optional. Specifies the new + * visibility timeout value, in seconds, relative to server time. The default + * value is 30 seconds. A specified value must be larger than or equal to 1 + * second, and cannot be larger than 7 days, or larger than 2 hours on REST + * protocol versions prior to version 2011-08-18. The visibility timeout of a + * message can be set to a value later than the expiry time. + */ + visibilitytimeout?: number; + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing MessagesEnqueueOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface MessagesEnqueueOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [visibilitytimeout] Optional. Specifies the new + * visibility timeout value, in seconds, relative to server time. The default + * value is 30 seconds. A specified value must be larger than or equal to 1 + * second, and cannot be larger than 7 days, or larger than 2 hours on REST + * protocol versions prior to version 2011-08-18. The visibility timeout of a + * message can be set to a value later than the expiry time. + */ + visibilitytimeout?: number; + /** + * @member {number} [messageTimeToLive] Optional. Specifies the time-to-live + * interval for the message, in seconds. Prior to version 2017-07-29, the + * maximum time-to-live allowed is 7 days. For version 2017-07-29 or later, + * the maximum time-to-live can be any positive number, as well as -1 + * indicating that the message does not expire. If this parameter is omitted, + * the default time-to-live is 7 days. + */ + messageTimeToLive?: number; + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing MessageIdUpdateOptionalParams. + * Optional Parameters. + * + * @extends RequestOptionsBase + */ +export interface MessageIdUpdateOptionalParams extends msRest.RequestOptionsBase { + /** + * @member {number} [timeout] The The timeout parameter is expressed in + * seconds. For more information, see Setting + * Timeouts for Queue Service Operations. + */ + timeout?: number; + /** + * @member {string} [requestId] Provides a client-generated, opaque value + * with a 1 KB character limit that is recorded in the analytics logs when + * storage analytics logging is enabled. + */ + requestId?: string; +} + +/** + * @interface + * An interface representing ServiceSetPropertiesHeaders. + * Defines headers for SetProperties operation. + * + */ +export interface ServiceSetPropertiesHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing ServiceGetPropertiesHeaders. + * Defines headers for GetProperties operation. + * + */ +export interface ServiceGetPropertiesHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing ServiceGetStatisticsHeaders. + * Defines headers for GetStatistics operation. + * + */ +export interface ServiceGetStatisticsHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing ServiceListQueuesSegmentHeaders. + * Defines headers for ListQueuesSegment operation. + * + */ +export interface ServiceListQueuesSegmentHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing QueueCreateHeaders. + * Defines headers for Create operation. + * + */ +export interface QueueCreateHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing QueueDeleteHeaders. + * Defines headers for Delete operation. + * + */ +export interface QueueDeleteHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing QueueGetPropertiesHeaders. + * Defines headers for GetProperties operation. + * + */ +export interface QueueGetPropertiesHeaders { + /** + * @member {{ [propertyName: string]: string }} [metadata] + */ + metadata?: { [propertyName: string]: string }; + /** + * @member {number} [approximateMessagesCount] The approximate number of + * messages in the queue. This number is not lower than the actual number of + * messages in the queue, but could be higher. + */ + approximateMessagesCount?: number; + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing QueueSetMetadataHeaders. + * Defines headers for SetMetadata operation. + * + */ +export interface QueueSetMetadataHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing QueueGetAccessPolicyHeaders. + * Defines headers for GetAccessPolicy operation. + * + */ +export interface QueueGetAccessPolicyHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing QueueSetAccessPolicyHeaders. + * Defines headers for SetAccessPolicy operation. + * + */ +export interface QueueSetAccessPolicyHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing MessagesDequeueHeaders. + * Defines headers for Dequeue operation. + * + */ +export interface MessagesDequeueHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing MessagesClearHeaders. + * Defines headers for Clear operation. + * + */ +export interface MessagesClearHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing MessagesEnqueueHeaders. + * Defines headers for Enqueue operation. + * + */ +export interface MessagesEnqueueHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing MessagesPeekHeaders. + * Defines headers for Peek operation. + * + */ +export interface MessagesPeekHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing MessageIdUpdateHeaders. + * Defines headers for Update operation. + * + */ +export interface MessageIdUpdateHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [popReceipt] The pop receipt of the queue message. + */ + popReceipt?: string; + /** + * @member {Date} [timeNextVisible] A UTC date/time value that represents + * when the message will be visible on the queue. + */ + timeNextVisible?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * @interface + * An interface representing MessageIdDeleteHeaders. + * Defines headers for Delete operation. + * + */ +export interface MessageIdDeleteHeaders { + /** + * @member {string} [requestId] This header uniquely identifies the request + * that was made and can be used for troubleshooting the request. + */ + requestId?: string; + /** + * @member {string} [version] Indicates the version of the Queue service used + * to execute the request. This header is returned for requests made against + * version 2009-09-19 and above. + */ + version?: string; + /** + * @member {Date} [date] UTC date/time value generated by the service that + * indicates the time at which the response was initiated + */ + date?: Date; + /** + * @member {string} [errorCode] + */ + errorCode?: string; +} + +/** + * Defines values for StorageErrorCode. + * Possible values include: 'AccountAlreadyExists', 'AccountBeingCreated', + * 'AccountIsDisabled', 'AuthenticationFailed', 'ConditionHeadersNotSupported', + * 'ConditionNotMet', 'EmptyMetadataKey', 'InsufficientAccountPermissions', + * 'InternalError', 'InvalidAuthenticationInfo', 'InvalidHeaderValue', + * 'InvalidHttpVerb', 'InvalidInput', 'InvalidMd5', 'InvalidMetadata', + * 'InvalidQueryParameterValue', 'InvalidRange', 'InvalidResourceName', + * 'InvalidUri', 'InvalidXmlDocument', 'InvalidXmlNodeValue', 'Md5Mismatch', + * 'MetadataTooLarge', 'MissingContentLengthHeader', + * 'MissingRequiredQueryParameter', 'MissingRequiredHeader', + * 'MissingRequiredXmlNode', 'MultipleConditionHeadersNotSupported', + * 'OperationTimedOut', 'OutOfRangeInput', 'OutOfRangeQueryParameterValue', + * 'RequestBodyTooLarge', 'ResourceTypeMismatch', 'RequestUrlFailedToParse', + * 'ResourceAlreadyExists', 'ResourceNotFound', 'ServerBusy', + * 'UnsupportedHeader', 'UnsupportedXmlNode', 'UnsupportedQueryParameter', + * 'UnsupportedHttpVerb', 'InvalidMarker', 'MessageNotFound', + * 'MessageTooLarge', 'PopReceiptMismatch', 'QueueAlreadyExists', + * 'QueueBeingDeleted', 'QueueDisabled', 'QueueNotEmpty', 'QueueNotFound' + * There could be more values for this enum apart from the ones defined here.If + * you want to set a value that is not from the known values then you can do + * the following: + * let param: StorageErrorCode = + * "someUnknownValueThatWillStillBeValid"; + * @readonly + * @enum {string} + */ +export enum StorageErrorCode { + AccountAlreadyExists = 'AccountAlreadyExists', + AccountBeingCreated = 'AccountBeingCreated', + AccountIsDisabled = 'AccountIsDisabled', + AuthenticationFailed = 'AuthenticationFailed', + ConditionHeadersNotSupported = 'ConditionHeadersNotSupported', + ConditionNotMet = 'ConditionNotMet', + EmptyMetadataKey = 'EmptyMetadataKey', + InsufficientAccountPermissions = 'InsufficientAccountPermissions', + InternalError = 'InternalError', + InvalidAuthenticationInfo = 'InvalidAuthenticationInfo', + InvalidHeaderValue = 'InvalidHeaderValue', + InvalidHttpVerb = 'InvalidHttpVerb', + InvalidInput = 'InvalidInput', + InvalidMd5 = 'InvalidMd5', + InvalidMetadata = 'InvalidMetadata', + InvalidQueryParameterValue = 'InvalidQueryParameterValue', + InvalidRange = 'InvalidRange', + InvalidResourceName = 'InvalidResourceName', + InvalidUri = 'InvalidUri', + InvalidXmlDocument = 'InvalidXmlDocument', + InvalidXmlNodeValue = 'InvalidXmlNodeValue', + Md5Mismatch = 'Md5Mismatch', + MetadataTooLarge = 'MetadataTooLarge', + MissingContentLengthHeader = 'MissingContentLengthHeader', + MissingRequiredQueryParameter = 'MissingRequiredQueryParameter', + MissingRequiredHeader = 'MissingRequiredHeader', + MissingRequiredXmlNode = 'MissingRequiredXmlNode', + MultipleConditionHeadersNotSupported = 'MultipleConditionHeadersNotSupported', + OperationTimedOut = 'OperationTimedOut', + OutOfRangeInput = 'OutOfRangeInput', + OutOfRangeQueryParameterValue = 'OutOfRangeQueryParameterValue', + RequestBodyTooLarge = 'RequestBodyTooLarge', + ResourceTypeMismatch = 'ResourceTypeMismatch', + RequestUrlFailedToParse = 'RequestUrlFailedToParse', + ResourceAlreadyExists = 'ResourceAlreadyExists', + ResourceNotFound = 'ResourceNotFound', + ServerBusy = 'ServerBusy', + UnsupportedHeader = 'UnsupportedHeader', + UnsupportedXmlNode = 'UnsupportedXmlNode', + UnsupportedQueryParameter = 'UnsupportedQueryParameter', + UnsupportedHttpVerb = 'UnsupportedHttpVerb', + InvalidMarker = 'InvalidMarker', + MessageNotFound = 'MessageNotFound', + MessageTooLarge = 'MessageTooLarge', + PopReceiptMismatch = 'PopReceiptMismatch', + QueueAlreadyExists = 'QueueAlreadyExists', + QueueBeingDeleted = 'QueueBeingDeleted', + QueueDisabled = 'QueueDisabled', + QueueNotEmpty = 'QueueNotEmpty', + QueueNotFound = 'QueueNotFound', +} + +/** + * Defines values for GeoReplicationStatusType. + * Possible values include: 'live', 'bootstrap', 'unavailable' + * There could be more values for this enum apart from the ones defined here.If + * you want to set a value that is not from the known values then you can do + * the following: + * let param: GeoReplicationStatusType = + * "someUnknownValueThatWillStillBeValid"; + * @readonly + * @enum {string} + */ +export enum GeoReplicationStatusType { + Live = 'live', + Bootstrap = 'bootstrap', + Unavailable = 'unavailable', +} + +/** + * Defines values for ListQueuesIncludeType. + * Possible values include: 'metadata' + * @readonly + * @enum {string} + */ +export enum ListQueuesIncludeType { + Metadata = 'metadata', +} + +/** + * Contains response data for the setProperties operation. + */ +export type ServiceSetPropertiesResponse = ServiceSetPropertiesHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: ServiceSetPropertiesHeaders; + }; +}; + +/** + * Contains response data for the getProperties operation. + */ +export type ServiceGetPropertiesResponse = StorageServiceProperties & ServiceGetPropertiesHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: ServiceGetPropertiesHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: StorageServiceProperties; + }; +}; + +/** + * Contains response data for the getStatistics operation. + */ +export type ServiceGetStatisticsResponse = StorageServiceStats & ServiceGetStatisticsHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: ServiceGetStatisticsHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: StorageServiceStats; + }; +}; + +/** + * Contains response data for the listQueuesSegment operation. + */ +export type ServiceListQueuesSegmentResponse = ListQueuesSegmentResponse & ServiceListQueuesSegmentHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: ServiceListQueuesSegmentHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: ListQueuesSegmentResponse; + }; +}; + +/** + * Contains response data for the create operation. + */ +export type QueueCreateResponse = QueueCreateHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: QueueCreateHeaders; + }; +}; + +/** + * Contains response data for the deleteMethod operation. + */ +export type QueueDeleteResponse = QueueDeleteHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: QueueDeleteHeaders; + }; +}; + +/** + * Contains response data for the getProperties operation. + */ +export type QueueGetPropertiesResponse = QueueGetPropertiesHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: QueueGetPropertiesHeaders; + }; +}; + +/** + * Contains response data for the setMetadata operation. + */ +export type QueueSetMetadataResponse = QueueSetMetadataHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: QueueSetMetadataHeaders; + }; +}; + +/** + * Contains response data for the getAccessPolicy operation. + */ +export type QueueGetAccessPolicyResponse = Array & QueueGetAccessPolicyHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: QueueGetAccessPolicyHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: SignedIdentifier[]; + }; +}; + +/** + * Contains response data for the setAccessPolicy operation. + */ +export type QueueSetAccessPolicyResponse = QueueSetAccessPolicyHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: QueueSetAccessPolicyHeaders; + }; +}; + +/** + * Contains response data for the dequeue operation. + */ +export type MessagesDequeueResponse = Array & MessagesDequeueHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: MessagesDequeueHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: DequeuedMessageItem[]; + }; +}; + +/** + * Contains response data for the clear operation. + */ +export type MessagesClearResponse = MessagesClearHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: MessagesClearHeaders; + }; +}; + +/** + * Contains response data for the enqueue operation. + */ +export type MessagesEnqueueResponse = Array & MessagesEnqueueHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: MessagesEnqueueHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: EnqueuedMessage[]; + }; +}; + +/** + * Contains response data for the peek operation. + */ +export type MessagesPeekResponse = Array & MessagesPeekHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: MessagesPeekHeaders; + /** + * The response body as text (string format) + */ + bodyAsText: string; + /** + * The response body as parsed JSON or XML + */ + parsedBody: PeekedMessageItem[]; + }; +}; + +/** + * Contains response data for the update operation. + */ +export type MessageIdUpdateResponse = MessageIdUpdateHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: MessageIdUpdateHeaders; + }; +}; + +/** + * Contains response data for the deleteMethod operation. + */ +export type MessageIdDeleteResponse = MessageIdDeleteHeaders & { + /** + * The underlying HTTP response. + */ + _response: msRest.HttpResponse & { + /** + * The parsed HTTP response headers. + */ + parsedHeaders: MessageIdDeleteHeaders; + }; +}; diff --git a/queue/lib/generated/models/mappers.ts b/queue/lib/generated/models/mappers.ts new file mode 100644 index 0000000..85236d7 --- /dev/null +++ b/queue/lib/generated/models/mappers.ts @@ -0,0 +1,1201 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; + + +export const AccessPolicy: msRest.CompositeMapper = { + serializedName: "AccessPolicy", + type: { + name: "Composite", + className: "AccessPolicy", + modelProperties: { + start: { + xmlName: "Start", + required: true, + serializedName: "Start", + type: { + name: "String" + } + }, + expiry: { + xmlName: "Expiry", + required: true, + serializedName: "Expiry", + type: { + name: "String" + } + }, + permission: { + xmlName: "Permission", + required: true, + serializedName: "Permission", + type: { + name: "String" + } + } + } + } +}; + +export const QueueItem: msRest.CompositeMapper = { + xmlName: "Queue", + serializedName: "QueueItem", + type: { + name: "Composite", + className: "QueueItem", + modelProperties: { + name: { + xmlName: "Name", + required: true, + serializedName: "Name", + type: { + name: "String" + } + }, + metadata: { + xmlName: "Metadata", + serializedName: "Metadata", + type: { + name: "Dictionary", + value: { + type: { + name: "String" + } + } + } + } + } + } +}; + +export const ListQueuesSegmentResponse: msRest.CompositeMapper = { + xmlName: "EnumerationResults", + serializedName: "ListQueuesSegmentResponse", + type: { + name: "Composite", + className: "ListQueuesSegmentResponse", + modelProperties: { + serviceEndpoint: { + xmlIsAttribute: true, + xmlName: "ServiceEndpoint", + required: true, + serializedName: "ServiceEndpoint", + type: { + name: "String" + } + }, + prefix: { + xmlName: "Prefix", + required: true, + serializedName: "Prefix", + type: { + name: "String" + } + }, + marker: { + xmlName: "Marker", + serializedName: "Marker", + type: { + name: "String" + } + }, + maxResults: { + xmlName: "MaxResults", + required: true, + serializedName: "MaxResults", + type: { + name: "Number" + } + }, + queueItems: { + xmlIsWrapped: true, + xmlName: "Queues", + xmlElementName: "Queue", + serializedName: "QueueItems", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "QueueItem" + } + } + } + }, + nextMarker: { + xmlName: "NextMarker", + required: true, + serializedName: "NextMarker", + type: { + name: "String" + } + } + } + } +}; + +export const CorsRule: msRest.CompositeMapper = { + serializedName: "CorsRule", + type: { + name: "Composite", + className: "CorsRule", + modelProperties: { + allowedOrigins: { + xmlName: "AllowedOrigins", + required: true, + serializedName: "AllowedOrigins", + type: { + name: "String" + } + }, + allowedMethods: { + xmlName: "AllowedMethods", + required: true, + serializedName: "AllowedMethods", + type: { + name: "String" + } + }, + allowedHeaders: { + xmlName: "AllowedHeaders", + required: true, + serializedName: "AllowedHeaders", + type: { + name: "String" + } + }, + exposedHeaders: { + xmlName: "ExposedHeaders", + required: true, + serializedName: "ExposedHeaders", + type: { + name: "String" + } + }, + maxAgeInSeconds: { + xmlName: "MaxAgeInSeconds", + required: true, + serializedName: "MaxAgeInSeconds", + constraints: { + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } + } + } +}; + +export const GeoReplication: msRest.CompositeMapper = { + serializedName: "GeoReplication", + type: { + name: "Composite", + className: "GeoReplication", + modelProperties: { + status: { + xmlName: "Status", + required: true, + serializedName: "Status", + type: { + name: "String" + } + }, + lastSyncTime: { + xmlName: "LastSyncTime", + required: true, + serializedName: "LastSyncTime", + type: { + name: "DateTimeRfc1123" + } + } + } + } +}; + +export const RetentionPolicy: msRest.CompositeMapper = { + serializedName: "RetentionPolicy", + type: { + name: "Composite", + className: "RetentionPolicy", + modelProperties: { + enabled: { + xmlName: "Enabled", + required: true, + serializedName: "Enabled", + type: { + name: "Boolean" + } + }, + days: { + xmlName: "Days", + serializedName: "Days", + constraints: { + InclusiveMinimum: 1 + }, + type: { + name: "Number" + } + } + } + } +}; + +export const Logging: msRest.CompositeMapper = { + serializedName: "Logging", + type: { + name: "Composite", + className: "Logging", + modelProperties: { + version: { + xmlName: "Version", + required: true, + serializedName: "Version", + type: { + name: "String" + } + }, + deleteProperty: { + xmlName: "Delete", + required: true, + serializedName: "Delete", + type: { + name: "Boolean" + } + }, + read: { + xmlName: "Read", + required: true, + serializedName: "Read", + type: { + name: "Boolean" + } + }, + write: { + xmlName: "Write", + required: true, + serializedName: "Write", + type: { + name: "Boolean" + } + }, + retentionPolicy: { + xmlName: "RetentionPolicy", + required: true, + serializedName: "RetentionPolicy", + type: { + name: "Composite", + className: "RetentionPolicy" + } + } + } + } +}; + +export const StorageError: msRest.CompositeMapper = { + serializedName: "StorageError", + type: { + name: "Composite", + className: "StorageError", + modelProperties: { + message: { + xmlName: "Message", + serializedName: "Message", + type: { + name: "String" + } + } + } + } +}; + +export const Metrics: msRest.CompositeMapper = { + serializedName: "Metrics", + type: { + name: "Composite", + className: "Metrics", + modelProperties: { + version: { + xmlName: "Version", + serializedName: "Version", + type: { + name: "String" + } + }, + enabled: { + xmlName: "Enabled", + required: true, + serializedName: "Enabled", + type: { + name: "Boolean" + } + }, + includeAPIs: { + xmlName: "IncludeAPIs", + serializedName: "IncludeAPIs", + type: { + name: "Boolean" + } + }, + retentionPolicy: { + xmlName: "RetentionPolicy", + serializedName: "RetentionPolicy", + type: { + name: "Composite", + className: "RetentionPolicy" + } + } + } + } +}; + +export const QueueMessage: msRest.CompositeMapper = { + serializedName: "QueueMessage", + type: { + name: "Composite", + className: "QueueMessage", + modelProperties: { + messageText: { + xmlName: "MessageText", + required: true, + serializedName: "MessageText", + type: { + name: "String" + } + } + } + } +}; + +export const DequeuedMessageItem: msRest.CompositeMapper = { + xmlName: "QueueMessage", + serializedName: "DequeuedMessageItem", + type: { + name: "Composite", + className: "DequeuedMessageItem", + modelProperties: { + messageId: { + xmlName: "MessageId", + required: true, + serializedName: "MessageId", + type: { + name: "String" + } + }, + insertionTime: { + xmlName: "InsertionTime", + required: true, + serializedName: "InsertionTime", + type: { + name: "DateTimeRfc1123" + } + }, + expirationTime: { + xmlName: "ExpirationTime", + required: true, + serializedName: "ExpirationTime", + type: { + name: "DateTimeRfc1123" + } + }, + popReceipt: { + xmlName: "PopReceipt", + required: true, + serializedName: "PopReceipt", + type: { + name: "String" + } + }, + timeNextVisible: { + xmlName: "TimeNextVisible", + required: true, + serializedName: "TimeNextVisible", + type: { + name: "DateTimeRfc1123" + } + }, + dequeueCount: { + xmlName: "DequeueCount", + required: true, + serializedName: "DequeueCount", + type: { + name: "Number" + } + }, + messageText: { + xmlName: "MessageText", + required: true, + serializedName: "MessageText", + type: { + name: "String" + } + } + } + } +}; + +export const PeekedMessageItem: msRest.CompositeMapper = { + xmlName: "QueueMessage", + serializedName: "PeekedMessageItem", + type: { + name: "Composite", + className: "PeekedMessageItem", + modelProperties: { + messageId: { + xmlName: "MessageId", + required: true, + serializedName: "MessageId", + type: { + name: "String" + } + }, + insertionTime: { + xmlName: "InsertionTime", + required: true, + serializedName: "InsertionTime", + type: { + name: "DateTimeRfc1123" + } + }, + expirationTime: { + xmlName: "ExpirationTime", + required: true, + serializedName: "ExpirationTime", + type: { + name: "DateTimeRfc1123" + } + }, + dequeueCount: { + xmlName: "DequeueCount", + required: true, + serializedName: "DequeueCount", + type: { + name: "Number" + } + }, + messageText: { + xmlName: "MessageText", + required: true, + serializedName: "MessageText", + type: { + name: "String" + } + } + } + } +}; + +export const EnqueuedMessage: msRest.CompositeMapper = { + xmlName: "QueueMessage", + serializedName: "EnqueuedMessage", + type: { + name: "Composite", + className: "EnqueuedMessage", + modelProperties: { + messageId: { + xmlName: "MessageId", + required: true, + serializedName: "MessageId", + type: { + name: "String" + } + }, + insertionTime: { + xmlName: "InsertionTime", + required: true, + serializedName: "InsertionTime", + type: { + name: "DateTimeRfc1123" + } + }, + expirationTime: { + xmlName: "ExpirationTime", + required: true, + serializedName: "ExpirationTime", + type: { + name: "DateTimeRfc1123" + } + }, + popReceipt: { + xmlName: "PopReceipt", + required: true, + serializedName: "PopReceipt", + type: { + name: "String" + } + }, + timeNextVisible: { + xmlName: "TimeNextVisible", + required: true, + serializedName: "TimeNextVisible", + type: { + name: "DateTimeRfc1123" + } + } + } + } +}; + +export const SignedIdentifier: msRest.CompositeMapper = { + serializedName: "SignedIdentifier", + type: { + name: "Composite", + className: "SignedIdentifier", + modelProperties: { + id: { + xmlName: "Id", + required: true, + serializedName: "Id", + type: { + name: "String" + } + }, + accessPolicy: { + xmlName: "AccessPolicy", + required: true, + serializedName: "AccessPolicy", + type: { + name: "Composite", + className: "AccessPolicy" + } + } + } + } +}; + +export const StorageServiceProperties: msRest.CompositeMapper = { + serializedName: "StorageServiceProperties", + type: { + name: "Composite", + className: "StorageServiceProperties", + modelProperties: { + logging: { + xmlName: "Logging", + serializedName: "Logging", + type: { + name: "Composite", + className: "Logging" + } + }, + hourMetrics: { + xmlName: "HourMetrics", + serializedName: "HourMetrics", + type: { + name: "Composite", + className: "Metrics" + } + }, + minuteMetrics: { + xmlName: "MinuteMetrics", + serializedName: "MinuteMetrics", + type: { + name: "Composite", + className: "Metrics" + } + }, + cors: { + xmlIsWrapped: true, + xmlName: "Cors", + xmlElementName: "CorsRule", + serializedName: "Cors", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "CorsRule" + } + } + } + } + } + } +}; + +export const StorageServiceStats: msRest.CompositeMapper = { + serializedName: "StorageServiceStats", + type: { + name: "Composite", + className: "StorageServiceStats", + modelProperties: { + geoReplication: { + xmlName: "GeoReplication", + serializedName: "GeoReplication", + type: { + name: "Composite", + className: "GeoReplication" + } + } + } + } +}; + +export const ServiceSetPropertiesHeaders: msRest.CompositeMapper = { + serializedName: "service-setproperties-headers", + type: { + name: "Composite", + className: "ServiceSetPropertiesHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const ServiceGetPropertiesHeaders: msRest.CompositeMapper = { + serializedName: "service-getproperties-headers", + type: { + name: "Composite", + className: "ServiceGetPropertiesHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const ServiceGetStatisticsHeaders: msRest.CompositeMapper = { + serializedName: "service-getstatistics-headers", + type: { + name: "Composite", + className: "ServiceGetStatisticsHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const ServiceListQueuesSegmentHeaders: msRest.CompositeMapper = { + serializedName: "service-listqueuessegment-headers", + type: { + name: "Composite", + className: "ServiceListQueuesSegmentHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const QueueCreateHeaders: msRest.CompositeMapper = { + serializedName: "queue-create-headers", + type: { + name: "Composite", + className: "QueueCreateHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const QueueDeleteHeaders: msRest.CompositeMapper = { + serializedName: "queue-delete-headers", + type: { + name: "Composite", + className: "QueueDeleteHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const QueueGetPropertiesHeaders: msRest.CompositeMapper = { + serializedName: "queue-getproperties-headers", + type: { + name: "Composite", + className: "QueueGetPropertiesHeaders", + modelProperties: { + metadata: { + serializedName: "x-ms-meta", + type: { + name: "Dictionary", + value: { + type: { + name: "String" + } + } + }, + headerCollectionPrefix: "x-ms-meta-" + }, + approximateMessagesCount: { + serializedName: "x-ms-approximate-messages-count", + type: { + name: "Number" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const QueueSetMetadataHeaders: msRest.CompositeMapper = { + serializedName: "queue-setmetadata-headers", + type: { + name: "Composite", + className: "QueueSetMetadataHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const QueueGetAccessPolicyHeaders: msRest.CompositeMapper = { + serializedName: "queue-getaccesspolicy-headers", + type: { + name: "Composite", + className: "QueueGetAccessPolicyHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const QueueSetAccessPolicyHeaders: msRest.CompositeMapper = { + serializedName: "queue-setaccesspolicy-headers", + type: { + name: "Composite", + className: "QueueSetAccessPolicyHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const MessagesDequeueHeaders: msRest.CompositeMapper = { + serializedName: "messages-dequeue-headers", + type: { + name: "Composite", + className: "MessagesDequeueHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const MessagesClearHeaders: msRest.CompositeMapper = { + serializedName: "messages-clear-headers", + type: { + name: "Composite", + className: "MessagesClearHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const MessagesEnqueueHeaders: msRest.CompositeMapper = { + serializedName: "messages-enqueue-headers", + type: { + name: "Composite", + className: "MessagesEnqueueHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const MessagesPeekHeaders: msRest.CompositeMapper = { + serializedName: "messages-peek-headers", + type: { + name: "Composite", + className: "MessagesPeekHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const MessageIdUpdateHeaders: msRest.CompositeMapper = { + serializedName: "messageid-update-headers", + type: { + name: "Composite", + className: "MessageIdUpdateHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + popReceipt: { + serializedName: "x-ms-popreceipt", + type: { + name: "String" + } + }, + timeNextVisible: { + serializedName: "x-ms-time-next-visible", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const MessageIdDeleteHeaders: msRest.CompositeMapper = { + serializedName: "messageid-delete-headers", + type: { + name: "Composite", + className: "MessageIdDeleteHeaders", + modelProperties: { + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; diff --git a/queue/lib/generated/models/messageIDMappers.ts b/queue/lib/generated/models/messageIDMappers.ts new file mode 100644 index 0000000..7dcf981 --- /dev/null +++ b/queue/lib/generated/models/messageIDMappers.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +export { + QueueMessage, + MessageIdUpdateHeaders, + StorageError, + MessageIdDeleteHeaders +} from "../models/mappers"; + diff --git a/queue/lib/generated/models/messagesMappers.ts b/queue/lib/generated/models/messagesMappers.ts new file mode 100644 index 0000000..06f3460 --- /dev/null +++ b/queue/lib/generated/models/messagesMappers.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +export { + DequeuedMessageItem, + MessagesDequeueHeaders, + StorageError, + MessagesClearHeaders, + QueueMessage, + EnqueuedMessage, + MessagesEnqueueHeaders, + PeekedMessageItem, + MessagesPeekHeaders +} from "../models/mappers"; + diff --git a/queue/lib/generated/models/parameters.ts b/queue/lib/generated/models/parameters.ts new file mode 100644 index 0000000..df4379c --- /dev/null +++ b/queue/lib/generated/models/parameters.ts @@ -0,0 +1,289 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; + +export const comp0: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'properties', + type: { + name: "String" + } + } +}; +export const comp1: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'stats', + type: { + name: "String" + } + } +}; +export const comp2: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'list', + type: { + name: "String" + } + } +}; +export const comp3: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'metadata', + type: { + name: "String" + } + } +}; +export const comp4: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'acl', + type: { + name: "String" + } + } +}; +export const include: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "include" + ], + mapper: { + serializedName: "include", + type: { + name: "Enum", + allowedValues: [ + "metadata" + ] + } + } +}; +export const marker: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "marker" + ], + mapper: { + serializedName: "marker", + type: { + name: "String" + } + } +}; +export const maxresults: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "maxresults" + ], + mapper: { + serializedName: "maxresults", + constraints: { + InclusiveMinimum: 1 + }, + type: { + name: "Number" + } + } +}; +export const messageTimeToLive: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "messageTimeToLive" + ], + mapper: { + serializedName: "messagettl", + constraints: { + InclusiveMinimum: -1 + }, + type: { + name: "Number" + } + } +}; +export const metadata: msRest.OperationParameter = { + parameterPath: [ + "options", + "metadata" + ], + mapper: { + serializedName: "x-ms-meta", + type: { + name: "Dictionary", + value: { + type: { + name: "String" + } + } + }, + headerCollectionPrefix: "x-ms-meta-" + } +}; +export const numberOfMessages: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "numberOfMessages" + ], + mapper: { + serializedName: "numofmessages", + constraints: { + InclusiveMinimum: 1 + }, + type: { + name: "Number" + } + } +}; +export const peekonly: msRest.OperationQueryParameter = { + parameterPath: "peekonly", + mapper: { + required: true, + isConstant: true, + serializedName: "peekonly", + defaultValue: 'true', + type: { + name: "String" + } + } +}; +export const popReceipt: msRest.OperationQueryParameter = { + parameterPath: "popReceipt", + mapper: { + required: true, + serializedName: "popreceipt", + type: { + name: "String" + } + } +}; +export const prefix: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "prefix" + ], + mapper: { + serializedName: "prefix", + type: { + name: "String" + } + } +}; +export const requestId: msRest.OperationParameter = { + parameterPath: [ + "options", + "requestId" + ], + mapper: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + } +}; +export const restype: msRest.OperationQueryParameter = { + parameterPath: "restype", + mapper: { + required: true, + isConstant: true, + serializedName: "restype", + defaultValue: 'service', + type: { + name: "String" + } + } +}; +export const timeout: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "timeout" + ], + mapper: { + serializedName: "timeout", + constraints: { + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } +}; +export const url: msRest.OperationURLParameter = { + parameterPath: "url", + mapper: { + required: true, + serializedName: "url", + defaultValue: '', + type: { + name: "String" + } + }, + skipEncoding: true +}; +export const version: msRest.OperationParameter = { + parameterPath: "version", + mapper: { + required: true, + isConstant: true, + serializedName: "x-ms-version", + defaultValue: '2018-03-28', + type: { + name: "String" + } + } +}; +export const visibilitytimeout0: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "visibilitytimeout" + ], + mapper: { + serializedName: "visibilitytimeout", + constraints: { + InclusiveMaximum: 604800, + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } +}; +export const visibilitytimeout1: msRest.OperationQueryParameter = { + parameterPath: "visibilitytimeout", + mapper: { + required: true, + serializedName: "visibilitytimeout", + constraints: { + InclusiveMaximum: 604800, + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } +}; diff --git a/queue/lib/generated/models/queueMappers.ts b/queue/lib/generated/models/queueMappers.ts new file mode 100644 index 0000000..136df44 --- /dev/null +++ b/queue/lib/generated/models/queueMappers.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +export { + QueueCreateHeaders, + StorageError, + QueueDeleteHeaders, + QueueGetPropertiesHeaders, + QueueSetMetadataHeaders, + SignedIdentifier, + AccessPolicy, + QueueGetAccessPolicyHeaders, + QueueSetAccessPolicyHeaders +} from "../models/mappers"; + diff --git a/queue/lib/generated/models/serviceMappers.ts b/queue/lib/generated/models/serviceMappers.ts new file mode 100644 index 0000000..58e3c8c --- /dev/null +++ b/queue/lib/generated/models/serviceMappers.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +export { + StorageServiceProperties, + Logging, + RetentionPolicy, + Metrics, + CorsRule, + ServiceSetPropertiesHeaders, + StorageError, + ServiceGetPropertiesHeaders, + StorageServiceStats, + GeoReplication, + ServiceGetStatisticsHeaders, + ListQueuesSegmentResponse, + QueueItem, + ServiceListQueuesSegmentHeaders +} from "../models/mappers"; + diff --git a/queue/lib/generated/operations/index.ts b/queue/lib/generated/operations/index.ts new file mode 100644 index 0000000..a47d039 --- /dev/null +++ b/queue/lib/generated/operations/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +export * from "./service"; +export * from "./queue"; +export * from "./messages"; +export * from "./messageId"; diff --git a/queue/lib/generated/operations/messageID.ts b/queue/lib/generated/operations/messageID.ts new file mode 100644 index 0000000..95dc021 --- /dev/null +++ b/queue/lib/generated/operations/messageID.ts @@ -0,0 +1,161 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; +import * as Models from "../models"; +import * as Mappers from "../models/messageIdMappers"; +import * as Parameters from "../models/parameters"; +import { StorageClientContext } from "../storageClientContext"; + +/** Class representing a MessageId. */ +export class MessageId { + private readonly client: StorageClientContext; + + /** + * Create a MessageId. + * @param {StorageClientContext} client Reference to the service client. + */ + constructor(client: StorageClientContext) { + this.client = client; + } + + /** + * The Update operation was introduced with version 2011-08-18 of the Queue service API. The Update + * Message operation updates the visibility timeout of a message. You can also use this operation + * to update the contents of a message. A message must be in a format that can be included in an + * XML request with UTF-8 encoding, and the encoded message can be up to 64KB in size. + * + * @param {QueueMessage} queueMessage A Message object which can be stored in a Queue + * + * @param {string} popReceipt Required. Specifies the valid pop receipt value returned from an + * earlier call to the Get Messages or Update Message operation. + * + * @param {number} visibilitytimeout Optional. Specifies the new visibility timeout value, in + * seconds, relative to server time. The default value is 30 seconds. A specified value must be + * larger than or equal to 1 second, and cannot be larger than 7 days, or larger than 2 hours on + * REST protocol versions prior to version 2011-08-18. The visibility timeout of a message can be + * set to a value later than the expiry time. + * + * @param {MessageIdUpdateOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + update(queueMessage: Models.QueueMessage, popReceipt: string, visibilitytimeout: number): Promise; + update(queueMessage: Models.QueueMessage, popReceipt: string, visibilitytimeout: number, options: Models.MessageIdUpdateOptionalParams): Promise; + update(queueMessage: Models.QueueMessage, popReceipt: string, visibilitytimeout: number, callback: msRest.ServiceCallback): void; + update(queueMessage: Models.QueueMessage, popReceipt: string, visibilitytimeout: number, options: Models.MessageIdUpdateOptionalParams, callback: msRest.ServiceCallback): void; + update(queueMessage: Models.QueueMessage, popReceipt: string, visibilitytimeout: number, options?: Models.MessageIdUpdateOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + queueMessage, + popReceipt, + visibilitytimeout, + options + }, + updateOperationSpec, + callback) as Promise; + } + + /** + * The Delete operation deletes the specified message. + * + * @param {string} popReceipt Required. Specifies the valid pop receipt value returned from an + * earlier call to the Get Messages or Update Message operation. + * + * @param {MessageIdDeleteMethodOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + deleteMethod(popReceipt: string): Promise; + deleteMethod(popReceipt: string, options: Models.MessageIdDeleteMethodOptionalParams): Promise; + deleteMethod(popReceipt: string, callback: msRest.ServiceCallback): void; + deleteMethod(popReceipt: string, options: Models.MessageIdDeleteMethodOptionalParams, callback: msRest.ServiceCallback): void; + deleteMethod(popReceipt: string, options?: Models.MessageIdDeleteMethodOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + popReceipt, + options + }, + deleteMethodOperationSpec, + callback) as Promise; + } + +} + +// Operation Specifications +const serializer = new msRest.Serializer(Mappers, true); +const updateOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + path: "{queueName}/messages/{messageid}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.popReceipt, + Parameters.visibilitytimeout1, + Parameters.timeout + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + requestBody: { + parameterPath: "queueMessage", + mapper: { + ...Mappers.QueueMessage, + required: true + } + }, + contentType: "application/xml; charset=utf-8", + responses: { + 204: { + headersMapper: Mappers.MessageIdUpdateHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const deleteMethodOperationSpec: msRest.OperationSpec = { + httpMethod: "DELETE", + path: "{queueName}/messages/{messageid}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.popReceipt, + Parameters.timeout + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 204: { + headersMapper: Mappers.MessageIdDeleteHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; diff --git a/queue/lib/generated/operations/messages.ts b/queue/lib/generated/operations/messages.ts new file mode 100644 index 0000000..057d4b9 --- /dev/null +++ b/queue/lib/generated/operations/messages.ts @@ -0,0 +1,288 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; +import * as Models from "../models"; +import * as Mappers from "../models/messagesMappers"; +import * as Parameters from "../models/parameters"; +import { StorageClientContext } from "../storageClientContext"; + +/** Class representing a Messages. */ +export class Messages { + private readonly client: StorageClientContext; + + /** + * Create a Messages. + * @param {StorageClientContext} client Reference to the service client. + */ + constructor(client: StorageClientContext) { + this.client = client; + } + + /** + * The Dequeue operation retrieves one or more messages from the front of the queue. + * + * @param {MessagesDequeueOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + dequeue(): Promise; + dequeue(options: Models.MessagesDequeueOptionalParams): Promise; + dequeue(callback: msRest.ServiceCallback): void; + dequeue(options: Models.MessagesDequeueOptionalParams, callback: msRest.ServiceCallback): void; + dequeue(options?: Models.MessagesDequeueOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + dequeueOperationSpec, + callback) as Promise; + } + + /** + * The Clear operation deletes all messages from the specified queue. + * + * @param {MessagesClearOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + clear(): Promise; + clear(options: Models.MessagesClearOptionalParams): Promise; + clear(callback: msRest.ServiceCallback): void; + clear(options: Models.MessagesClearOptionalParams, callback: msRest.ServiceCallback): void; + clear(options?: Models.MessagesClearOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + clearOperationSpec, + callback) as Promise; + } + + /** + * The Enqueue operation adds a new message to the back of the message queue. A visibility timeout + * can also be specified to make the message invisible until the visibility timeout expires. A + * message must be in a format that can be included in an XML request with UTF-8 encoding. The + * encoded message can be up to 64 KB in size for versions 2011-08-18 and newer, or 8 KB in size + * for previous versions. + * + * @param {QueueMessage} queueMessage A Message object which can be stored in a Queue + * + * @param {MessagesEnqueueOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + enqueue(queueMessage: Models.QueueMessage): Promise; + enqueue(queueMessage: Models.QueueMessage, options: Models.MessagesEnqueueOptionalParams): Promise; + enqueue(queueMessage: Models.QueueMessage, callback: msRest.ServiceCallback): void; + enqueue(queueMessage: Models.QueueMessage, options: Models.MessagesEnqueueOptionalParams, callback: msRest.ServiceCallback): void; + enqueue(queueMessage: Models.QueueMessage, options?: Models.MessagesEnqueueOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + queueMessage, + options + }, + enqueueOperationSpec, + callback) as Promise; + } + + /** + * The Peek operation retrieves one or more messages from the front of the queue, but does not + * alter the visibility of the message. + * + * @param {MessagesPeekOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + peek(): Promise; + peek(options: Models.MessagesPeekOptionalParams): Promise; + peek(callback: msRest.ServiceCallback): void; + peek(options: Models.MessagesPeekOptionalParams, callback: msRest.ServiceCallback): void; + peek(options?: Models.MessagesPeekOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + peekOperationSpec, + callback) as Promise; + } + +} + +// Operation Specifications +const serializer = new msRest.Serializer(Mappers, true); +const dequeueOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{queueName}/messages", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.numberOfMessages, + Parameters.visibilitytimeout0, + Parameters.timeout + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: { + xmlElementName: "QueueMessage", + serializedName: "parsedResponse", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "DequeuedMessageItem" + } + } + } + }, + headersMapper: Mappers.MessagesDequeueHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const clearOperationSpec: msRest.OperationSpec = { + httpMethod: "DELETE", + path: "{queueName}/messages", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 204: { + headersMapper: Mappers.MessagesClearHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const enqueueOperationSpec: msRest.OperationSpec = { + httpMethod: "POST", + path: "{queueName}/messages", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.visibilitytimeout0, + Parameters.messageTimeToLive, + Parameters.timeout + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + requestBody: { + parameterPath: "queueMessage", + mapper: { + ...Mappers.QueueMessage, + required: true + } + }, + contentType: "application/xml; charset=utf-8", + responses: { + 201: { + bodyMapper: { + xmlElementName: "QueueMessage", + serializedName: "parsedResponse", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "EnqueuedMessage" + } + } + } + }, + headersMapper: Mappers.MessagesEnqueueHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const peekOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{queueName}/messages", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.numberOfMessages, + Parameters.timeout, + Parameters.peekonly + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: { + xmlElementName: "QueueMessage", + serializedName: "parsedResponse", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "PeekedMessageItem" + } + } + } + }, + headersMapper: Mappers.MessagesPeekHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; diff --git a/queue/lib/generated/operations/queue.ts b/queue/lib/generated/operations/queue.ts new file mode 100644 index 0000000..7e75eb5 --- /dev/null +++ b/queue/lib/generated/operations/queue.ts @@ -0,0 +1,371 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; +import * as Models from "../models"; +import * as Mappers from "../models/queueMappers"; +import * as Parameters from "../models/parameters"; +import { StorageClientContext } from "../storageClientContext"; + +/** Class representing a Queue. */ +export class Queue { + private readonly client: StorageClientContext; + + /** + * Create a Queue. + * @param {StorageClientContext} client Reference to the service client. + */ + constructor(client: StorageClientContext) { + this.client = client; + } + + /** + * creates a new queue under the given account. + * + * @param {QueueCreateOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + create(): Promise; + create(options: Models.QueueCreateOptionalParams): Promise; + create(callback: msRest.ServiceCallback): void; + create(options: Models.QueueCreateOptionalParams, callback: msRest.ServiceCallback): void; + create(options?: Models.QueueCreateOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + createOperationSpec, + callback) as Promise; + } + + /** + * operation permanently deletes the specified queue + * + * @param {QueueDeleteMethodOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + deleteMethod(): Promise; + deleteMethod(options: Models.QueueDeleteMethodOptionalParams): Promise; + deleteMethod(callback: msRest.ServiceCallback): void; + deleteMethod(options: Models.QueueDeleteMethodOptionalParams, callback: msRest.ServiceCallback): void; + deleteMethod(options?: Models.QueueDeleteMethodOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + deleteMethodOperationSpec, + callback) as Promise; + } + + /** + * Retrieves user-defined metadata and queue properties on the specified queue. Metadata is + * associated with the queue as name-values pairs. + * + * @param {QueueGetPropertiesOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + getProperties(): Promise; + getProperties(options: Models.QueueGetPropertiesOptionalParams): Promise; + getProperties(callback: msRest.ServiceCallback): void; + getProperties(options: Models.QueueGetPropertiesOptionalParams, callback: msRest.ServiceCallback): void; + getProperties(options?: Models.QueueGetPropertiesOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + getPropertiesOperationSpec, + callback) as Promise; + } + + /** + * sets user-defined metadata on the specified queue. Metadata is associated with the queue as + * name-value pairs. + * + * @param {QueueSetMetadataOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + setMetadata(): Promise; + setMetadata(options: Models.QueueSetMetadataOptionalParams): Promise; + setMetadata(callback: msRest.ServiceCallback): void; + setMetadata(options: Models.QueueSetMetadataOptionalParams, callback: msRest.ServiceCallback): void; + setMetadata(options?: Models.QueueSetMetadataOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + setMetadataOperationSpec, + callback) as Promise; + } + + /** + * returns details about any stored access policies specified on the queue that may be used with + * Shared Access Signatures. + * + * @param {QueueGetAccessPolicyOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + getAccessPolicy(): Promise; + getAccessPolicy(options: Models.QueueGetAccessPolicyOptionalParams): Promise; + getAccessPolicy(callback: msRest.ServiceCallback): void; + getAccessPolicy(options: Models.QueueGetAccessPolicyOptionalParams, callback: msRest.ServiceCallback): void; + getAccessPolicy(options?: Models.QueueGetAccessPolicyOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + getAccessPolicyOperationSpec, + callback) as Promise; + } + + /** + * sets stored access policies for the queue that may be used with Shared Access Signatures + * + * @param {QueueSetAccessPolicyOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + setAccessPolicy(): Promise; + setAccessPolicy(options: Models.QueueSetAccessPolicyOptionalParams): Promise; + setAccessPolicy(callback: msRest.ServiceCallback): void; + setAccessPolicy(options: Models.QueueSetAccessPolicyOptionalParams, callback: msRest.ServiceCallback): void; + setAccessPolicy(options?: Models.QueueSetAccessPolicyOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + setAccessPolicyOperationSpec, + callback) as Promise; + } + +} + +// Operation Specifications +const serializer = new msRest.Serializer(Mappers, true); +const createOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + path: "{queueName}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout + ], + headerParameters: [ + Parameters.metadata, + Parameters.version, + Parameters.requestId + ], + responses: { + 201: { + headersMapper: Mappers.QueueCreateHeaders + }, + 204: { + headersMapper: Mappers.QueueCreateHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const deleteMethodOperationSpec: msRest.OperationSpec = { + httpMethod: "DELETE", + path: "{queueName}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 204: { + headersMapper: Mappers.QueueDeleteHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const getPropertiesOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{queueName}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp3 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + headersMapper: Mappers.QueueGetPropertiesHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const setMetadataOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + path: "{queueName}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp3 + ], + headerParameters: [ + Parameters.metadata, + Parameters.version, + Parameters.requestId + ], + responses: { + 204: { + headersMapper: Mappers.QueueSetMetadataHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const getAccessPolicyOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{queueName}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp4 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: { + xmlElementName: "SignedIdentifier", + serializedName: "parsedResponse", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "SignedIdentifier" + } + } + } + }, + headersMapper: Mappers.QueueGetAccessPolicyHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const setAccessPolicyOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + path: "{queueName}", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp4 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + requestBody: { + parameterPath: [ + "options", + "queueAcl" + ], + mapper: { + xmlName: "SignedIdentifiers", + xmlElementName: "SignedIdentifier", + serializedName: "queueAcl", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "SignedIdentifier" + } + } + } + } + }, + contentType: "application/xml; charset=utf-8", + responses: { + 204: { + headersMapper: Mappers.QueueSetAccessPolicyHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; diff --git a/queue/lib/generated/operations/service.ts b/queue/lib/generated/operations/service.ts new file mode 100644 index 0000000..fb9a37c --- /dev/null +++ b/queue/lib/generated/operations/service.ts @@ -0,0 +1,252 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; +import * as Models from "../models"; +import * as Mappers from "../models/serviceMappers"; +import * as Parameters from "../models/parameters"; +import { StorageClientContext } from "../storageClientContext"; + +/** Class representing a Service. */ +export class Service { + private readonly client: StorageClientContext; + + /** + * Create a Service. + * @param {StorageClientContext} client Reference to the service client. + */ + constructor(client: StorageClientContext) { + this.client = client; + } + + /** + * Sets properties for a storage account's Queue service endpoint, including properties for Storage + * Analytics and CORS (Cross-Origin Resource Sharing) rules + * + * @param {StorageServiceProperties} storageServiceProperties The StorageService properties. + * + * @param {ServiceSetPropertiesOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + setProperties(storageServiceProperties: Models.StorageServiceProperties): Promise; + setProperties(storageServiceProperties: Models.StorageServiceProperties, options: Models.ServiceSetPropertiesOptionalParams): Promise; + setProperties(storageServiceProperties: Models.StorageServiceProperties, callback: msRest.ServiceCallback): void; + setProperties(storageServiceProperties: Models.StorageServiceProperties, options: Models.ServiceSetPropertiesOptionalParams, callback: msRest.ServiceCallback): void; + setProperties(storageServiceProperties: Models.StorageServiceProperties, options?: Models.ServiceSetPropertiesOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + storageServiceProperties, + options + }, + setPropertiesOperationSpec, + callback) as Promise; + } + + /** + * gets the properties of a storage account's Queue service, including properties for Storage + * Analytics and CORS (Cross-Origin Resource Sharing) rules. + * + * @param {ServiceGetPropertiesOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + getProperties(): Promise; + getProperties(options: Models.ServiceGetPropertiesOptionalParams): Promise; + getProperties(callback: msRest.ServiceCallback): void; + getProperties(options: Models.ServiceGetPropertiesOptionalParams, callback: msRest.ServiceCallback): void; + getProperties(options?: Models.ServiceGetPropertiesOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + getPropertiesOperationSpec, + callback) as Promise; + } + + /** + * Retrieves statistics related to replication for the Queue service. It is only available on the + * secondary location endpoint when read-access geo-redundant replication is enabled for the + * storage account. + * + * @param {ServiceGetStatisticsOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + getStatistics(): Promise; + getStatistics(options: Models.ServiceGetStatisticsOptionalParams): Promise; + getStatistics(callback: msRest.ServiceCallback): void; + getStatistics(options: Models.ServiceGetStatisticsOptionalParams, callback: msRest.ServiceCallback): void; + getStatistics(options?: Models.ServiceGetStatisticsOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + getStatisticsOperationSpec, + callback) as Promise; + } + + /** + * The List Queues Segment operation returns a list of the queues under the specified account + * + * @param {ServiceListQueuesSegmentOptionalParams} [options] Optional Parameters. + * + * @returns {Promise} A promise is returned + * + * @resolve {HttpOperationResponse} The deserialized result object. + * + * @reject {Error|ServiceError} The error object. + */ + listQueuesSegment(): Promise; + listQueuesSegment(options: Models.ServiceListQueuesSegmentOptionalParams): Promise; + listQueuesSegment(callback: msRest.ServiceCallback): void; + listQueuesSegment(options: Models.ServiceListQueuesSegmentOptionalParams, callback: msRest.ServiceCallback): void; + listQueuesSegment(options?: Models.ServiceListQueuesSegmentOptionalParams, callback?: msRest.ServiceCallback): Promise { + return this.client.sendOperationRequest( + { + options + }, + listQueuesSegmentOperationSpec, + callback) as Promise; + } + +} + +// Operation Specifications +const serializer = new msRest.Serializer(Mappers, true); +const setPropertiesOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + requestBody: { + parameterPath: "storageServiceProperties", + mapper: { + ...Mappers.StorageServiceProperties, + required: true + } + }, + contentType: "application/xml; charset=utf-8", + responses: { + 202: { + headersMapper: Mappers.ServiceSetPropertiesHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const getPropertiesOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: Mappers.StorageServiceProperties, + headersMapper: Mappers.ServiceGetPropertiesHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const getStatisticsOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: Mappers.StorageServiceStats, + headersMapper: Mappers.ServiceGetStatisticsHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; + +const listQueuesSegmentOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.prefix, + Parameters.marker, + Parameters.maxresults, + Parameters.include, + Parameters.timeout, + Parameters.comp2 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: Mappers.ListQueuesSegmentResponse, + headersMapper: Mappers.ServiceListQueuesSegmentHeaders + }, + default: { + bodyMapper: Mappers.StorageError + } + }, + isXML: true, + serializer +}; diff --git a/queue/lib/generated/storageClient.ts b/queue/lib/generated/storageClient.ts new file mode 100644 index 0000000..8a67390 --- /dev/null +++ b/queue/lib/generated/storageClient.ts @@ -0,0 +1,56 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; +import * as Models from "./models"; +import * as Mappers from "./models/mappers"; +import * as operations from "./operations"; +import { StorageClientContext } from "./storageClientContext"; + +class StorageClient extends StorageClientContext { + // Operation groups + service: operations.Service; + queue: operations.Queue; + messages: operations.Messages; + messageId: operations.MessageId; + + /** + * @class + * Initializes a new instance of the StorageClient class. + * @constructor + * + * @param {object} [options] - The parameter options + * + * @param {Array} [options.filters] - Filters to be added to the request pipeline + * + * @param {object} [options.requestOptions] - The request options. Detailed info can be found at + * {@link https://github.github.io/fetch/#Request Options doc} + * + * @param {boolean} [options.noRetryPolicy] - If set to true, turn off default retry policy + * + */ + constructor(url: string, options?: msRest.ServiceClientOptions) { + super(url, options); + this.service = new operations.Service(this); + this.queue = new operations.Queue(this); + this.messages = new operations.Messages(this); + this.messageId = new operations.MessageId(this); + } +} + +// Operation Specifications + +export { + StorageClient, + StorageClientContext, + Models as StorageModels, + Mappers as StorageMappers +}; +export * from "./operations"; diff --git a/queue/lib/generated/storageClientContext.ts b/queue/lib/generated/storageClientContext.ts new file mode 100644 index 0000000..67a2823 --- /dev/null +++ b/queue/lib/generated/storageClientContext.ts @@ -0,0 +1,55 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +import * as msRest from "ms-rest-js"; + +const packageName = ""; +const packageVersion = ""; + +export class StorageClientContext extends msRest.ServiceClient { + url: string; + version: string; + + /** + * @class + * Initializes a new instance of the StorageClientContext class. + * @constructor + * + * @param {string} url - The URL of the service account, queue or message that is the targe of the desired operation. + * + * @param {object} [options] - The parameter options + * + * @param {Array} [options.filters] - Filters to be added to the request pipeline + * + * @param {object} [options.requestOptions] - The request options. Detailed info can be found at + * {@link https://github.github.io/fetch/#Request Options doc} + * + * @param {boolean} [options.noRetryPolicy] - If set to true, turn off default retry policy + * + */ + constructor(url: string, options?: msRest.ServiceClientOptions) { + if (url === null || url === undefined) { + throw new Error('\'url\' cannot be null.'); + } + + if (!options) { + options = {}; + } + + super(undefined, options); + + this.version = '2018-03-28'; + this.baseUri = "{url}"; + this.requestContentType = "application/json; charset=utf-8"; + this.url = url; + + this.addUserAgentInfo(`${packageName}/${packageVersion}`); + } +} diff --git a/queue/lib/index.browser.ts b/queue/lib/index.browser.ts new file mode 100644 index 0000000..97fef61 --- /dev/null +++ b/queue/lib/index.browser.ts @@ -0,0 +1,25 @@ +import { RestError } from "ms-rest-js"; + +import * as Models from "../lib/generated/models"; + +export * from "./Aborter"; +export * from "./credentials/AnonymousCredential"; +export * from "./credentials/Credential"; +export * from "./credentials/TokenCredential"; +export { IIPRange } from "./IIPRange"; +export * from "./MessageIdURL"; +export * from "./MessagesURL"; +export * from "./Pipeline"; +export * from "./policies/AnonymousCredentialPolicy"; +export * from "./policies/CredentialPolicy"; +export * from "./RetryPolicyFactory"; +export * from "./LoggingPolicyFactory"; +export * from "./TelemetryPolicyFactory"; +export * from "./policies/TokenCredentialPolicy"; +export * from "./QueueURL" +export * from "./QueueSASPermissions"; +export * from "./UniqueRequestIDPolicyFactory"; +export * from "./SASQueryParameters"; +export * from "./ServiceURL"; +export * from "./StorageURL"; +export { Models, RestError }; diff --git a/queue/lib/index.ts b/queue/lib/index.ts new file mode 100644 index 0000000..f68aeb1 --- /dev/null +++ b/queue/lib/index.ts @@ -0,0 +1,31 @@ +import { RestError } from "ms-rest-js"; + +import * as Models from "../lib/generated/models"; + +export * from "./Aborter"; +export * from "./AccountSASPermissions"; +export * from "./AccountSASResourceTypes"; +export * from "./AccountSASServices"; +export * from "./IAccountSASSignatureValues"; +export * from "./credentials/AnonymousCredential"; +export * from "./credentials/Credential"; +export * from "./credentials/SharedKeyCredential"; +export * from "./credentials/TokenCredential"; +export { IIPRange } from "./IIPRange"; +export * from "./MessageIdURL"; +export * from "./MessagesURL"; +export * from "./Pipeline"; +export * from "./policies/AnonymousCredentialPolicy"; +export * from "./policies/CredentialPolicy"; +export * from "./RetryPolicyFactory"; +export * from "./LoggingPolicyFactory"; +export * from "./policies/SharedKeyCredentialPolicy"; +export * from "./TelemetryPolicyFactory"; +export * from "./policies/TokenCredentialPolicy"; +export * from "./QueueURL" +export * from "./QueueSASPermissions"; +export * from "./IQueueSASSignatureValues" +export * from "./UniqueRequestIDPolicyFactory"; +export * from "./ServiceURL"; +export * from "./StorageURL"; +export { Models, RestError }; diff --git a/queue/lib/models.ts b/queue/lib/models.ts new file mode 100644 index 0000000..737bf9d --- /dev/null +++ b/queue/lib/models.ts @@ -0,0 +1,3 @@ +export interface IMetadata { + [propertyName: string]: string; +} \ No newline at end of file diff --git a/queue/lib/policies/AnonymousCredentialPolicy.ts b/queue/lib/policies/AnonymousCredentialPolicy.ts new file mode 100644 index 0000000..e7d5924 --- /dev/null +++ b/queue/lib/policies/AnonymousCredentialPolicy.ts @@ -0,0 +1,23 @@ +import { RequestPolicy, RequestPolicyOptions } from "ms-rest-js"; + +import { CredentialPolicy } from "./CredentialPolicy"; + +/** + * AnonymousCredentialPolicy is used with HTTP(S) requests that read public resources + * or for use with Shared Access Signatures (SAS). + * + * @export + * @class AnonymousCredentialPolicy + * @extends {CredentialPolicy} + */ +export class AnonymousCredentialPolicy extends CredentialPolicy { + /** + * Creates an instance of AnonymousCredentialPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @memberof AnonymousCredentialPolicy + */ + constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions) { + super(nextPolicy, options); + } +} diff --git a/queue/lib/policies/BrowserPolicy.ts b/queue/lib/policies/BrowserPolicy.ts new file mode 100644 index 0000000..5f417e7 --- /dev/null +++ b/queue/lib/policies/BrowserPolicy.ts @@ -0,0 +1,70 @@ +import { + BaseRequestPolicy, + HttpOperationResponse, + isNode, + RequestPolicy, + RequestPolicyOptions, + WebResource +} from "ms-rest-js"; + +import { HeaderConstants, URLConstants } from "../utils/constants"; +import { setURLParameter } from "../utils/utils.common"; + +/** + * BrowserPolicy will handle differences between Node.js and browser runtime, including: + * + * 1. Browsers cache GET/HEAD requests by adding conditional headers such as 'IF_MODIFIED_SINCE'. + * BrowserPolicy is a policy used to add a timestamp query to GET/HEAD request URL + * thus avoid the browser cache. + * + * 2. Remove cookie header for security + * + * 3. Remove content-length header to avoid browsers warning + * + * @class BrowserPolicy + * @extends {BaseRequestPolicy} + */ +export class BrowserPolicy extends BaseRequestPolicy { + /** + * Creates an instance of BrowserPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @memberof BrowserPolicy + */ + constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions) { + super(nextPolicy, options); + } + + /** + * Sends out request. + * + * @param {WebResource} request + * @returns {Promise} + * @memberof BrowserPolicy + */ + public async sendRequest( + request: WebResource + ): Promise { + if (isNode) { + return this._nextPolicy.sendRequest(request); + } + + if ( + request.method.toUpperCase() === "GET" || + request.method.toUpperCase() === "HEAD" + ) { + request.url = setURLParameter( + request.url, + URLConstants.Parameters.FORCE_BROWSER_NO_CACHE, + new Date().getTime().toString() + ); + } + + request.headers.remove(HeaderConstants.COOKIE); + + // According to XHR standards, content-length should be fully controlled by browsers + request.headers.remove(HeaderConstants.CONTENT_LENGTH); + + return this._nextPolicy.sendRequest(request); + } +} diff --git a/queue/lib/policies/CredentialPolicy.ts b/queue/lib/policies/CredentialPolicy.ts new file mode 100644 index 0000000..1a5dcc7 --- /dev/null +++ b/queue/lib/policies/CredentialPolicy.ts @@ -0,0 +1,43 @@ +import { + BaseRequestPolicy, + HttpOperationResponse, + WebResource +} from "ms-rest-js"; + +/** + * Credential policy used to sign HTTP(S) requests before sending. This is an + * abstract class. + * + * @export + * @abstract + * @class CredentialPolicy + * @extends {BaseRequestPolicy} + */ +export abstract class CredentialPolicy extends BaseRequestPolicy { + /** + * Sends out request. + * + * @param {WebResource} request + * @returns {Promise} + * @memberof CredentialPolicy + */ + public sendRequest(request: WebResource): Promise { + return this._nextPolicy.sendRequest(this.signRequest(request)); + } + + /** + * Child classes must implement this method with request signing. This method + * will be executed in sendRequest(). + * + * @protected + * @abstract + * @param {WebResource} request + * @returns {WebResource} + * @memberof CredentialPolicy + */ + protected signRequest(request: WebResource): WebResource { + // Child classes must override this method with request signing. This method + // will be executed in sendRequest(). + return request; + } +} diff --git a/queue/lib/policies/LoggingPolicy.ts b/queue/lib/policies/LoggingPolicy.ts new file mode 100644 index 0000000..0e4f35d --- /dev/null +++ b/queue/lib/policies/LoggingPolicy.ts @@ -0,0 +1,141 @@ +import { + BaseRequestPolicy, + HttpOperationResponse, + HttpPipelineLogLevel, + RequestPolicy, + RequestPolicyOptions, + WebResource +} from "ms-rest-js"; + +import { IRequestLogOptions } from "../LoggingPolicyFactory"; +import { HTTPURLConnection, URLConstants } from "../utils/constants"; +import { getURLParameter, setURLParameter } from "../utils/utils.common"; + +// Default values of IRetryOptions +const DEFAULT_REQUEST_LOG_OPTIONS: IRequestLogOptions = { + logWarningIfTryOverThreshold: 3000 +}; + +/** + * LoggingPolicy is a policy used to log requests. + * + * @class LoggingPolicy + * @extends {BaseRequestPolicy} + */ +export class LoggingPolicy extends BaseRequestPolicy { + private tryCount: number = 0; + private operationStartTime: Date = new Date(); + private requestStartTime: Date = new Date(); + + private readonly loggingOptions: IRequestLogOptions; + + /** + * Creates an instance of LoggingPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @param {IRequestLogOptions} [loggingOptions=DEFAULT_REQUEST_LOG_OPTIONS] + * @memberof LoggingPolicy + */ + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions, + loggingOptions: IRequestLogOptions = DEFAULT_REQUEST_LOG_OPTIONS + ) { + super(nextPolicy, options); + this.loggingOptions = loggingOptions; + } + + /** + * Sends out request. + * + * @param {WebResource} request + * @returns {Promise} + * @memberof LoggingPolicy + */ + public async sendRequest( + request: WebResource + ): Promise { + this.tryCount++; + this.requestStartTime = new Date(); + if (this.tryCount === 1) { + this.operationStartTime = this.requestStartTime; + } + + let safeURL: string = request.url; + if (getURLParameter(safeURL, URLConstants.Parameters.SIGNATURE)) { + safeURL = setURLParameter( + safeURL, + URLConstants.Parameters.SIGNATURE, + "*****" + ); + } + this.log( + HttpPipelineLogLevel.INFO, + `'${safeURL}'==> OUTGOING REQUEST (Try number=${this.tryCount}).` + ); + + try { + const response = await this._nextPolicy.sendRequest(request); + + const requestEndTime = new Date(); + const requestCompletionTime = + requestEndTime.getTime() - this.requestStartTime.getTime(); + const operationDuration = + requestEndTime.getTime() - this.operationStartTime.getTime(); + + let currentLevel: HttpPipelineLogLevel = HttpPipelineLogLevel.INFO; + let logMessage: string = ""; + if (this.shouldLog(HttpPipelineLogLevel.INFO)) { + // Assume success and default to informational logging. + logMessage = "Successfully Received Response. "; + } + + // If the response took too long, we'll upgrade to warning. + if ( + requestCompletionTime >= + this.loggingOptions.logWarningIfTryOverThreshold + ) { + // Log a warning if the try duration exceeded the specified threshold. + if (this.shouldLog(HttpPipelineLogLevel.WARNING)) { + currentLevel = HttpPipelineLogLevel.WARNING; + logMessage = `SLOW OPERATION. Duration > ${ + this.loggingOptions.logWarningIfTryOverThreshold + } ms. `; + } + } + + if ( + (response.status >= 400 && + response.status <= 499 && + (response.status !== HTTPURLConnection.HTTP_NOT_FOUND && + response.status !== HTTPURLConnection.HTTP_CONFLICT && + response.status !== HTTPURLConnection.HTTP_PRECON_FAILED && + response.status !== + HTTPURLConnection.HTTP_RANGE_NOT_SATISFIABLE)) || + (response.status >= 500 && response.status <= 509) + ) { + const errorString = `REQUEST ERROR: HTTP request failed with status code: ${ + response.status + }. `; + logMessage = errorString; + + currentLevel = HttpPipelineLogLevel.ERROR; + } + + const messageInfo = `Request try:${this.tryCount}, status:${ + response.status + } request duration:${requestCompletionTime} ms, operation duration:${operationDuration} ms\n`; + this.log(currentLevel, logMessage + messageInfo); + + return response; + } catch (err) { + this.log( + HttpPipelineLogLevel.ERROR, + `Unexpected failure attempting to make request. Error message: ${ + err.message + }` + ); + throw err; + } + } +} diff --git a/queue/lib/policies/RetryPolicy.ts b/queue/lib/policies/RetryPolicy.ts new file mode 100644 index 0000000..ef92467 --- /dev/null +++ b/queue/lib/policies/RetryPolicy.ts @@ -0,0 +1,347 @@ +import { + BaseRequestPolicy, + delay, + HttpOperationResponse, + HttpPipelineLogLevel, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions, + RestError, + WebResource +} from "ms-rest-js"; + +import { IRetryOptions } from "../RetryPolicyFactory"; +import { URLConstants } from "../utils/constants"; +import { setURLHost, setURLParameter } from "../utils/utils.common"; + +/** + * A factory method used to generated a RetryPolicy factory. + * + * @export + * @param {IRetryOptions} retryOptions + * @returns + */ +export function NewRetryPolicyFactory( + retryOptions?: IRetryOptions +): RequestPolicyFactory { + return { + create: ( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions + ): RetryPolicy => { + return new RetryPolicy(nextPolicy, options, retryOptions); + } + }; +} + +/** + * RetryPolicy types. + * + * @export + * @enum {number} + */ +export enum RetryPolicyType { + /** + * Exponential retry. Retry time delay grows exponentially. + */ + EXPONENTIAL, + /** + * Linear retry. Retry time delay grows linearly. + */ + FIXED +} + +// Default values of IRetryOptions +const DEFAULT_RETRY_OPTIONS: IRetryOptions = { + maxRetryDelayInMs: 120 * 1000, + maxTries: 4, + retryDelayInMs: 4 * 1000, + retryPolicyType: RetryPolicyType.EXPONENTIAL, + secondaryHost: "", + tryTimeoutInMs: 60 * 1000 +}; + +/** + * Retry policy with exponential retry and linear retry implemented. + * + * @class RetryPolicy + * @extends {BaseRequestPolicy} + */ +export class RetryPolicy extends BaseRequestPolicy { + /** + * RetryOptions. + * + * @private + * @type {IRetryOptions} + * @memberof RetryPolicy + */ + private readonly retryOptions: IRetryOptions; + + /** + * Creates an instance of RetryPolicy. + * + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @param {IRetryOptions} [retryOptions=DEFAULT_RETRY_OPTIONS] + * @memberof RetryPolicy + */ + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions, + retryOptions: IRetryOptions = DEFAULT_RETRY_OPTIONS + ) { + super(nextPolicy, options); + + // Initialize retry options + this.retryOptions = { + retryPolicyType: retryOptions.retryPolicyType + ? retryOptions.retryPolicyType + : DEFAULT_RETRY_OPTIONS.retryPolicyType, + + maxTries: + retryOptions.maxTries && retryOptions.maxTries >= 1 + ? Math.floor(retryOptions.maxTries) + : DEFAULT_RETRY_OPTIONS.maxTries, + + tryTimeoutInMs: + retryOptions.tryTimeoutInMs && retryOptions.tryTimeoutInMs >= 0 + ? retryOptions.tryTimeoutInMs + : DEFAULT_RETRY_OPTIONS.tryTimeoutInMs, + + retryDelayInMs: + retryOptions.retryDelayInMs && retryOptions.retryDelayInMs >= 0 + ? Math.min( + retryOptions.retryDelayInMs, + retryOptions.maxRetryDelayInMs + ? retryOptions.maxRetryDelayInMs + : DEFAULT_RETRY_OPTIONS.maxRetryDelayInMs! + ) + : DEFAULT_RETRY_OPTIONS.retryDelayInMs, + + maxRetryDelayInMs: + retryOptions.maxRetryDelayInMs && retryOptions.maxRetryDelayInMs >= 0 + ? retryOptions.maxRetryDelayInMs + : DEFAULT_RETRY_OPTIONS.maxRetryDelayInMs, + + secondaryHost: retryOptions.secondaryHost + ? retryOptions.secondaryHost + : DEFAULT_RETRY_OPTIONS.secondaryHost + }; + } + + /** + * Sends request. + * + * @param {WebResource} request + * @returns {Promise} + * @memberof RetryPolicy + */ + public async sendRequest( + request: WebResource + ): Promise { + return this.attemptSendRequest(request, false, 1); + } + + /** + * Decide and perform next retry. Won't mutate request parameter. + * + * @protected + * @param {WebResource} request + * @param {HttpOperationResponse} response + * @param {boolean} secondaryHas404 If attempt was against the secondary & it returned a StatusNotFound (404), then + * the resource was not found. This may be due to replication delay. So, in this + * case, we'll never try the secondary again for this operation. + * @param {number} attempt How many retries has been attempted to performed, starting from 1, which includes + * the attempt will be performed by this method call. + * @returns {Promise} + * @memberof RetryPolicy + */ + protected async attemptSendRequest( + request: WebResource, + secondaryHas404: boolean, + attempt: number + ): Promise { + const newRequest: WebResource = request.clone(); + + const isPrimaryRetry = + secondaryHas404 || + !this.retryOptions.secondaryHost || + !( + request.method === "GET" || + request.method === "HEAD" || + request.method === "OPTIONS" + ) || + attempt % 2 === 1; + + if (!isPrimaryRetry) { + newRequest.url = setURLHost( + newRequest.url, + this.retryOptions.secondaryHost! + ); + } + + // Set the server-side timeout query parameter "timeout=[seconds]" + newRequest.url = setURLParameter( + newRequest.url, + URLConstants.Parameters.TIMEOUT, + Math.floor(this.retryOptions.tryTimeoutInMs! / 1000).toString() + ); + + let response: HttpOperationResponse | undefined; + try { + this.logf( + HttpPipelineLogLevel.INFO, + `RetryPolicy: =====> Try=${attempt} ${ + isPrimaryRetry ? "Primary" : "Secondary" + }` + ); + response = await this._nextPolicy.sendRequest(newRequest); + if (!this.shouldRetry(isPrimaryRetry, attempt, response)) { + return response; + } + + secondaryHas404 = + secondaryHas404 || (!isPrimaryRetry && response.status === 404); + } catch (err) { + this.logf( + HttpPipelineLogLevel.ERROR, + `RetryPolicy: Caught error, message: ${err.message}, code: ${err.code}` + ); + if (!this.shouldRetry(isPrimaryRetry, attempt, response, err)) { + throw err; + } + } + + await this.delay(isPrimaryRetry, attempt); + return await this.attemptSendRequest(request, secondaryHas404, ++attempt); + } + + /** + * Decide whether to retry according to last HTTP response and retry counters. + * + * @protected + * @param {boolean} isPrimaryRetry + * @param {number} attempt + * @param {HttpOperationResponse} [response] + * @param {RestError} [err] + * @returns {boolean} + * @memberof RetryPolicy + */ + protected shouldRetry( + isPrimaryRetry: boolean, + attempt: number, + response?: HttpOperationResponse, + err?: RestError + ): boolean { + if (attempt >= this.retryOptions.maxTries!) { + this.logf( + HttpPipelineLogLevel.INFO, + `RetryPolicy: Attempt(s) ${attempt} >= maxTries ${this.retryOptions + .maxTries!}, no further try.` + ); + return false; + } + + // Handle network failures, you may need to customize the list when you implement + // your own http client + const retriableErrors = [ + "ETIMEDOUT", + "ESOCKETTIMEDOUT", + "ECONNREFUSED", + "ECONNRESET", + "ENOENT", + "ENOTFOUND", + "TIMEOUT", + "REQUEST_SEND_ERROR" // For default xhr based http client provided in ms-rest-js + ]; + if (err) { + for (const retriableError of retriableErrors) { + if ( + err.name.toUpperCase().includes(retriableError) || + err.message.toUpperCase().includes(retriableError) || + (err.code && err.code.toUpperCase().includes(retriableError)) + ) { + this.logf( + HttpPipelineLogLevel.INFO, + `RetryPolicy: Network error ${retriableError} found, will retry.` + ); + return true; + } + } + } + + // If attempt was against the secondary & it returned a StatusNotFound (404), then + // the resource was not found. This may be due to replication delay. So, in this + // case, we'll never try the secondary again for this operation. + if (response || err) { + const statusCode = response ? response.status : err ? err.statusCode : 0; + if (!isPrimaryRetry && statusCode === 404) { + this.logf( + HttpPipelineLogLevel.INFO, + `RetryPolicy: Secondary access with 404, will retry.` + ); + return true; + } + + // Server internal error or server timeout + if (statusCode === 503 || statusCode === 500) { + this.logf( + HttpPipelineLogLevel.INFO, + `RetryPolicy: Will retry for status code ${statusCode}.` + ); + return true; + } + } + + return false; + } + + /** + * This is to log for debugging purposes only. + * Comment/uncomment as necessary for releasing/debugging. + * + * @private + * @param {HttpPipelineLogLevel} level + * @param {string} message + * @memberof RetryPolicy + */ + // tslint:disable-next-line:variable-name + private logf(_level: HttpPipelineLogLevel, _message: string) { + // this.log(_level, _message); + } + + /** + * Delay a calculated time between retries. + * + * @private + * @param {boolean} isPrimaryRetry + * @param {number} attempt + * @returns + * @memberof RetryPolicy + */ + private async delay(isPrimaryRetry: boolean, attempt: number) { + let delayTimeInMs: number = 0; + + if (isPrimaryRetry) { + switch (this.retryOptions.retryPolicyType) { + case RetryPolicyType.EXPONENTIAL: + delayTimeInMs = Math.min( + (Math.pow(2, attempt - 1) - 1) * this.retryOptions.retryDelayInMs!, + this.retryOptions.maxRetryDelayInMs! + ); + break; + case RetryPolicyType.FIXED: + delayTimeInMs = this.retryOptions.retryDelayInMs!; + break; + } + } else { + delayTimeInMs = Math.random() * 1000; + } + + this.logf( + HttpPipelineLogLevel.INFO, + `RetryPolicy: Delay for ${delayTimeInMs}ms` + ); + return delay(delayTimeInMs); + } +} diff --git a/queue/lib/policies/SharedKeyCredentialPolicy.ts b/queue/lib/policies/SharedKeyCredentialPolicy.ts new file mode 100644 index 0000000..c8ef48f --- /dev/null +++ b/queue/lib/policies/SharedKeyCredentialPolicy.ts @@ -0,0 +1,206 @@ +import { RequestPolicy, RequestPolicyOptions, WebResource } from "ms-rest-js"; +import { SharedKeyCredential } from "../credentials/SharedKeyCredential"; +import { HeaderConstants } from "../utils/constants"; +import { getURLPath, getURLQueries } from "../utils/utils.common"; +import { CredentialPolicy } from "./CredentialPolicy"; + +/** + * SharedKeyCredentialPolicy is a policy used to sign HTTP request with a shared key. + * + * @export + * @class SharedKeyCredentialPolicy + * @extends {CredentialPolicy} + */ +export class SharedKeyCredentialPolicy extends CredentialPolicy { + /** + * Reference to SharedKeyCredential which generates SharedKeyCredentialPolicy + * + * @type {SharedKeyCredential} + * @memberof SharedKeyCredentialPolicy + */ + private readonly factory: SharedKeyCredential; + + /** + * Creates an instance of SharedKeyCredentialPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @param {SharedKeyCredential} factory + * @memberof SharedKeyCredentialPolicy + */ + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions, + factory: SharedKeyCredential + ) { + super(nextPolicy, options); + this.factory = factory; + } + + /** + * Signs request. + * + * @protected + * @param {WebResource} request + * @returns {WebResource} + * @memberof SharedKeyCredentialPolicy + */ + protected signRequest(request: WebResource): WebResource { + request.headers.set(HeaderConstants.X_MS_DATE, new Date().toUTCString()); + + if ( + request.body && + typeof request.body === "string" && + request.body.length > 0 + ) { + request.headers.set(HeaderConstants.CONTENT_LENGTH, request.body.length); + } + + const stringToSign: string = + [ + request.method.toUpperCase(), + this.getHeaderValueToSign(request, HeaderConstants.CONTENT_LANGUAGE), + this.getHeaderValueToSign(request, HeaderConstants.CONTENT_ENCODING), + this.getHeaderValueToSign(request, HeaderConstants.CONTENT_LENGTH), + this.getHeaderValueToSign(request, HeaderConstants.CONTENT_MD5), + this.getHeaderValueToSign(request, HeaderConstants.CONTENT_TYPE), + this.getHeaderValueToSign(request, HeaderConstants.DATE), + this.getHeaderValueToSign(request, HeaderConstants.IF_MODIFIED_SINCE), + this.getHeaderValueToSign(request, HeaderConstants.IF_MATCH), + this.getHeaderValueToSign(request, HeaderConstants.IF_NONE_MATCH), + this.getHeaderValueToSign(request, HeaderConstants.IF_UNMODIFIED_SINCE), + this.getHeaderValueToSign(request, HeaderConstants.RANGE) + ].join("\n") + + "\n" + + this.getCanonicalizedHeadersString(request) + + this.getCanonicalizedResourceString(request); + + const signature: string = this.factory.computeHMACSHA256(stringToSign); + request.headers.set( + HeaderConstants.AUTHORIZATION, + `SharedKey ${this.factory.accountName}:${signature}` + ); + + // console.log(`[URL]:${request.url}`); + // console.log(`[HEADERS]:${request.headers.toString()}`); + // console.log(`[STRING TO SIGN]:${JSON.stringify(stringToSign)}`); + // console.log(`[KEY]: ${request.headers.get(HeaderConstants.AUTHORIZATION)}`); + return request; + } + + /** + * Retrieve header value according to shared key sign rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + * + * @private + * @param {WebResource} request + * @param {string} headerName + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getHeaderValueToSign( + request: WebResource, + headerName: string + ): string { + const value = request.headers.get(headerName); + + if (!value) { + return ""; + } + + // When using version 2015-02-21 or later, if Content-Length is zero, then + // set the Content-Length part of the StringToSign to an empty string. + // https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + if (headerName === HeaderConstants.CONTENT_LENGTH && value === "0") { + return ""; + } + + return value; + } + + /** + * To construct the CanonicalizedHeaders portion of the signature string, follow these steps: + * 1. Retrieve all headers for the resource that begin with x-ms-, including the x-ms-date header. + * 2. Convert each HTTP header name to lowercase. + * 3. Sort the headers lexicographically by header name, in ascending order. + * Each header may appear only once in the string. + * 4. Replace any linear whitespace in the header value with a single space. + * 5. Trim any whitespace around the colon in the header. + * 6. Finally, append a new-line character to each canonicalized header in the resulting list. + * Construct the CanonicalizedHeaders string by concatenating all headers in this list into a single string. + * + * @private + * @param {WebResource} request + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getCanonicalizedHeadersString(request: WebResource): string { + let headersArray = request.headers.headersArray().filter(value => { + return value.name + .toLowerCase() + .startsWith(HeaderConstants.PREFIX_FOR_STORAGE); + }); + + headersArray.sort( + (a, b): number => { + return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); + } + ); + + // Remove duplicate headers + headersArray = headersArray.filter((value, index, array) => { + if ( + index > 0 && + value.name.toLowerCase() === array[index - 1].name.toLowerCase() + ) { + return false; + } + return true; + }); + + let canonicalizedHeadersStringToSign: string = ""; + headersArray.forEach(header => { + canonicalizedHeadersStringToSign += `${header.name + .toLowerCase() + .trimRight()}:${header.value.trimLeft()}\n`; + }); + + return canonicalizedHeadersStringToSign; + } + + /** + * Retrieves the webResource canonicalized resource string. + * + * @private + * @param {WebResource} request + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getCanonicalizedResourceString(request: WebResource): string { + const path = encodeURI(getURLPath(request.url) || "/"); + + let canonicalizedResourceString: string = ""; + canonicalizedResourceString += `/${this.factory.accountName}${path}`; + + const queries = getURLQueries(request.url); + const lowercaseQueries: { [key: string]: string } = {}; + if (queries) { + const queryKeys: string[] = []; + for (const key in queries) { + if (queries.hasOwnProperty(key)) { + const lowercaseKey = key.toLowerCase(); + lowercaseQueries[lowercaseKey] = queries[key]; + queryKeys.push(lowercaseKey); + } + } + + queryKeys.sort(); + for (const key of queryKeys) { + canonicalizedResourceString += `\n${key}:${decodeURIComponent( + lowercaseQueries[key] + )}`; + } + } + + return canonicalizedResourceString; + } +} diff --git a/queue/lib/policies/TelemetryPolicy.ts b/queue/lib/policies/TelemetryPolicy.ts new file mode 100644 index 0000000..a4b1c77 --- /dev/null +++ b/queue/lib/policies/TelemetryPolicy.ts @@ -0,0 +1,65 @@ +import { + BaseRequestPolicy, + HttpHeaders, + HttpOperationResponse, + isNode, + RequestPolicy, + RequestPolicyOptions, + WebResource +} from "ms-rest-js"; + +import { HeaderConstants } from "../utils/constants"; + +/** + * TelemetryPolicy is a policy used to tag user-agent header for every requests. + * + * @class TelemetryPolicy + * @extends {BaseRequestPolicy} + */ +export class TelemetryPolicy extends BaseRequestPolicy { + /** + * Telemetry string. + * + * @type {string} + * @memberof TelemetryPolicy + */ + public readonly telemetry: string; + + /** + * Creates an instance of TelemetryPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @param {ITelemetryOptions} [telemetry] + * @memberof TelemetryPolicy + */ + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions, + telemetry: string + ) { + super(nextPolicy, options); + this.telemetry = telemetry; + } + + /** + * Sends out request. + * + * @param {WebResource} request + * @returns {Promise} + * @memberof TelemetryPolicy + */ + public async sendRequest( + request: WebResource + ): Promise { + if (isNode) { + if (!request.headers) { + request.headers = new HttpHeaders(); + } + if (!request.headers.get(HeaderConstants.USER_AGENT)) { + request.headers.set(HeaderConstants.USER_AGENT, this.telemetry); + } + } + + return this._nextPolicy.sendRequest(request); + } +} diff --git a/queue/lib/policies/TokenCredentialPolicy.ts b/queue/lib/policies/TokenCredentialPolicy.ts new file mode 100644 index 0000000..25c1153 --- /dev/null +++ b/queue/lib/policies/TokenCredentialPolicy.ts @@ -0,0 +1,72 @@ +import { + HttpHeaders, + RequestPolicy, + RequestPolicyOptions, + WebResource +} from "ms-rest-js"; + +import { TokenCredential } from "../credentials/TokenCredential"; +import { HeaderConstants } from "../utils/constants"; +import { CredentialPolicy } from "./CredentialPolicy"; + +/** + * TokenCredentialPolicy is a policy used to sign HTTP request with a token. + * Such as an OAuth bearer token. + * + * @export + * @class TokenCredentialPolicy + * @extends {CredentialPolicy} + */ +export class TokenCredentialPolicy extends CredentialPolicy { + /** + * The value of token. + * + * @type {TokenCredential} + * @memberof TokenCredentialPolicy + */ + public readonly tokenCredential: TokenCredential; + + /** + * Token authorization scheme, default header is "Bearer". + * + * @type {string} + * @memberof TokenCredentialPolicy + */ + public readonly authorizationScheme: string; + + /** + * Creates an instance of TokenCredentialPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @param {TokenCredential} tokenCredential + * @memberof TokenCredentialPolicy + */ + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptions, + tokenCredential: TokenCredential + ) { + super(nextPolicy, options); + this.tokenCredential = tokenCredential; + this.authorizationScheme = HeaderConstants.AUTHORIZATION_SCHEME; + } + + /** + * Sign request with token. + * + * @protected + * @param {WebResource} request + * @returns {WebResource} + * @memberof TokenCredentialPolicy + */ + protected signRequest(request: WebResource): WebResource { + if (!request.headers) { + request.headers = new HttpHeaders(); + } + request.headers.set( + HeaderConstants.AUTHORIZATION, + `${this.authorizationScheme} ${this.tokenCredential.token}` + ); + return request; + } +} diff --git a/queue/lib/policies/UniqueRequestIDPolicy.ts b/queue/lib/policies/UniqueRequestIDPolicy.ts new file mode 100644 index 0000000..1c6f049 --- /dev/null +++ b/queue/lib/policies/UniqueRequestIDPolicy.ts @@ -0,0 +1,48 @@ +import { + BaseRequestPolicy, + generateUuid, + HttpOperationResponse, + RequestPolicy, + RequestPolicyOptions, + WebResource +} from "ms-rest-js"; + +import { HeaderConstants } from "../utils/constants"; + +/** + * UniqueRequestIDPolicy generates an UUID as x-ms-request-id header value. + * + * @class UniqueRequestIDPolicy + * @extends {BaseRequestPolicy} + */ +export class UniqueRequestIDPolicy extends BaseRequestPolicy { + /** + * Creates an instance of UniqueRequestIDPolicy. + * @param {RequestPolicy} nextPolicy + * @param {RequestPolicyOptions} options + * @memberof UniqueRequestIDPolicy + */ + constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions) { + super(nextPolicy, options); + } + + /** + * Sends request. + * + * @param {WebResource} request + * @returns {Promise} + * @memberof UniqueRequestIDPolicy + */ + public async sendRequest( + request: WebResource + ): Promise { + if (!request.headers.contains(HeaderConstants.X_MS_CLIENT_REQUEST_ID)) { + request.headers.set( + HeaderConstants.X_MS_CLIENT_REQUEST_ID, + generateUuid() + ); + } + + return this._nextPolicy.sendRequest(request); + } +} diff --git a/queue/lib/utils/constants.ts b/queue/lib/utils/constants.ts new file mode 100644 index 0000000..d86f330 --- /dev/null +++ b/queue/lib/utils/constants.ts @@ -0,0 +1,41 @@ +export const SDK_VERSION: string = "10.0.0-preview"; +export const SERVICE_VERSION: string = "2018-03-28"; + +export const URLConstants = { + Parameters: { + FORCE_BROWSER_NO_CACHE: "_", + SIGNATURE: "sig", + TIMEOUT: "timeout" + } +}; + +export const HTTPURLConnection = { + HTTP_CONFLICT: 409, + HTTP_NOT_FOUND: 404, + HTTP_PRECON_FAILED: 412, + HTTP_RANGE_NOT_SATISFIABLE: 416 +}; + +export const HeaderConstants = { + AUTHORIZATION: "authorization", + AUTHORIZATION_SCHEME: "Bearer", + CONTENT_ENCODING: "content-encoding", + CONTENT_LANGUAGE: "content-language", + CONTENT_LENGTH: "content-length", + CONTENT_MD5: "content-md5", + CONTENT_TYPE: "content-type", + COOKIE: "Cookie", + DATE: "date", + IF_MATCH: "if-match", + IF_MODIFIED_SINCE: "if-modified-since", + IF_NONE_MATCH: "if-none-match", + IF_UNMODIFIED_SINCE: "if-unmodified-since", + PREFIX_FOR_STORAGE: "x-ms-", + RANGE: "Range", + USER_AGENT: "User-Agent", + X_MS_CLIENT_REQUEST_ID: "x-ms-client-request-id", + X_MS_DATE: "x-ms-date" +}; + +export const ETagNone = ""; +export const ETagAny = "*"; diff --git a/queue/lib/utils/utils.common.ts b/queue/lib/utils/utils.common.ts new file mode 100644 index 0000000..c316ee3 --- /dev/null +++ b/queue/lib/utils/utils.common.ts @@ -0,0 +1,177 @@ +import { URLBuilder } from "ms-rest-js"; + +/** + * Append a string to URL path. Will remove duplicated "/" in front of the string + * when URL path ends with a "/". + * + * @export + * @param {string} url Source URL string + * @param {string} name String to be appended to URL + * @returns {string} An updated URL string + */ +export function appendToURLPath(url: string, name: string): string { + const urlParsed = URLBuilder.parse(url); + + let path = urlParsed.getPath(); + path = path + ? path.endsWith("/") + ? `${path}${name}` + : `${path}/${name}` + : name; + urlParsed.setPath(path); + + return urlParsed.toString(); +} + +/** + * Set URL parameter name and value. If name exists in URL parameters, old value + * will be replaced by name key. If not provide value, the parameter will be deleted. + * + * @export + * @param {string} url Source URL string + * @param {string} name Parameter name + * @param {string} [value] Parameter value + * @returns {string} An updated URL string + */ +export function setURLParameter( + url: string, + name: string, + value?: string +): string { + const urlParsed = URLBuilder.parse(url); + urlParsed.setQueryParameter(name, value); + return urlParsed.toString(); +} + +/** + * Get URL parameter by name. + * + * @export + * @param {string} url + * @param {string} name + * @returns {(string | string[] | undefined)} + */ +export function getURLParameter( + url: string, + name: string +): string | string[] | undefined { + const urlParsed = URLBuilder.parse(url); + return urlParsed.getQueryParameterValue(name); +} + +/** + * Set URL host. + * + * @export + * @param {string} url Source URL string + * @param {string} host New host string + * @returns An updated URL string + */ +export function setURLHost(url: string, host: string): string { + const urlParsed = URLBuilder.parse(url); + urlParsed.setHost(host); + return urlParsed.toString(); +} + +/** + * Get URL path from an URL string. + * + * @export + * @param {string} url Source URL string + * @returns {(string | undefined)} + */ +export function getURLPath(url: string): string | undefined { + const urlParsed = URLBuilder.parse(url); + return urlParsed.getPath(); +} + +/** + * Get URL query key value pairs from an URL string. + * + * @export + * @param {string} url + * @returns {{[key: string]: string}} + */ +export function getURLQueries(url: string): { [key: string]: string } { + let queryString = URLBuilder.parse(url).getQuery(); + if (!queryString) { + return {}; + } + + queryString = queryString.trim(); + queryString = queryString.startsWith("?") + ? queryString.substr(1) + : queryString; + + let querySubStrings: string[] = queryString.split("&"); + querySubStrings = querySubStrings.filter((value: string) => { + const indexOfEqual = value.indexOf("="); + const lastIndexOfEqual = value.lastIndexOf("="); + return ( + indexOfEqual > 0 && + indexOfEqual === lastIndexOfEqual && + lastIndexOfEqual < value.length - 1 + ); + }); + + const queries: { [key: string]: string } = {}; + for (const querySubString of querySubStrings) { + const splitResults = querySubString.split("="); + const key: string = splitResults[0]; + const value: string = splitResults[1]; + queries[key] = value; + } + + return queries; +} + +/** + * Rounds a date off to seconds. + * + * @export + * @param {Date} date + * @param {boolean} [withMilliseconds=true] If true, YYYY-MM-DDThh:mm:ss.fffffffZ will be returned; + * If false, YYYY-MM-DDThh:mm:ssZ will be returned. + * @returns {string} Date string in ISO8061 format, with or without 7 milliseconds component + */ +export function truncatedISO8061Date( + date: Date, + withMilliseconds: boolean = true +): string { + // Date.toISOString() will return like "2018-10-29T06:34:36.139Z" + const dateString = date.toISOString(); + + return withMilliseconds + ? dateString.substring(0, dateString.length - 1) + "0000" + "Z" + : dateString.substring(0, dateString.length - 5) + "Z"; +} + +/** + * String.prototype.padStart() + * + * @export + * @param {string} currentString + * @param {number} targetLength + * @param {string} [padString=" "] + * @returns {string} + */ +export function padStart( + currentString: string, + targetLength: number, + padString: string = " " +): string { + if (String.prototype.padStart) { + return currentString.padStart(targetLength, padString); + } + + padString = padString || " "; + if (currentString.length > targetLength) { + return currentString; + } else { + targetLength = targetLength - currentString.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); + } + return padString.slice(0, targetLength) + currentString; + } +} diff --git a/queue/package-lock.json b/queue/package-lock.json new file mode 100644 index 0000000..ab500d1 --- /dev/null +++ b/queue/package-lock.json @@ -0,0 +1,5716 @@ +{ + "name": "@azure/storage-queue", + "version": "10.0.0-preview", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "4.0.0" + } + }, + "@types/body-parser": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", + "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", + "requires": { + "@types/connect": "3.4.32", + "@types/node": "10.12.12" + } + }, + "@types/connect": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", + "requires": { + "@types/node": "10.12.12" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/events": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/express": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", + "integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==", + "requires": { + "@types/body-parser": "1.17.0", + "@types/express-serve-static-core": "4.16.0", + "@types/serve-static": "1.13.2" + } + }, + "@types/express-serve-static-core": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz", + "integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==", + "requires": { + "@types/events": "1.2.0", + "@types/node": "10.12.12", + "@types/range-parser": "1.2.2" + } + }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "requires": { + "@types/node": "10.12.12" + } + }, + "@types/mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", + "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" + }, + "@types/mocha": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", + "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", + "dev": true + }, + "@types/node": { + "version": "10.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.12.tgz", + "integrity": "sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A==" + }, + "@types/range-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", + "integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==" + }, + "@types/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", + "requires": { + "@types/express-serve-static-core": "4.16.0", + "@types/mime": "2.0.0" + } + }, + "@types/uuid": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", + "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==", + "requires": { + "@types/node": "10.12.12" + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "2.1.21", + "negotiator": "0.6.1" + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.3" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "1.0.1" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "1.1.0", + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "1.0.0", + "get-value": "2.0.6", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-array-reduce": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/async-array-reduce/-/async-array-reduce-0.2.1.tgz", + "integrity": "sha1-yL4BCitc0A3qlsgRFgNGk9/dgtE=", + "dev": true + }, + "async-done": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", + "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0", + "process-nextick-args": "1.0.7", + "stream-exhaust": "1.0.2" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "1.3.1" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "axios": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "1.1.6" + } + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "1.1.2", + "arr-flatten": "1.1.0", + "arr-map": "2.0.2", + "array-each": "1.0.1", + "array-initial": "1.1.0", + "array-last": "1.3.0", + "async-done": "1.3.1", + "async-settle": "1.0.0", + "now-and-later": "2.0.0" + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.1", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.1.0" + } + }, + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "2.0.1", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "2.0.2", + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "4.17.11" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "1.3.2", + "is-plain-object": "2.0.4" + } + }, + "core-js": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.0.tgz", + "integrity": "sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.46" + } + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.2", + "void-elements": "2.0.1" + } + }, + "duplexify": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.1", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0" + } + }, + "edge-launcher": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/edge-launcher/-/edge-launcher-1.2.2.tgz", + "integrity": "sha1-60Cq+9Bnpup27/+rBke81VCbN7I=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "1.3.5", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "3.1.0", + "engine.io-parser": "2.1.3", + "ws": "3.3.3" + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "3.1.0", + "engine.io-parser": "2.1.3", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", + "yeast": "0.1.2" + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "1.0.3" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.46", + "es6-symbol": "3.1.1" + } + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.46" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.46", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz", + "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "0.2.3", + "array-unique": "0.2.1", + "braces": "0.1.5" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "0.1.1", + "repeat-string": "0.2.2" + }, + "dependencies": { + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "parse-node-version": "1.0.0", + "time-stamp": "1.1.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" + } + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "2.0.1", + "readable-stream": "2.3.6" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.21" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "1.0.0" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "through2": "2.0.5" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.11.1", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "3.0.2", + "glob": "7.1.3", + "glob-parent": "3.1.0", + "is-negated-glob": "1.0.0", + "ordered-read-streams": "1.0.1", + "pumpify": "1.5.1", + "readable-stream": "2.3.6", + "remove-trailing-separator": "1.1.0", + "to-absolute-glob": "2.0.2", + "unique-stream": "2.2.1" + } + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-done": "1.3.1", + "chokidar": "2.0.4", + "is-negated-glob": "1.0.0", + "just-debounce": "1.0.0", + "object.defaults": "1.1.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "gulp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", + "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", + "dev": true, + "requires": { + "glob-watcher": "5.0.3", + "gulp-cli": "2.0.1", + "undertaker": "1.2.0", + "vinyl-fs": "3.0.3" + }, + "dependencies": { + "gulp-cli": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", + "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "archy": "1.0.0", + "array-sort": "1.0.0", + "color-support": "1.1.3", + "concat-stream": "1.6.2", + "copy-props": "2.0.4", + "fancy-log": "1.3.3", + "gulplog": "1.0.0", + "interpret": "1.1.0", + "isobject": "3.0.1", + "liftoff": "2.5.0", + "matchdep": "2.0.0", + "mute-stdout": "1.0.1", + "pretty-hrtime": "1.0.3", + "replace-homedir": "1.0.0", + "semver-greatest-satisfied-range": "1.1.0", + "v8flags": "3.1.1", + "yargs": "7.1.0" + } + } + } + }, + "gulp-zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-4.2.0.tgz", + "integrity": "sha512-I+697f6jf+PncdTrqfuwoauxgnLG1yHRg3vlmvDgmJuEnlEHy4meBktJ/oHgfyg4tp6X25wuZqUOraVeVg97wQ==", + "dev": true, + "requires": { + "get-stream": "3.0.0", + "plugin-error": "0.1.2", + "through2": "2.0.5", + "vinyl": "2.2.0", + "yazl": "2.5.1" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-0.1.1.tgz", + "integrity": "sha1-omHEwqbGZ+DHe3AKfyl8Oe86pYk=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "3.1.0", + "follow-redirects": "1.5.10", + "requires-port": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.12.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", + "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", + "dev": true, + "requires": { + "merge-stream": "1.0.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "karma": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.3.tgz", + "integrity": "sha512-JU4FYUtFEGsLZd6ZJzLrivcPj0TkteBiIRDcXWFsltPMGgZMDtby/MIzNOzgyZv/9dahs9vHpSxerC/ZfeX9Qw==", + "dev": true, + "requires": { + "bluebird": "3.5.3", + "body-parser": "1.18.3", + "chokidar": "2.0.4", + "colors": "1.3.2", + "combine-lists": "1.0.1", + "connect": "3.6.6", + "core-js": "2.6.0", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "flatted": "2.0.0", + "glob": "7.1.3", + "graceful-fs": "4.1.15", + "http-proxy": "1.17.0", + "isbinaryfile": "3.0.3", + "lodash": "4.17.11", + "log4js": "3.0.6", + "mime": "2.4.0", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.2.0", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "socket.io": "2.1.1", + "source-map": "0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "1.0.1", + "which": "1.3.1" + } + }, + "karma-edge-launcher": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/karma-edge-launcher/-/karma-edge-launcher-0.4.2.tgz", + "integrity": "sha512-YAJZb1fmRcxNhMIWYsjLuxwODBjh2cSHgTW/jkVmdpGguJjLbs9ZgIK/tEJsMQcBLUkO+yO4LBbqYxqgGW2HIw==", + "dev": true, + "requires": { + "edge-launcher": "1.2.2" + } + }, + "karma-env-preprocessor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/karma-env-preprocessor/-/karma-env-preprocessor-0.1.1.tgz", + "integrity": "sha1-u+jIfVnADtt2BwvTwxtLOdXcfhU=", + "dev": true + }, + "karma-firefox-launcher": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", + "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "dev": true + }, + "karma-ie-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", + "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", + "dev": true, + "requires": { + "lodash": "4.17.11" + } + }, + "karma-mocha": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "karma-mocha-reporter": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", + "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", + "dev": true, + "requires": { + "chalk": "2.4.1", + "log-symbols": "2.2.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "2.0.0", + "es6-weak-map": "2.0.2" + } + }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "dev": true, + "requires": { + "set-getter": "0.1.0" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "1.0.3" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "3.0.2", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.8.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "2.4.1" + } + }, + "log4js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "dev": true, + "requires": { + "circular-json": "0.5.9", + "date-format": "1.2.0", + "debug": "3.1.0", + "rfdc": "1.1.2", + "streamroller": "0.7.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "magic-string": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", + "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", + "dev": true, + "requires": { + "sourcemap-codec": "1.4.4" + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "2.0.0", + "micromatch": "3.1.10", + "resolve": "1.8.1", + "stack-trace": "0.0.10" + } + }, + "matched": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/matched/-/matched-0.4.4.tgz", + "integrity": "sha1-Vte36xgDPwz5vFLrIJD6x9weifo=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "async-array-reduce": "0.2.1", + "extend-shallow": "2.0.1", + "fs-exists-sync": "0.1.0", + "glob": "7.1.3", + "has-glob": "0.1.1", + "is-valid-glob": "0.3.0", + "lazy-cache": "2.0.2", + "resolve-dir": "0.1.1" + }, + "dependencies": { + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "0.2.0", + "which": "1.3.1" + } + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + } + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "dev": true + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "1.37.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "ms-rest-js": { + "version": "0.22.425", + "resolved": "https://registry.npmjs.org/ms-rest-js/-/ms-rest-js-0.22.425.tgz", + "integrity": "sha512-PM9l0Si+T3kFxce8hwB/LlCxPJSHwSlFUSpjdJHzPvF+2w8lw7huE/FCPnRfdaUm7IikQESkJhydnbqX6g2OuQ==", + "requires": { + "@types/express": "4.16.0", + "@types/form-data": "2.2.1", + "@types/node": "9.6.40", + "@types/uuid": "3.4.4", + "axios": "0.18.0", + "form-data": "2.3.3", + "tough-cookie": "2.5.0", + "tslib": "1.9.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "@types/node": { + "version": "9.6.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.40.tgz", + "integrity": "sha512-M3HHoXXndsho/sTbQML2BJr7/uwNhMg8P0D4lb+UsM65JQZx268faiz9hKpY4FpocWqpwlLwa8vevw8hLtKjOw==" + } + } + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.6.0", + "validate-npm-package-license": "3.0.4" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.12" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "opn": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.2" + } + }, + "parse-node-version": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", + "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "3.6.1", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.8.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "is-utf8": "0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "3.0.0", + "safe-buffer": "5.1.2", + "through2": "2.0.5" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "is-absolute": "1.0.0", + "remove-trailing-separator": "1.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.3" + } + }, + "rollup": { + "version": "0.65.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.65.2.tgz", + "integrity": "sha512-BbXOrpxVbx0MpElI6vVLR2B6vnWHvYU/QAMw3GcEXvs601bvgrozuaW30cnvt43B96a6DeoYA0i9T5THanN+Rw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "@types/node": "10.12.12" + } + }, + "rollup-plugin-commonjs": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz", + "integrity": "sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA==", + "dev": true, + "requires": { + "estree-walker": "0.5.2", + "magic-string": "0.25.1", + "resolve": "1.8.1", + "rollup-pluginutils": "2.3.3" + } + }, + "rollup-plugin-multi-entry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-multi-entry/-/rollup-plugin-multi-entry-2.0.2.tgz", + "integrity": "sha512-TY72fCVJvcEAQBpBzkXykoYQx2fz0B20EVtcbh0WZaYr5eBu3U1dRPzgMt6aO8MePWWOdcmgoBtG6PhmYJr4Ew==", + "dev": true, + "requires": { + "matched": "0.4.4" + } + }, + "rollup-plugin-node-resolve": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz", + "integrity": "sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg==", + "dev": true, + "requires": { + "builtin-modules": "2.0.0", + "is-module": "1.0.0", + "resolve": "1.8.1" + }, + "dependencies": { + "builtin-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-2.0.0.tgz", + "integrity": "sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg==", + "dev": true + } + } + }, + "rollup-plugin-replace": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.1.0.tgz", + "integrity": "sha512-SxrAIgpH/B5/W4SeULgreOemxcpEgKs2gcD42zXw50bhqGWmcnlXneVInQpAqzA/cIly4bJrOpeelmB9p4YXSQ==", + "dev": true, + "requires": { + "magic-string": "0.25.1", + "minimatch": "3.0.4", + "rollup-pluginutils": "2.3.3" + } + }, + "rollup-plugin-shim": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-shim/-/rollup-plugin-shim-1.0.0.tgz", + "integrity": "sha512-rZqFD43y4U9nSqVq3iyWBiDwmBQJY8Txi04yI9jTKD3xcl7CbFjh1qRpQshUB3sONLubDzm7vJiwB+1MEGv67w==", + "dev": true + }, + "rollup-plugin-uglify": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-5.0.2.tgz", + "integrity": "sha512-CRRyMgKjTwTx1GXnn+v1VYV+6De5NyPB1UBStsQIQ+asrxvP7dK43cg2pf1vyFNr/NIHGvfYAR9Yo4j+5ZMQsw==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0", + "jest-worker": "23.2.0", + "uglify-js": "3.4.9" + } + }, + "rollup-plugin-visualizer": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-0.9.2.tgz", + "integrity": "sha512-EHXHLp9Q8v5QdRTSjgio4Alr2MKxCJroLhJunmcH+pWAM5869nI5mdWjk2jp64rjxzEahrMYmfF/G5sbTHIhKw==", + "dev": true, + "requires": { + "mkdirp": "0.5.1", + "opn": "5.4.0", + "source-map": "0.7.3", + "typeface-oswald": "0.0.54" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "rollup-pluginutils": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz", + "integrity": "sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA==", + "dev": true, + "requires": { + "estree-walker": "0.5.2", + "micromatch": "2.3.11" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.4" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.1", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "1.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "dev": true, + "requires": { + "to-object-path": "0.3.0" + } + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "3.1.0", + "engine.io": "3.2.1", + "has-binary2": "1.0.3", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.1.1", + "socket.io-parser": "3.2.0" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "3.1.0", + "engine.io-client": "3.2.1", + "has-binary2": "1.0.3", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "3.2.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "1.1.1", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz", + "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.2" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.2" + } + }, + "spdx-license-ids": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.6" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.5", + "xtend": "4.0.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "is-negated-glob": "1.0.0" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "2.0.5" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "1.1.29", + "punycode": "2.1.1" + } + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "buffer-from": "1.1.1", + "diff": "3.5.0", + "make-error": "1.3.5", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.5.9", + "yn": "2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.21" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typeface-oswald": { + "version": "0.0.54", + "resolved": "https://registry.npmjs.org/typeface-oswald/-/typeface-oswald-0.0.54.tgz", + "integrity": "sha512-U1WMNp4qfy4/3khIfHMVAIKnNu941MXUfs3+H9R8PFgnoz42Hh9pboSFztWr86zut0eXC8byalmVhfkiKON/8Q==", + "dev": true + }, + "typescript": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.1.tgz", + "integrity": "sha512-jw7P2z/h6aPT4AENXDGjcfHTu5CSqzsbZc6YlUIebTyBAq8XaKp78x7VcSh30xwSCcsu5irZkYZUSFP1MrAMbg==", + "dev": true + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "requires": { + "commander": "2.17.1", + "source-map": "0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undertaker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", + "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "arr-map": "2.0.2", + "bach": "1.2.0", + "collection-map": "1.0.0", + "es6-weak-map": "2.0.2", + "last-run": "1.1.1", + "object.defaults": "1.1.0", + "object.reduce": "1.0.1", + "undertaker-registry": "1.0.1" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.5", + "tmp": "0.0.33" + } + }, + "util": { + "version": "0.10.3", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "v8flags": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", + "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "3.0.2", + "spdx-expression-parse": "3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "1.0.0", + "glob-stream": "6.1.0", + "graceful-fs": "4.1.15", + "is-valid-glob": "1.0.0", + "lazystream": "1.0.0", + "lead": "1.0.0", + "object.assign": "4.1.0", + "pumpify": "1.5.1", + "readable-stream": "2.3.6", + "remove-bom-buffer": "3.0.0", + "remove-bom-stream": "1.2.0", + "resolve-options": "1.1.0", + "through2": "2.0.5", + "to-through": "2.0.0", + "value-or-function": "3.0.0", + "vinyl": "2.2.0", + "vinyl-sourcemap": "1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "1.0.2", + "convert-source-map": "1.6.0", + "graceful-fs": "4.1.15", + "normalize-path": "2.1.1", + "now-and-later": "2.0.0", + "remove-bom-buffer": "3.0.0", + "vinyl": "2.2.0" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": "1.2.4", + "xmlbuilder": "9.0.7" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + } + } +} diff --git a/queue/package.json b/queue/package.json new file mode 100644 index 0000000..b3e6f83 --- /dev/null +++ b/queue/package.json @@ -0,0 +1,82 @@ +{ + "name": "@azure/storage-queue", + "version": "10.0.0-preview", + "description": "Microsoft Azure Storage SDK for JavaScript - Queue", + "main": "./dist/index.js", + "module": "./dist-esm/lib/index.js", + "browser": { + "./dist/index.js": "./browser/azure-storage.queue.min.js", + "./dist-esm/lib/index.js": "./dist-esm/lib/index.browser.js", + "./dist-esm/test/utils/index.js": "./dist-esm/test/utils/index.browser.js", + "os": false, + "process": false + }, + "types": "./typings/lib/index.d.ts", + "engines": { + "node": ">=6.5.0" + }, + "dependencies": { + "ms-rest-js": "0.22.425", + "tslib": "^1.9.3" + }, + "devDependencies": { + "@types/mocha": "^5.2.5", + "@types/node": "^10.12.9", + "assert": "^1.4.1", + "es6-promise": "^4.2.5", + "gulp": "^4.0.0", + "gulp-zip": "^4.2.0", + "karma": "^3.1.1", + "karma-chrome-launcher": "^2.2.0", + "karma-edge-launcher": "^0.4.2", + "karma-env-preprocessor": "^0.1.1", + "karma-firefox-launcher": "^1.1.0", + "karma-ie-launcher": "^1.0.0", + "karma-mocha": "^1.3.0", + "karma-mocha-reporter": "^2.2.5", + "mocha": "^5.2.0", + "rimraf": "^2.6.2", + "rollup": "^0.65.2", + "rollup-plugin-commonjs": "^9.1.8", + "rollup-plugin-multi-entry": "^2.0.2", + "rollup-plugin-node-resolve": "^3.4.0", + "rollup-plugin-replace": "^2.0.0", + "rollup-plugin-shim": "^1.0.0", + "rollup-plugin-uglify": "^5.0.2", + "rollup-plugin-visualizer": "^0.9.0", + "ts-node": "^7.0.1", + "typescript": "^3.2.1" + }, + "scripts": { + "test": "npm run test:node && npm run test:browser", + "test:node": "mocha --no-timeouts dist-test/index.js", + "test:browser": "karma start --single-run", + "build": "npm run build:es6 && npm run build:nodebrowser && npm run build:browserzip && npm run build:test", + "build:test": "rollup -c rollup.test.config.js", + "build:nodebrowser": "rollup -c", + "build:es6": "tsc -p tsconfig.json", + "build:autorest": "autorest ./swagger/README.md --typescript --use=@microsoft.azure/autorest.typescript@2.0.476", + "build:browserzip": "gulp zip", + "clean": "rimraf dist dist-esm dist-test typings temp browser/*.js* browser/*.zip statistics.html" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Azure/azure-storage-js.git" + }, + "keywords": [ + "Azure", + "Storage", + "Queue", + "Node.js", + "TypeScript", + "JavaScript", + "Browser" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Azure/azure-storage-js/issues" + }, + "homepage": "https://github.com/Azure/azure-storage-js#readme", + "sideEffects": false +} diff --git a/queue/rollup.config.js b/queue/rollup.config.js new file mode 100644 index 0000000..333b983 --- /dev/null +++ b/queue/rollup.config.js @@ -0,0 +1,91 @@ +import nodeResolve from "rollup-plugin-node-resolve"; +import { uglify } from "rollup-plugin-uglify"; +import replace from "rollup-plugin-replace"; +import commonjs from "rollup-plugin-commonjs"; +import shim from "rollup-plugin-shim"; +import visualizer from "rollup-plugin-visualizer"; + +const version = require("./package.json").version; +const banner = [ + "/*!", + ` * Azure Storage SDK for JavaScript - Queue, ${version}`, + " * Copyright (c) Microsoft and contributors. All rights reserved.", + " */" +].join("\n"); + +const nodeRollupConfigFactory = () => { + return { + external: ["ms-rest-js", "crypto", "fs", "os"], + input: "dist-esm/lib/index.js", + output: { + file: "dist/index.js", + format: "cjs", + sourcemap: true + }, + plugins: [nodeResolve(), uglify()] + }; +}; + +const browserRollupConfigFactory = isProduction => { + const browserRollupConfig = { + input: "dist-esm/lib/index.browser.js", + output: { + file: "browser/azure-storage.queue.js", + banner: banner, + format: "umd", + name: "azqueue", + sourcemap: true + }, + plugins: [ + replace({ + delimiters: ["", ""], + values: { + // replace dynamic checks with if (false) since this is for + // browser only. Rollup's dead code elimination will remove + // any code guarded by if (isNode) { ... } + "if (isNode)": "if (false)" + } + }), + // os is not used by the browser bundle, so just shim it + shim({ + os: ` + export const type = 1; + export const release = 1; + ` + }), + nodeResolve({ + module: true, + browser: true, + preferBuiltins: false + }), + commonjs({ + namedExports: { + assert: ["ok", "deepEqual", "equal", "fail", "deepStrictEqual"] + } + }) + ] + }; + + if (isProduction) { + browserRollupConfig.output.file = "browser/azure-storage.queue.min.js"; + browserRollupConfig.plugins.push( + uglify({ + output: { + preamble: banner + } + }), + visualizer({ + filename: "./statistics.html", + sourcemap: true + }) + ); + } + + return browserRollupConfig; +}; + +export default [ + nodeRollupConfigFactory(), + browserRollupConfigFactory(true), + browserRollupConfigFactory(false) +]; \ No newline at end of file diff --git a/queue/rollup.test.config.js b/queue/rollup.test.config.js new file mode 100644 index 0000000..6d0809c --- /dev/null +++ b/queue/rollup.test.config.js @@ -0,0 +1,16 @@ +import multi from "rollup-plugin-multi-entry"; +import baseConfig from "./rollup.config"; +const [node, browser] = baseConfig; + +node.input = ["dist-esm/test/*.js", "dist-esm/test/node/*.js"]; +node.output.file = "dist-test/index.js"; +node.plugins.unshift(multi()); +node.external.push("assert", "path"); +node.context = "null"; + +browser.input = ["dist-esm/test/*.js", "dist-esm/test/browser/*.js"]; +browser.output.file = "dist-test/index.browser.js"; +browser.plugins.unshift(multi()); +browser.context = "null"; + +export default [node, browser]; diff --git a/queue/samples/basic.sample.js b/queue/samples/basic.sample.js new file mode 100644 index 0000000..5c4a4a2 --- /dev/null +++ b/queue/samples/basic.sample.js @@ -0,0 +1,105 @@ +// Steps to run this sample +// 1. npm install +// 2. Enter your storage account name and shared key in main() + +const { + Aborter, + QueueURL, + MessagesURL, + MessageIdURL, + ServiceURL, + StorageURL, + SharedKeyCredential, + AnonymousCredential, + TokenCredential +} = require(".."); // Change to "@azure/storage-queue" in your package + +async function main() { + // Enter your storage account name and shared key + const account = ""; + const accountKey = ""; + + // Use SharedKeyCredential with storage account and account key + const sharedKeyCredential = new SharedKeyCredential(account, accountKey); + + // Use TokenCredential with OAuth token + const tokenCredential = new TokenCredential("token"); + tokenCredential.token = "renewedToken"; // Renew the token by updating token field of token credential + + // Use AnonymousCredential when url already includes a SAS signature + const anonymousCredential = new AnonymousCredential(); + + // Use sharedKeyCredential, tokenCredential or anonymousCredential to create a pipeline + const pipeline = StorageURL.newPipeline(sharedKeyCredential, { + // httpClient: MyHTTPClient, // A customized HTTP client implementing IHttpClient interface + // logger: MyLogger, // A customized logger implementing IHttpPipelineLogger interface + retryOptions: { maxTries: 4 }, // Retry options + telemetry: { value: "BasicSample V10.0.0" } // Customized telemetry string + }); + + // List queues + const serviceURL = new ServiceURL( + // When using AnonymousCredential, following url should include a valid SAS or support public access + `https://${account}.queue.core.windows.net`, + pipeline + ); + + console.log(`List queues`); + let marker; + do { + const listQueuesResponse = await serviceURL.listQueuesSegment( + Aborter.none, + marker + ); + + marker = listQueuesResponse.nextMarker; + for (const queue of listQueuesResponse.queueItems) { + console.log(`Queue: ${queue.name}`); + } + } while (marker); + + // Create a new queue + const queueName = `newqueue${new Date().getTime()}`; + const queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + const createQueueResponse = await queueURL.create(Aborter.none); + console.log( + `Create queue ${queueName} successfully, service assigned request Id: ${createQueueResponse.requestId}` + ); + + // Enqueue a message into the queue using the enqueue method. + const messagesURL = MessagesURL.fromQueueURL(queueURL); + const enqueueQueueResponse = await messagesURL.enqueue(Aborter.none, "Hello World!"); + console.log( + `Enqueue message successfully, service assigned message Id: ${enqueueQueueResponse.messageId}, service assigned request Id: ${enqueueQueueResponse.requestId}` + ); + + // Peek a message using peek method. + const peekQueueResponse = await messagesURL.peek(Aborter.none); + console.log(`The peeked message is: ${peekQueueResponse.peekedMessageItems[0].messageText}`); + + // You de-queue a message in two steps. Call GetMessage at which point the message becomes invisible to any other code reading messages + // from this queue for a default period of 30 seconds. To finish removing the message from the queue, you call DeleteMessage. + // This two-step process ensures that if your code fails to process a message due to hardware or software failure, another instance + // of your code can get the same message and try again. + const dequeueResponse = await messagesURL.dequeue(Aborter.none); + if (dequeueResponse.dequeuedMessageItems.length == 1) { + const dequeueMessageItem = dequeueResponse.dequeuedMessageItems[0]; + console.log(`Processing & deleting message with content: ${dequeueMessageItem.messageText}`); + const messageIdURL = MessageIdURL.fromMessagesURL(messagesURL, dequeueMessageItem.messageId); + const deleteMessageResponse = await messageIdURL.delete(Aborter.none, dequeueMessageItem.popReceipt); + console.log(`Delete message succesfully, service assigned request Id: ${deleteMessageResponse.requestId}`); + } + + // Delete the queue. + const deleteQueueResponse = await queueURL.delete(Aborter.none); + console.log(`Delete queue successfully, service assigned request Id: ${deleteQueueResponse.requestId}`); +} + +// An async method returns a Promise object, which is compatible with then().catch() coding style. +main() + .then(() => { + console.log("Successfully executed sample."); + }) + .catch(err => { + console.log(err.message); + }); \ No newline at end of file diff --git a/queue/swagger/README.md b/queue/swagger/README.md new file mode 100644 index 0000000..bbd26aa --- /dev/null +++ b/queue/swagger/README.md @@ -0,0 +1,16 @@ +# Azure Storage TypeScript Protocol Layer + +> see https://aka.ms/autorest + +```yaml +package-name: azure-storage-queue +title: StorageClient +description: Storage Client +enable-xml: true +generate-metadata: false +license-header: MICROSOFT_MIT_NO_VERSION +output-folder: ../lib/generated +input-file: ./queue-storage-2018-03-28.json +model-date-time-as-string: true +optional-response-headers: true +``` diff --git a/queue/test/aborter.test.ts b/queue/test/aborter.test.ts new file mode 100644 index 0000000..d6eca65 --- /dev/null +++ b/queue/test/aborter.test.ts @@ -0,0 +1,66 @@ +import * as assert from "assert"; + +import { Aborter } from "../lib/Aborter"; +import { QueueURL } from "../lib/QueueURL"; +import { getQSU, getUniqueName } from "./utils"; + +// tslint:disable:no-empty +describe("Aborter", () => { + const serviceURL = getQSU(); + let queueName: string = getUniqueName("queue"); + let queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + + beforeEach(async () => { + queueName = getUniqueName("queue"); + queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + }); + + it("Should not abort after calling abort()", async () => { + const cResp = await queueURL.create(Aborter.none); + assert.ok(cResp.date); + await queueURL.delete(Aborter.none); + }); + + it("Should abort when calling abort() before request finishes", async () => { + const aborter = Aborter.none; + const response = queueURL.create(aborter); + aborter.abort(); + try { + await response; + assert.fail(); + } catch (err) {} + }); + + it("Should not abort when calling abort() after request finishes", async () => { + const aborter = Aborter.none; + await queueURL.create(aborter); + aborter.abort(); + await queueURL.delete(Aborter.none); + }); + + it("Should abort after aborter timeout", async () => { + try { + await queueURL.create(Aborter.timeout(1)); + assert.fail(); + } catch (err) {} + }); + + it("Should abort after parent aborter calls abort()", async () => { + try { + const aborter = Aborter.none; + const response = queueURL.create(aborter.withTimeout(10 * 60 * 1000)); + aborter.abort(); + await response; + assert.fail(); + } catch (err) {} + }); + + it("Should abort after parent aborter timeout", async () => { + try { + const aborter = Aborter.timeout(1); + const response = queueURL.create(aborter.withTimeout(10 * 60 * 1000)); + await response; + assert.fail(); + } catch (err) {} + }); +}); diff --git a/queue/test/messageidurl.test.ts b/queue/test/messageidurl.test.ts new file mode 100644 index 0000000..30ad71d --- /dev/null +++ b/queue/test/messageidurl.test.ts @@ -0,0 +1,69 @@ +import * as assert from "assert"; + +import { Aborter } from "../lib/Aborter"; +import { QueueURL } from "../lib/QueueURL"; +import { MessagesURL } from "../lib/MessagesURL"; +import { MessageIdURL } from "../lib/MessageIdURL"; +import { getQSU, getUniqueName } from "./utils"; + +describe("MessageIdURL", () => { + const serviceURL = getQSU(); + let queueName = getUniqueName("queue"); + let queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + const messageContent = "Hello World"; + + beforeEach(async () => { + queueName = getUniqueName("queue"); + queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + }); + + afterEach(async () => { + await queueURL.delete(Aborter.none); + }); + + it("update and delete message with default/all parameters", async () => { + let messagesURL = MessagesURL.fromQueueURL(queueURL); + let eResult = await messagesURL.enqueue(Aborter.none, messageContent); + assert.ok(eResult.date); + assert.ok(eResult.expirationTime); + assert.ok(eResult.insertionTime); + assert.ok(eResult.messageId); + assert.ok(eResult.popReceipt); + assert.ok(eResult.requestId); + assert.ok(eResult.timeNextVisible); + assert.ok(eResult.version); + + let newMessage = "New Message"; + let messageIdURL = MessageIdURL.fromMessagesURL( + messagesURL, + eResult.messageId + ); + let uResult = await messageIdURL.update( + Aborter.none, + eResult.popReceipt, + 0, + newMessage + ); + assert.ok(uResult.version); + assert.ok(uResult.timeNextVisible); + assert.ok(uResult.date); + assert.ok(uResult.requestId); + assert.ok(uResult.popReceipt); + + let pResult = await messagesURL.peek(Aborter.none); + assert.equal(pResult.peekedMessageItems.length, 1); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageText, + newMessage + ); + + let dResult = await messageIdURL.delete(Aborter.none, uResult.popReceipt!); + assert.ok(dResult.date); + assert.ok(dResult.requestId); + assert.ok(dResult.version); + + pResult = await messagesURL.peek(Aborter.none); + assert.equal(pResult.peekedMessageItems.length, 0); + }); +}); diff --git a/queue/test/messagesurl.test.ts b/queue/test/messagesurl.test.ts new file mode 100644 index 0000000..fb44542 --- /dev/null +++ b/queue/test/messagesurl.test.ts @@ -0,0 +1,249 @@ +import * as assert from "assert"; + +import { Aborter } from "../lib/Aborter"; +import { QueueURL } from "../lib/QueueURL"; +import { MessagesURL } from "../lib/MessagesURL"; +import { getQSU, getUniqueName } from "./utils"; + +describe("MessagesURL", () => { + const serviceURL = getQSU(); + let queueName = getUniqueName("queue"); + let queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + const messageContent = "Hello World"; + + beforeEach(async () => { + queueName = getUniqueName("queue"); + queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + }); + + afterEach(async () => { + await queueURL.delete(Aborter.none); + }); + + it("enqueue, peek, dequeue and clear message with default parameters", async () => { + let messagesURL = MessagesURL.fromQueueURL(queueURL); + let eResult = await messagesURL.enqueue(Aborter.none, messageContent); + assert.ok(eResult.date); + assert.ok(eResult.expirationTime); + assert.ok(eResult.insertionTime); + assert.ok(eResult.messageId); + assert.ok(eResult.popReceipt); + assert.ok(eResult.requestId); + assert.ok(eResult.timeNextVisible); + assert.ok(eResult.version); + + await messagesURL.enqueue(Aborter.none, messageContent); + + let pResult = await messagesURL.peek(Aborter.none); + assert.ok(pResult.date); + assert.ok(pResult.requestId); + assert.ok(pResult.version); + assert.deepStrictEqual(pResult.peekedMessageItems.length, 1); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageText, + messageContent + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageId, + eResult.messageId + ); + + let dqResult = await messagesURL.dequeue(Aborter.none); + assert.ok(dqResult.date); + assert.ok(dqResult.requestId); + assert.ok(dqResult.version); + assert.deepStrictEqual(dqResult.dequeuedMessageItems.length, 1); + assert.ok(dqResult.dequeuedMessageItems[0].popReceipt); + assert.deepStrictEqual( + dqResult.dequeuedMessageItems[0].messageText, + messageContent + ); + assert.deepStrictEqual( + dqResult.dequeuedMessageItems[0].messageId, + eResult.messageId + ); + + let cResult = await messagesURL.clear(Aborter.none); + assert.ok(cResult.date); + assert.ok(cResult.requestId); + assert.ok(cResult.version); + + // check all messages are cleared + let pResult2 = await messagesURL.peek(Aborter.none); + assert.ok(pResult2.date); + assert.deepStrictEqual(pResult2.peekedMessageItems.length, 0); + }); + + it("enqueue, peek, dequeue and clear message with all parameters", async () => { + let messagesURL = MessagesURL.fromQueueURL(queueURL); + + let eResult = await messagesURL.enqueue(Aborter.none, messageContent, { + messageTimeToLive: 40, + visibilitytimeout: 0 + }); + assert.ok(eResult.date); + assert.ok(eResult.expirationTime); + assert.ok(eResult.insertionTime); + assert.ok(eResult.messageId); + assert.ok(eResult.popReceipt); + assert.ok(eResult.requestId); + assert.ok(eResult.timeNextVisible); + assert.ok(eResult.version); + + let eResult2 = await messagesURL.enqueue(Aborter.none, messageContent, { + messageTimeToLive: 40, + visibilitytimeout: 0 + }); + await messagesURL.enqueue(Aborter.none, messageContent, { + messageTimeToLive: 10, + visibilitytimeout: 5 + }); + await messagesURL.enqueue(Aborter.none, messageContent, { + messageTimeToLive: 20, + visibilitytimeout: 19 + }); + + let pResult = await messagesURL.peek(Aborter.none, { numberOfMessages: 2 }); + assert.ok(pResult.date); + assert.ok(pResult.requestId); + assert.ok(pResult.version); + assert.deepStrictEqual(pResult.peekedMessageItems.length, 2); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageText, + messageContent + ); + assert.deepStrictEqual(pResult.peekedMessageItems[0].dequeueCount, 0); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageId, + eResult.messageId + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].insertionTime, + eResult.insertionTime + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].expirationTime, + eResult.expirationTime + ); + + assert.deepStrictEqual( + pResult.peekedMessageItems[1].messageText, + messageContent + ); + assert.deepStrictEqual(pResult.peekedMessageItems[1].dequeueCount, 0); + assert.deepStrictEqual( + pResult.peekedMessageItems[1].messageId, + eResult2.messageId + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[1].insertionTime, + eResult2.insertionTime + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[1].expirationTime, + eResult2.expirationTime + ); + + let dResult = await messagesURL.dequeue(Aborter.none, { + visibilitytimeout: 10, + numberOfMessages: 2 + }); + assert.ok(dResult.date); + assert.ok(dResult.requestId); + assert.ok(dResult.version); + assert.deepStrictEqual(dResult.dequeuedMessageItems.length, 2); + assert.deepStrictEqual( + dResult.dequeuedMessageItems[0].messageText, + messageContent + ); + assert.deepStrictEqual(dResult.dequeuedMessageItems[0].dequeueCount, 1); + assert.deepStrictEqual( + dResult.dequeuedMessageItems[0].messageId, + eResult.messageId + ); + assert.deepStrictEqual( + dResult.dequeuedMessageItems[0].insertionTime, + eResult.insertionTime + ); + assert.deepStrictEqual( + dResult.dequeuedMessageItems[0].expirationTime, + eResult.expirationTime + ); + assert.ok(dResult.dequeuedMessageItems[0].popReceipt); + assert.ok(dResult.dequeuedMessageItems[0].timeNextVisible); + + assert.deepStrictEqual( + pResult.peekedMessageItems[1].messageText, + messageContent + ); + + // check no message is visible + let pResult2 = await messagesURL.peek(Aborter.none); + assert.ok(pResult2.date); + assert.deepStrictEqual(pResult2.peekedMessageItems.length, 0); + }); + + it("enqueue, dequeue and peek negative", async () => { + let messagesURL = MessagesURL.fromQueueURL(queueURL); + let eResult = await messagesURL.enqueue(Aborter.none, messageContent, { + messageTimeToLive: 40 + }); + assert.ok(eResult.date); + assert.ok(eResult.expirationTime); + assert.ok(eResult.insertionTime); + assert.ok(eResult.messageId); + assert.ok(eResult.popReceipt); + assert.ok(eResult.requestId); + assert.ok(eResult.timeNextVisible); + assert.ok(eResult.version); + + let error; + try { + await messagesURL.enqueue(Aborter.none, messageContent, { + messageTimeToLive: 30, + visibilitytimeout: 30 + }); + } catch (err) { + error = err; + } + assert.ok(error); + + let errorPeek; + try { + await messagesURL.peek(Aborter.none, { numberOfMessages: 100 }); + } catch (err) { + errorPeek = err; + } + assert.ok(errorPeek); + + let pResult = await messagesURL.peek(Aborter.none, { numberOfMessages: 2 }); + assert.ok(pResult.date); + assert.ok(pResult.requestId); + assert.ok(pResult.version); + assert.deepStrictEqual(pResult.peekedMessageItems.length, 1); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageText, + messageContent + ); + assert.deepStrictEqual(pResult.peekedMessageItems[0].dequeueCount, 0); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageId, + eResult.messageId + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].insertionTime, + eResult.insertionTime + ); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].expirationTime, + eResult.expirationTime + ); + + // Note visibility time could be larger then message time to live for dequeue. + await messagesURL.dequeue(Aborter.none, { + visibilitytimeout: 40, + numberOfMessages: 2 + }); + }); +}); diff --git a/queue/test/node/queueurl.test.ts b/queue/test/node/queueurl.test.ts new file mode 100644 index 0000000..58a3f74 --- /dev/null +++ b/queue/test/node/queueurl.test.ts @@ -0,0 +1,66 @@ +import * as assert from "assert"; + +import { Aborter } from "../../lib/Aborter"; +import { QueueURL } from "../../lib/QueueURL"; +import { getQSU, getUniqueName } from "../utils"; + +describe("QueueURL", () => { + const serviceURL = getQSU(); + let queueName: string = getUniqueName("queue"); + let queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + + beforeEach(async () => { + queueName = getUniqueName("queue"); + queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + }); + + afterEach(async () => { + await queueURL.delete(Aborter.none); + }); + + it("getAccessPolicy", async () => { + const result = await queueURL.getAccessPolicy(Aborter.none); + assert.ok(result.requestId); + assert.ok(result.version); + assert.ok(result.date); + }); + + it("setAccessPolicy", async () => { + const queueAcl = [ + { + accessPolicy: { + expiry: new Date("2018-12-31T11:22:33.4567890Z"), + permission: "raup", + start: new Date("2017-12-31T11:22:33.4567890Z") + }, + id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" + } + ]; + + await queueURL.setAccessPolicy(Aborter.none, queueAcl); + const result = await queueURL.getAccessPolicy(Aborter.none); + assert.deepEqual(result.signedIdentifiers, queueAcl); + }); + + it("setAccessPolicy negative", async () => { + const queueAcl = [ + { + accessPolicy: { + expiry: new Date("2018-12-31T11:22:33.4567890Z"), + permission: "rwdl", + start: new Date("2017-12-31T11:22:33.4567890Z") + }, + id: "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" + } + ]; + + let error; + try { + await queueURL.setAccessPolicy(Aborter.none, queueAcl); + } catch (err) { + error = err; + } + assert.ok(error); + }); +}); diff --git a/queue/test/node/sas.test.ts b/queue/test/node/sas.test.ts new file mode 100644 index 0000000..b059341 --- /dev/null +++ b/queue/test/node/sas.test.ts @@ -0,0 +1,349 @@ +import * as assert from "assert"; + +import { + AccountSASPermissions, + AccountSASResourceTypes, + AccountSASServices, + AnonymousCredential, + QueueSASPermissions, + generateAccountSASQueryParameters, + generateQueueSASQueryParameters, + ServiceURL, + SharedKeyCredential, + StorageURL +} from "../../lib"; +import { Aborter } from "../../lib/Aborter"; +import { + QueueURL, + MessagesURL, + MessageIdURL, + SASProtocol +} from "../../lib/index.browser"; +import { getQSU, getUniqueName, sleep } from "../utils/index"; + +describe("Shared Access Signature (SAS) generation Node.js only", () => { + const serviceURL = getQSU(); + + it("generateAccountSASQueryParameters should work", async () => { + const now = new Date(); + now.setMinutes(now.getMinutes() - 5); // Skip clock skew with server + + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const sas = generateAccountSASQueryParameters( + { + expiryTime: tmr, + ipRange: { start: "0.0.0.0", end: "255.255.255.255" }, + permissions: AccountSASPermissions.parse("rwdlacup").toString(), + protocol: SASProtocol.HTTPSandHTTP, + resourceTypes: AccountSASResourceTypes.parse("sco").toString(), + services: AccountSASServices.parse("btqf").toString(), + startTime: now, + version: "2016-05-31" + }, + sharedKeyCredential as SharedKeyCredential + ).toString(); + + const sasURL = `${serviceURL.url}?${sas}`; + const serviceURLwithSAS = new ServiceURL( + sasURL, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + await serviceURLwithSAS.getProperties(Aborter.none); + }); + + it("generateAccountSASQueryParameters should not work with invalid permission", async () => { + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const sas = generateAccountSASQueryParameters( + { + expiryTime: tmr, + permissions: AccountSASPermissions.parse("wdlcup").toString(), + resourceTypes: AccountSASResourceTypes.parse("sco").toString(), + services: AccountSASServices.parse("btqf").toString() + }, + sharedKeyCredential as SharedKeyCredential + ).toString(); + + const sasURL = `${serviceURL.url}?${sas}`; + const serviceURLwithSAS = new ServiceURL( + sasURL, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + let error; + try { + await serviceURLwithSAS.getProperties(Aborter.none); + } catch (err) { + error = err; + } + + assert.ok(error); + }); + + it("generateAccountSASQueryParameters should not work with invalid service", async () => { + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const sas = generateAccountSASQueryParameters( + { + expiryTime: tmr, + permissions: AccountSASPermissions.parse("rwdlacup").toString(), + resourceTypes: AccountSASResourceTypes.parse("sco").toString(), + services: AccountSASServices.parse("b").toString() + }, + sharedKeyCredential as SharedKeyCredential + ).toString(); + + const sasURL = `${serviceURL.url}?${sas}`; + const serviceURLwithSAS = new ServiceURL( + sasURL, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + let error; + try { + await serviceURLwithSAS.getProperties(Aborter.none); + } catch (err) { + error = err; + } + + assert.ok(error); + }); + + it("generateAccountSASQueryParameters should not work with invalid resource type", async () => { + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const sas = generateAccountSASQueryParameters( + { + expiryTime: tmr, + ipRange: { start: "0.0.0.0", end: "255.255.255.255" }, + permissions: AccountSASPermissions.parse("rwdlacup").toString(), + protocol: SASProtocol.HTTPSandHTTP, + resourceTypes: AccountSASResourceTypes.parse("co").toString(), + services: AccountSASServices.parse("btqf").toString(), + version: "2016-05-31" + }, + sharedKeyCredential as SharedKeyCredential + ).toString(); + + const sasURL = `${serviceURL.url}?${sas}`; + const serviceURLwithSAS = new ServiceURL( + sasURL, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + let error; + try { + await serviceURLwithSAS.getProperties(Aborter.none); + } catch (err) { + error = err; + } + + assert.ok(error); + }); + + it("generateQueueSASQueryParameters should work for queue", async () => { + const now = new Date(); + now.setMinutes(now.getMinutes() - 5); // Skip clock skew with server + + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const queueName = getUniqueName("queue"); + const queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + + const queueSAS = generateQueueSASQueryParameters( + { + queueName, + expiryTime: tmr, + ipRange: { start: "0.0.0.0", end: "255.255.255.255" }, + permissions: QueueSASPermissions.parse("raup").toString(), + protocol: SASProtocol.HTTPSandHTTP, + startTime: now, + version: "2016-05-31" + }, + sharedKeyCredential as SharedKeyCredential + ); + + const sasURL = `${queueURL.url}?${queueSAS}`; + const queueURLwithSAS = new QueueURL( + sasURL, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + await queueURLwithSAS.getProperties(Aborter.none); + await queueURL.delete(Aborter.none); + }); + + it("generateQueueSASQueryParameters should work for messages", async () => { + const now = new Date(); + now.setMinutes(now.getMinutes() - 5); // Skip clock skew with server + + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const queueName = getUniqueName("queue"); + const queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + + const queueSAS = generateQueueSASQueryParameters( + { + queueName: queueName, + expiryTime: tmr, + ipRange: { start: "0.0.0.0", end: "255.255.255.255" }, + permissions: QueueSASPermissions.parse("raup").toString(), + protocol: SASProtocol.HTTPSandHTTP, + startTime: now, + version: "2016-05-31" + }, + sharedKeyCredential as SharedKeyCredential + ); + + const messageContent = "Hello World!"; + + const messagesURL = MessagesURL.fromQueueURL(queueURL); + const sasURLForMessages = `${messagesURL.url}?${queueSAS}`; + const messagesURLWithSAS = new MessagesURL( + sasURLForMessages, + StorageURL.newPipeline(new AnonymousCredential()) + ); + const enqueueResult = await messagesURLWithSAS.enqueue( + Aborter.none, + messageContent + ); + + let pResult = await messagesURL.peek(Aborter.none); + assert.deepStrictEqual(pResult.peekedMessageItems.length, 1); + + const messageIdURL = MessageIdURL.fromMessagesURL( + messagesURL, + enqueueResult.messageId + ); + const sasURLForMessageId = `${messageIdURL.url}?${queueSAS}`; + const messageIdURLWithSAS = new MessageIdURL( + sasURLForMessageId, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + await messageIdURLWithSAS.delete(Aborter.none, enqueueResult.popReceipt); + + pResult = await messagesURL.peek(Aborter.none); + assert.deepStrictEqual(pResult.peekedMessageItems.length, 0); + + await queueURL.delete(Aborter.none); + }); + + it("generateQueueSASQueryParameters should work for queue with access policy", async () => { + const now = new Date(); + now.setMinutes(now.getMinutes() - 5); // Skip clock skew with server + + const tmr = new Date(); + tmr.setDate(tmr.getDate() + 1); + + // By default, credential is always the last element of pipeline factories + const factories = serviceURL.pipeline.factories; + const sharedKeyCredential = factories[factories.length - 1]; + + const queueName = getUniqueName("queue"); + const queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + + const id = "unique-id"; + await queueURL.setAccessPolicy(Aborter.none, [ + { + accessPolicy: { + expiry: tmr, + permission: QueueSASPermissions.parse("raup").toString(), + start: now + }, + id + } + ]); + + const queueSAS = generateQueueSASQueryParameters( + { + queueName, + identifier: id + }, + sharedKeyCredential as SharedKeyCredential + ); + + const messagesURL = MessagesURL.fromQueueURL(queueURL); + + const sasURL = `${messagesURL.url}?${queueSAS}`; + const messagesURLwithSAS = new MessagesURL( + sasURL, + StorageURL.newPipeline(new AnonymousCredential()) + ); + + const messageContent = "hello"; + + const eResult = await messagesURLwithSAS.enqueue( + Aborter.none, + messageContent + ); + assert.ok(eResult.messageId); + const pResult = await messagesURLwithSAS.peek(Aborter.none); + assert.deepStrictEqual( + pResult.peekedMessageItems[0].messageText, + messageContent + ); + const dResult = await messagesURLwithSAS.dequeue(Aborter.none, { + visibilitytimeout: 1 + }); + assert.deepStrictEqual( + dResult.dequeuedMessageItems[0].messageText, + messageContent + ); + + await sleep(2 * 1000); + + const messageIdURL = MessageIdURL.fromMessagesURL( + messagesURL, + dResult.dequeuedMessageItems[0].messageId + ); + + const sasURLForMessage = `${messageIdURL.url}?${queueSAS}`; + const messageIdURLwithSAS = new MessageIdURL( + sasURLForMessage, + StorageURL.newPipeline(new AnonymousCredential()) + ); + const deleteResult = await messageIdURLwithSAS.delete( + Aborter.none, + dResult.dequeuedMessageItems[0].popReceipt + ); + assert.ok(deleteResult.requestId); + + //const cResult = await messagesURLwithSAS.clear(Aborter.none); //This request is not authorized to perform this operation. As testing, this is service's current behavior. + }); +}); diff --git a/queue/test/queueurl.test.ts b/queue/test/queueurl.test.ts new file mode 100644 index 0000000..5208941 --- /dev/null +++ b/queue/test/queueurl.test.ts @@ -0,0 +1,59 @@ +import * as assert from "assert"; + +import { Aborter } from "../lib/Aborter"; +import { QueueURL } from "../lib/QueueURL"; +import { getQSU, getUniqueName } from "./utils"; + +describe("QueueURL", () => { + const serviceURL = getQSU(); + let queueName = getUniqueName("queue"); + let queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + + beforeEach(async () => { + queueName = getUniqueName("queue"); + queueURL = QueueURL.fromServiceURL(serviceURL, queueName); + await queueURL.create(Aborter.none); + }); + + afterEach(async () => { + await queueURL.delete(Aborter.none); + }); + + it("setMetadata", async () => { + const metadata = { + key0: "val0", + keya: "vala", + keyb: "valb" + }; + await queueURL.setMetadata(Aborter.none, metadata); + + const result = await queueURL.getProperties(Aborter.none); + assert.deepEqual(result.metadata, metadata); + }); + + it("getProperties with default/all parameters", async () => { + const result = await queueURL.getProperties(Aborter.none); + assert.ok(result.approximateMessagesCount! >= 0); + assert.ok(result.requestId); + assert.ok(result.version); + assert.ok(result.date); + }); + + it("create with default parameters", done => { + // create() with default parameters has been tested in beforeEach + done(); + }); + + it("create with all parameters", async () => { + const qURL = QueueURL.fromServiceURL(serviceURL, getUniqueName(queueName)); + const metadata = { key: "value" }; + await qURL.create(Aborter.none, { metadata }); + const result = await qURL.getProperties(Aborter.none); + assert.deepEqual(result.metadata, metadata); + }); + + it("delete", done => { + // delete() with default parameters has been tested in afterEach + done(); + }); +}); diff --git a/queue/test/serviceurl.test.ts b/queue/test/serviceurl.test.ts new file mode 100644 index 0000000..462ae5a --- /dev/null +++ b/queue/test/serviceurl.test.ts @@ -0,0 +1,167 @@ +import * as assert from "assert"; + +import { Aborter } from "../lib/Aborter"; +import { QueueURL } from "../lib/QueueURL"; +import { ListQueuesIncludeType } from "../lib/generated/models"; +import { ServiceURL } from "../lib/ServiceURL"; +import { getAlternateQSU, getQSU, getUniqueName, wait } from "./utils"; + +describe("ServiceURL", () => { + it("listQueuesSegment with default parameters", async () => { + const serviceURL = getQSU(); + const result = await serviceURL.listQueuesSegment(Aborter.none); + assert.ok(typeof result.requestId); + assert.ok(result.requestId!.length > 0); + assert.ok(typeof result.version); + assert.ok(result.version!.length > 0); + + assert.ok(result.serviceEndpoint.length > 0); + assert.ok(result.queueItems!.length >= 0); + + if (result.queueItems!.length > 0) { + const queue = result.queueItems![0]; + assert.ok(queue.name.length > 0); + } + }); + + it("listQueuesSegment with all parameters", async () => { + const serviceURL = getQSU(); + + const queueNamePrefix = getUniqueName("queue"); + const queueName1 = `${queueNamePrefix}x1`; + const queueName2 = `${queueNamePrefix}x2`; + const queueURL1 = QueueURL.fromServiceURL(serviceURL, queueName1); + const queueURL2 = QueueURL.fromServiceURL(serviceURL, queueName2); + await queueURL1.create(Aborter.none, { metadata: { key: "val" } }); + await queueURL2.create(Aborter.none, { metadata: { key: "val" } }); + + const result1 = await serviceURL.listQueuesSegment( + Aborter.none, + undefined, + { + include: ListQueuesIncludeType.Metadata, + maxresults: 1, + prefix: queueNamePrefix + } + ); + + assert.ok(result1.nextMarker); + assert.equal(result1.queueItems!.length, 1); + assert.ok(result1.queueItems![0].name.startsWith(queueNamePrefix)); + assert.deepEqual(result1.queueItems![0].metadata!.key, "val"); + + const result2 = await serviceURL.listQueuesSegment( + Aborter.none, + result1.nextMarker, + { + include: ListQueuesIncludeType.Metadata, + maxresults: 1, + prefix: queueNamePrefix + } + ); + + assert.ok(!result2.nextMarker); + assert.equal(result2.queueItems!.length, 1); + assert.ok(result2.queueItems![0].name.startsWith(queueNamePrefix)); + assert.deepEqual(result2.queueItems![0].metadata!.key, "val"); + + await queueURL1.delete(Aborter.none); + await queueURL2.delete(Aborter.none); + }); + + it("getProperties with default/all parameters", async () => { + const serviceURL = getQSU(); + const result = await serviceURL.getProperties(Aborter.none); + + assert.ok(typeof result.requestId); + assert.ok(result.requestId!.length > 0); + assert.ok(typeof result.version); + assert.ok(result.version!.length > 0); + + if (result.cors && result.cors!.length > 0) { + assert.ok(result.cors![0].allowedHeaders.length > 0); + assert.ok(result.cors![0].allowedMethods.length > 0); + assert.ok(result.cors![0].allowedOrigins.length > 0); + assert.ok(result.cors![0].exposedHeaders.length > 0); + assert.ok(result.cors![0].maxAgeInSeconds >= 0); + } + }); + + it("setProperties with all parameters", async () => { + const serviceURL = getQSU(); + + const serviceProperties = await serviceURL.getProperties(Aborter.none); + + serviceProperties.logging = { + deleteProperty: true, + read: true, + retentionPolicy: { + days: 5, + enabled: true + }, + version: "1.0", + write: true + }; + + serviceProperties.minuteMetrics = { + enabled: true, + includeAPIs: true, + retentionPolicy: { + days: 4, + enabled: true + }, + version: "1.0" + }; + + serviceProperties.hourMetrics = { + enabled: true, + includeAPIs: true, + retentionPolicy: { + days: 3, + enabled: true + }, + version: "1.0" + }; + + const newCORS = { + allowedHeaders: "*", + allowedMethods: "GET", + allowedOrigins: "example.com", + exposedHeaders: "*", + maxAgeInSeconds: 8888 + }; + if (!serviceProperties.cors) { + serviceProperties.cors = [newCORS]; + } else if (serviceProperties.cors!.length < 5) { + serviceProperties.cors.push(newCORS); + } + + await serviceURL.setProperties(Aborter.none, serviceProperties); + await wait(5 * 1000); + + const result = await serviceURL.getProperties(Aborter.none); + assert.ok(typeof result.requestId); + assert.ok(result.requestId!.length > 0); + assert.ok(typeof result.version); + assert.ok(result.version!.length > 0); + assert.deepEqual(result.hourMetrics, serviceProperties.hourMetrics); + }); + + it("getStatistics with default/all parameters", done => { + let serviceURL: ServiceURL | undefined; + try { + serviceURL = getAlternateQSU(); + } catch (err) { + done(); + return; + } + + serviceURL! + .getStatistics(Aborter.none) + .then(result => { + assert.ok(result.geoReplication!.lastSyncTime); + done(); + }) + .catch(done); + }); +}); diff --git a/queue/test/utils/index.browser.ts b/queue/test/utils/index.browser.ts new file mode 100644 index 0000000..e132b61 --- /dev/null +++ b/queue/test/utils/index.browser.ts @@ -0,0 +1,135 @@ +import { AnonymousCredential } from "../../lib/credentials/AnonymousCredential"; +import { ServiceURL } from "../../lib/ServiceURL"; +import { StorageURL } from "../../lib/StorageURL"; + +export * from "./testutils.common"; + +export function getGenericQSU( + accountType: string, + accountNameSuffix: string = "" +): ServiceURL { + const accountNameEnvVar = `${accountType}ACCOUNT_NAME`; + const accountSASEnvVar = `${accountType}ACCOUNT_SAS`; + + let accountName: string | undefined; + let accountSAS: string | undefined; + accountName = (window as any).__env__[accountNameEnvVar]; + accountSAS = (window as any).__env__[accountSASEnvVar]; + + if (!accountName || !accountSAS || accountName === "" || accountSAS === "") { + throw new Error( + `${accountNameEnvVar} and/or ${accountSASEnvVar} environment variables not specified.` + ); + } + + if (accountSAS) { + accountSAS = accountSAS.startsWith("?") ? accountSAS : `?${accountSAS}`; + } + + const credentials = new AnonymousCredential(); + const pipeline = StorageURL.newPipeline(credentials, { + // Enable logger when debugging + // logger: new ConsoleHttpPipelineLogger(HttpPipelineLogLevel.INFO) + }); + const filePrimaryURL = `https://${accountName}${accountNameSuffix}.queue.core.windows.net${accountSAS}`; + return new ServiceURL(filePrimaryURL, pipeline); +} + +export function getQSU(): ServiceURL { + return getGenericQSU(""); +} + +export function getAlternateQSU(): ServiceURL { + return getGenericQSU("SECONDARY_", "-secondary"); +} + +/** + * Read body from downloading operation methods to string. + * Work on both Node.js and browser environment. + * + * @param response Convenience layer methods response with downloaded body + * @param length Length of Readable stream, needed for Node.js environment + */ +export async function bodyToString( + response: { + readableStreamBody?: NodeJS.ReadableStream; + blobBody?: Promise; + }, + // tslint:disable-next-line:variable-name + _length?: number +): Promise { + const blob = await response.blobBody!; + return blobToString(blob); +} + +export async function blobToString(blob: Blob): Promise { + const fileReader = new FileReader(); + return new Promise((resolve, reject) => { + fileReader.onloadend = (ev: any) => { + resolve(ev.target!.result); + }; + fileReader.onerror = reject; + fileReader.readAsText(blob); + }); +} + +export async function blobToArrayBuffer(blob: Blob): Promise { + const fileReader = new FileReader(); + return new Promise((resolve, reject) => { + fileReader.onloadend = (ev: any) => { + resolve(ev.target!.result); + }; + fileReader.onerror = reject; + fileReader.readAsArrayBuffer(blob); + }); +} + +export function arrayBufferEqual( + buf1: ArrayBuffer, + buf2: ArrayBuffer +): boolean { + if (buf1.byteLength !== buf2.byteLength) { + return false; + } + + const uint8Arr1 = new Uint8Array(buf1); + const uint8Arr2 = new Uint8Array(buf2); + + for (let i = 0; i <= uint8Arr1.length; i++) { + if (uint8Arr1[i] !== uint8Arr2[i]) { + return false; + } + } + + return true; +} + +export function isIE(): boolean { + const sAgent = window.navigator.userAgent; + const Idx = sAgent.indexOf("MSIE"); + + // If IE, return version number. + if (Idx > 0) { + return true; + } else if (!!navigator.userAgent.match(/Trident\/7\./)) { + // IE 11 + return true; + } else { + return false; + } // It is not IE +} + +// Mock a Browser file with specified name and size +export function getBrowserFile(name: string, size: number): File { + const uint8Arr = new Uint8Array(size); + for (let j = 0; j < size; j++) { + uint8Arr[j] = Math.floor(Math.random() * 256); + } + + // IE11 & Edge doesn't support create File using var file = new File([binary], name); + // We leverage Blob() to mock a File + + const file = new Blob([uint8Arr]) as any; + file.name = name; + return file; +} diff --git a/queue/test/utils/index.ts b/queue/test/utils/index.ts new file mode 100644 index 0000000..108338f --- /dev/null +++ b/queue/test/utils/index.ts @@ -0,0 +1,44 @@ +import { SharedKeyCredential } from "../../lib/credentials/SharedKeyCredential"; +import { ServiceURL } from "../../lib/ServiceURL"; +import { StorageURL } from "../../lib/StorageURL"; +// Uncomment if need to enable logger when debugging +// import {HttpPipelineLogLevel} from "../../lib" +// import {ConsoleHttpPipelineLogger} from "./testutils.common" + +export * from "./testutils.common"; + +export function getGenericQSU( + accountType: string, + accountNameSuffix: string = "" +): ServiceURL { + const accountNameEnvVar = `${accountType}ACCOUNT_NAME`; + const accountKeyEnvVar = `${accountType}ACCOUNT_KEY`; + + let accountName: string | undefined; + let accountKey: string | undefined; + + accountName = process.env[accountNameEnvVar]; + accountKey = process.env[accountKeyEnvVar]; + + if (!accountName || !accountKey || accountName === "" || accountKey === "") { + throw new Error( + `${accountNameEnvVar} and/or ${accountKeyEnvVar} environment variables not specified.` + ); + } + + const credentials = new SharedKeyCredential(accountName, accountKey); + const pipeline = StorageURL.newPipeline(credentials, { + // Enable logger when debugging + // logger: new ConsoleHttpPipelineLogger(HttpPipelineLogLevel.INFO) + }); + const queuePrimaryURL = `https://${accountName}${accountNameSuffix}.queue.core.windows.net/`; + return new ServiceURL(queuePrimaryURL, pipeline); +} + +export function getQSU(): ServiceURL { + return getGenericQSU(""); +} + +export function getAlternateQSU(): ServiceURL { + return getGenericQSU("SECONDARY_", "-secondary"); +} diff --git a/queue/test/utils/testutils.common.ts b/queue/test/utils/testutils.common.ts new file mode 100644 index 0000000..93994a0 --- /dev/null +++ b/queue/test/utils/testutils.common.ts @@ -0,0 +1,59 @@ +import { HttpPipelineLogLevel, IHttpPipelineLogger } from "../../lib/Pipeline"; +import { padStart } from "../../lib/utils/utils.common"; + +export function isBrowser(): boolean { + return typeof window !== "undefined"; +} + +export function getUniqueName(prefix: string): string { + return `${prefix}${new Date().getTime()}${padStart( + Math.floor(Math.random() * 10000).toString(), + 5, + "00000" + )}`; +} + +export async function sleep(time: number): Promise { + return new Promise(resolve => { + setTimeout(resolve, time); + }); +} + +export function base64encode(content: string): string { + return isBrowser() ? btoa(content) : Buffer.from(content).toString("base64"); +} + +export function base64decode(encodedString: string): string { + return isBrowser() + ? atob(encodedString) + : Buffer.from(encodedString, "base64").toString(); +} + +export class ConsoleHttpPipelineLogger implements IHttpPipelineLogger { + constructor(public minimumLogLevel: HttpPipelineLogLevel) {} + public log(logLevel: HttpPipelineLogLevel, message: string): void { + const logMessage = `${new Date().toISOString()} ${ + HttpPipelineLogLevel[logLevel] + }: ${message}`; + switch (logLevel) { + case HttpPipelineLogLevel.ERROR: + // tslint:disable-next-line:no-console + console.error(logMessage); + break; + case HttpPipelineLogLevel.WARNING: + // tslint:disable-next-line:no-console + console.warn(logMessage); + break; + case HttpPipelineLogLevel.INFO: + // tslint:disable-next-line:no-console + console.log(logMessage); + break; + } + } +} + +export async function wait(time: number): Promise { + return new Promise(resolve => { + setTimeout(resolve, time); + }); +} diff --git a/queue/tsconfig.json b/queue/tsconfig.json new file mode 100644 index 0000000..3894242 --- /dev/null +++ b/queue/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "alwaysStrict": true, + "noImplicitAny": true, + "preserveConstEnums": true, + "sourceMap": true, + "newLine": "LF", + "target": "es5", + "moduleResolution": "node", + "noUnusedLocals": true, + "noUnusedParameters": true, + "strict": true, + "module": "esNext", + "outDir": "./dist-esm", + "declaration": true, + "declarationMap": true, + "importHelpers": true, + "declarationDir": "./typings", + "lib": ["dom", "es5", "es6", "es7", "esnext"], + "esModuleInterop": true + }, + "compileOnSave": true, + "exclude": ["node_modules"], + "include": ["./lib/**/*.ts", "./test/**/*.ts"] +} diff --git a/queue/tslint.json b/queue/tslint.json new file mode 100644 index 0000000..1a72ca1 --- /dev/null +++ b/queue/tslint.json @@ -0,0 +1,13 @@ +{ + "defaultSeverity": "error", + "extends": ["tslint:recommended"], + "jsRules": {}, + "rules": { + "trailing-comma": false, + "arrow-parens": false + }, + "rulesDirectory": [], + "linterOptions": { + "exclude": ["lib/generated/**"] + } +}