` which contains `messageId`, `popReceipt`, `timeNextVisible`, `insertionTime` and `expirationTime`. It can be passed to updateMessage and deleteMessage APIs.
+
+FILE
+* Returned content MD5 for range gets Files.
+* Fixed the issue that `useTransactionalMD5` didn't take effect for downloading a big file.
+* Added support for listing files and directories with prefix, refer to `FileService.listFilesAndDirectoriesSegmentedWithPrefix`.
+
+TABLE
+* Fixed the issue that response in incorrect for table batch operation when the error response item is not the first item in the responses.
+
+2016.11 Version 1.4.0
+
+ALL
+* Added `ENOTFOUND` for secondary endpoint and `ECONNREFUSED` to `RetryPolicyFilter`.
+* Added support for `text/html` error response body.
+
+BLOB
+* Fixed the issue that the ChunkAllocator maxCount is aligned with parallelOperationThreadCount.
+* Changed `/S` of SpeedSummary to `/s`.
+* Fixed the issue that `BlobService.createBlockBlobFromText` will hang when passed `null` or `undefined` `text` argument.
+* Fixed the issue that `BlobService.createBlockBlobFromText` will always set `content-type` to `text/plain`.
+
+QUEUE
+* Allowed `QueueService.peekMessages` against secondary endpoint.
+
+FILE
+* Fixed the issue that the ChunkAllocator maxCount is aligned with parallelOperationThreadCount.
+* Changed `/S` of SpeedSummary to `/s`.
+
+2016.10 Version 1.3.2
+
+BLOB
+* Prevent a blockId from being generated with a decimal point.
+
+2016.09 Version 1.3.1
+
+ALL
+* Improved the type script support.
+
+2016.08 Version 1.3.0
+
+ALL
+
+* Fixed the issue that retry filter will fail against storage emulator.
+* Fixed a hang issue of `StorageServiceClient` with retry policy filter set when retrying sending the request, the stream is not readable anymore.
+* Updated the default value of `CorsRule.ExposedHeaders`, `CorsRule.AllowedHeaders` to empty and `CorsRule.MaxAgeInSeconds` to `0` for `setServiceProperties` APIs of all services.
+* Fixed the issue that service SAS doesn't work if specifying the `AccessPolicy.Protocols`.
+
+BLOB
+* Added the API `BlobService.getPageRangesDiff` for getting the page ranges difference. Refer to https://msdn.microsoft.com/en-us/library/azure/mt736912.aspx for more detailed information.
+
+QUEUE
+* Updated the `QueueMessageResult.dequeueCount` from `string` to `number`.
+* Added the API `QueueService.getUrl` for getting the queue url.
+
+TABLE
+* Added the API `TableService.getUrl` for getting the table url.
+
+2016.07 Version 1.2.0
+
+ALL
+* Fixed the issue that metadata name will be converted to lower-case after retrieving back from the server. **Note** that this fix is only applicable for Node 0.12 or higher version.
+* Added support for EndpointSuffix for all service constructors.
+* Updated storage service version to 2015-12-11. Fore more information, please see - https://msdn.microsoft.com/en-us/library/azure/dd894041.aspx
+* Updated the `request` package to version 2.74.0 to address the security vulnerability - https://nodesecurity.io/advisories/130
+
+BLOB
+* Fixed the issue that the service error message will be written to the destination stream if getting error when downloading the blob to a stream/file.
+* Added `serverEncryped` property to `BlobResult` class which indicates if the blob data and application metadata are completely encrypted using the specified algorithm on the server.
+
+FILE
+* Fixed the issue that the service error message will be written to the destination stream if getting error when downloading the file to a stream/file.
+
+TABLE
+* The atom feed payload format is not supported anymore for table service APIs.
+
+2016.06 Version 1.1.0
+
+ALL
+* Fixed the issue that using SAS doesn't work against storage emulator.
+* Fixed the issue that the service SAS signature is incorrect when protocol parameter is specified.
+* Fixed the issue that the timeout query string should be in seconds instead of milliseconds.
+
+BLOB
+* Added parameter snapshotId to BlobService.getUrl function to support getting url of a specified snapshot.
+* Fixed the issue that the getUrl doesn't work against storage emulator.
+* Fixed the race issue that the _rangeList may be deleted before using it in the BlockRangeStream._getTypeList function.
+* Fixed the issue that downloading block blob with size bigger than 32MB will fail when using anonymous credential.
+* Added `CREATE` to `BlobUtilities.SharedAccessPermissions`.
+
+TABLE
+* Supported string type value for entity PartionKey and RowKey.
+* Supported implicit Edm type value for entity properties. The supported implicit Edm types including Int32, Double, Bool, DateTime and String.
+
+FILE
+* Fixed the issue that the getUrl doesn't work against storage emulator.
+* Added `CREATE` to `FileUtilities.SharedAccessPermissions`.
+
+2016.05 Version 1.0.1
+
+ALL
+* Fixed the issue that StorageServiceClient._normalizeError will throw exception on Node below v4 because string.startsWith is not available on Node below v4.
+
+2016.05 Version 1.0.0
+
+BLOB
+* The `blob` property of BlobResult has been renamed to `name` to keep consistent with other services API and the `listBlob` API.
+* Decoded the block name of LockListResult from base64 string to utf-8 string.
+
+QUEUE
+* The `encodeMessage` flag of QueueService has been replaced by `messageEncoder` which support `TextBase64QueueMessageEncoder`, `BinaryBase64QueueMessageEncoder`, `TextXmlQueueMessageEncoder` and custom implementation of QueueMessageEncoder.
+
+TABLE
+* Fixed the issue that loses the data type for Edm.Double value like: 1.0.
+* Fixed the issue that loses the data precision for Edm.Int64 value when it is outisde of the range (2^53 - 1) to -(2^53 - 1).
+
+2016.03 Version 0.10.0
+
+ALL
+* The `signedIdentifiers` parameter and result properties have been changed from array to hash map to avoid non unique signed identifier id.
+
+BLOB
+* Added 'COPY' to the BlobUtilities.BlobListingDetails to include copy information in the results.
+* Added 'bytesCopied' and 'totalBytes' to the blob result.
+* Added the blob result to the callback of BlobService.commitBlocks.
+* Moved the properties in the properties object of BlobResult and ContainerResult when listing blobs or containers to the result object.
+* Renamed the property names returned from listing blobs or containers to camelCase.
+* The `contentType`, `contentEncoding`, `contentLanguage`, `contentDisposition`, 'contentMD5' and `cacheControl` parameters and return values about the blob's content settings are grouped into a `contentSettings` sub property.
+* The `contentMD5` parameter to verify the integrity of the data during the transport is changed to `transactionalContentMD5`
+* The `copy*` return values are grouped into a `copy` sub property.
+* The `lease*` return values are grouped into a `lease` sub property.
+* The options.accessConditions parameter is changed to AccessConditions type.
+
+QUEUE
+* Renamed QueueResult.approximatemessagecount to camelCase and change its type to 'number.
+* Renamed the property names of QueueMessageResult to camelCase.
+* Renamed the parameter options.messagettl of the createMessage API to options.messageTimeToLive.
+* Updated the callback of the createMessage API from errorOrResult to errorOrResponse.
+* Removed peekOnly option from the options parameter of the getMessages API. To peek messages, use peekMessages instead.
+* Added getMessage and peekMessage API.
+
+FILE
+* Moved the properties in the properties object of FileResult and ShareResult when listing files or shares to the result object.
+* Renamed the property names returned from listing files or shares to camelCase.
+* Renamed the property names returned from getting share stats to camelCase.
+* The `contentType`, `contentEncoding`, `contentLanguage`, `contentDisposition`, 'contentMD5' and `cacheControl` parameters and return values about the blob's content settings are grouped into a `contentSettings` sub property.
+* The `contentMD5` parameter to verify the integrity of the data during the transport is changed to `transactionalContentMD5`
+* The `copy*` return values are grouped into a `copy` sub property.
+* Fixed the issue that SAS tokens created from table names with upper-case letters do not work.
+* The options.accessConditions parameter is changed to AccessConditions type.
+
+TABLE
+* Fixed the issue that getTableAcl returns empty array with signedIdentifier property.
+* Renamed the function updateEntity to replaceEntity.
+* Renamed TableUtilities.entityGenerator.Entity to EntityProperty.
+
+2016.03 Version 0.9.0
+
+ALL
+* Updated storage service version to 2015-04-05. Fore more information, please see - https://msdn.microsoft.com/en-us/library/azure/dd894041.aspx
+* Added support for Account SAS.
+* Added support for IPACL and Protocols options for service SAS.
+* Fixed the issue where the authentication may fail when a metadata key is in upper case.
+* Added 'nsp check' task for security vulnerability check.
+* Updated the dependency of the 'request' module to avoid the security vulnerability reported by the 'nsp' tool.
+
+BLOB
+* Added new permission 'ADD' for service SAS.
+
+FILE
+* Added support for metrics setting for service properties.
+
+2016.01 Version 0.8.0
+
+ALL
+* Preview release of the TypeScript definition file at "lib/azure-storage.d.ts".
+
+BLOB
+* Added the blob result to the callback of BlobService.commitBlocks.
+* Added the speed summary to the downloading APIs.
+
+2015.12 Version 0.7.0
+
+ALL
+* Fixed the typo in the function generateDevelopmentStorageCredentials.
+* Fixed the issue that the HTTP global agent setting is changed during parallel uploading and downloading and impacts on other Node.js applications.
+* Fixed the issue that the chunked stream writing methods do not accept string.
+* Fixed the issue that the request fails when the content-length is set to string '0' in the 'sendingRequestEvent' event handler.
+* Supported retry on XML parsing errors when the XML in the response body is corrupted.
+* Replaced the dependency "mime" to "browserify-mime" to work with Browserify.
+
+BLOB
+* Added an option to skip the blob or file size checking prior to the actual downloading.
+* Fixed the issue that it doesn't callback when loses the internet connection during uploading/uploading.
+* Fixed the issue that the local file cannot be removed in the callback when uploading a blob from a local file.
+* Fixed the issue that the stream length doesn't work when it is larger than 32MB in the createBlockBlobFromStream, createPageBlobFromStream, createAppendBlobFromStream and appendFromStream functions.
+* Fixed the issue that it doesn't return error in the page range validation when the size exceeds the limit.
+* Renamed the function AppendFromLocalFile to appendFromLocalFile.
+* Renamed the function AppendFromStream to appendFromStream.
+* Renamed the function AppendFromText to appendFromText.
+
+TABLE
+* Fixed the issue that listTablesSegmentedWithPrefix with maxResult option throws exception.
+
+2015.09 Version 0.6.0
+
+ALL
+* Fixed the MD5 mismatch issue in uploading a blob when running with Node.js v4.0 or io.js.
+
+BLOB
+* Fixed the issue that it doesn't prompt appropriate error message when the source URI is missing in BlobService.startCopyBlob().
+
+2015.08 Version 0.5.0
+
+ALL
+* Updated storage service version to 2015-02-21. For more information, please see - https://msdn.microsoft.com/en-us/library/azure/dd894041.aspx
+* Unified the function parameters for setting ACL of container, table, queue and share.
+* Renamed 'AccessPolicy.Permission' to 'AccessPolicy.Permissions' on the result object from get*Acl to match the property name on the signedIdentifier property passed to set*Acl calls.
+* Unified the name pattern of the http header constants.
+* Split the property parameters from the options parameter for setting properties of blob, share and file.
+* Updated the error message when an argument is in a wrong type while it requires a string.
+* Exported AccessCondition to generate an object that represents a condition.
+* Fixed an issue that the SAS in the SharedAccessSignature part of the connection string cannot start with '?'.
+* Deprecated the generateSharedAccessSignatureWithVersion() method in each service.
+
+BLOB
+* Supported operating against append blobs.
+* Fixed an issue that the file descriptor in the FileReadStream is not closed.
+
+QUEUE
+* Fixed an issue that options.messageText doesn't work in QueueService.updateMessage.
+
+2015.06 Version 0.4.5
+
+* Updated the dependency of the 'request' module to avoid the security vulnerability reported by the 'nsp' tool: (https://nodesecurity.io/advisories/qs_dos_extended_event_loop_blocking) and (https://nodesecurity.io/advisories/qs_dos_memory_exhaustion).
+* Included package validation in grunt tasks.
+
+2015.05 Version 0.4.4
+
+ALL
+* Updated the dependency of the 'validator' module to avoid the security vulnerability reported by the 'nsp' tool. (https://nodesecurity.io/advisories/validator-isurl-denial-of-service)
+* Updated the error message when an argument is in a wrong type while it requires a string.
+* Updated the grunt file to run test with mocha and generate jsDoc.
+
+BLOB
+* Fixed an issue that the metadata is duplicated when creating a page blob.
+* Fixed an issue that the metadata is duplicated when setting blob's metadata with metadata in the options.
+* Fixed an issue that cannot create an empty block blob with useTransactionalMD5 option.
+
+FILE
+* Fixed an issue that the result of file downloading contains wrong values for share, directory or file names.
+
+TABLE
+* Fixed an issue that it prompts "Cannot set property 'isSuccessful' of null" when TableService.createTableIfNotExists is called.
+
+2015.03 Version 0.4.3
+
+ALL
+* Fixed an issue that setting metadata keys are converted into lowercase. The metadata keys retrieved from the service will however still be converted into lowercase by the http component of Node.js.(https://github.com/joyent/node/issues/1954)
+* Included all storage error code strings in the error constants definition.
+* Documented the client request ID option in all APIs.
+
+BLOB
+* Supported listing blob virtual directories.
+* Fixed an issue that exception is thrown when downloading a blob larger than 32MB to a stream.
+* Fixed an issue that the process exits when the free memory is low.
+
+2014.12 Version 0.4.2
+
+ALL
+* Fixed an issue that batch operation could probably wait without callback.
+* Added the readable-stream module to adapt stream operations in both node 0.8 and node 0.10.
+* Supported nock in tests.
+
+BLOB
+* Supported trimming the default port of http or https when getting URL for the blob service.
+* Fixed an issue that the metadata is not populated when getting the blob to text.
+
+FILE
+* Supported trimming the default port of http or https when getting URL for the file service.
+
+2014.11.28 Version 0.4.1
+
+ALL
+* Fixed an issue where the request does not invoke the callback when the input stream ends with an 'end' event instead of a 'finish' event.
+* Fixed an issue where the request does not invoke the callback when the input stream ends with a 'close' event on Node 0.8.X.
+* Fixed an issue that the temporary files generated by unit tests are not cleaned up.
+* Fixed an issue that the unit tests may fail when the file generated by previous tests is not accessible temporarily.
+
+FILE
+* Added support to download a single file in parallel similar to upload. You can set ‘parallelOperationThreadCount’ option for api’s that download a file to indicate number of parallel operations to use for download.
+
+TABLE
+* Fixed an issue which caused invalid input errors when the partition key or the row key contains an apostrophe.
+
+2014.10.28 Version 0.4.0
+
+ALL
+* Provide an option to enable/disable nagling. Nagling is disabled by default. It can be enabled by setting options.useNagleAlgorithm to true.
+* Added batch operation callback in sequence mode.
+
+BLOB
+* Added support to download a single blob in parallel similar to upload. You can set ‘parallelOperationThreadCount’ option for api’s that download a blob to indicate number of parallel operations to use for download.
+* Added speed summary in blob downloading.
+
+FILE
+* Fixed an issue which caused an invalid resource name error when the directory name starts or ends with a '/'
+
+2014.08.20 Version 0.3.3
+
+BLOB
+* Fixed an issue where SAS tokens were being incorrectly generated for the root container and when the blob name required encoding.
+* Documented the 'parallelOperationThreadCount' option as input to various uploadBlob APIs.
+
+FILE
+* Fixed an issue where signing was incorrect when the URI contained '.' or '..'.
+* Fixed an issue where "getURI" was requiring a file parameter, although the parameter should be optional.
+
+2014.07.25 Version 0.3.2
+
+ALL
+* Fixed an issue which prevented transient server errors like ECONNRESET, ESOCKETTIMEDOUT and ETIMEDOUT from being retried.
+
+BLOB
+* Fixed an issue which caused a reference error in blobs due to 'err' not being defined.
+
+2014.07.22 Version 0.3.1
+
+ALL
+* Fixed an issue which failed to validate special names for containers and tables.
+* Exposed the Validation utility methods so users can use it to validate resource names.
+
+BLOB
+* Fixed an issue which caused failures when an error was encountered while uploading big blobs.
+
+2014.07.07 Version 0.3.0
+
+BLOB
+* Fixed an issue which failed to return single item blocklists while doing listBlocks.
+
+FILE
+* Added File Service support. The File Service and the associated APIs are in preview.
+
+2014.07.01 Version 0.2.1
+
+ALL
+* Fixed an issue with casing which caused the module to fail on linux machines.
+
+BLOB
+* Fixed an issue which failed to upload an empty blob for empty block blob files uploaded using createBlockBlobFromFile when retry policies were used.
+
+2014.06.16 Version 0.2.0
+
+ALL
+* Updated storage service version to 2014-02-14. The SAS tokens generated will therefore contain a signed version of 2014-02-14 and all the requests using SAS credentials have the api-version query parameter appended to the URI.
+
+2014.06.12 Version 0.1.0
+
+ALL
+* The package has been renamed to azure-storage.
+* There is no separate azure-common sub-package. Everything is condensed into a single package called azure-storage.
+* azure.create*Service supports the following configurations:
+ * create*Service(connection string)
+ * create*Service(account name, account key)
+ * create*Service(storage host, sasToken)
+* Added the ability to choose which SAS Version to use when generating Shared Access Signatures (either the 2012-02-12 or 2013-08-15 versions).
+* Host can be given as either an object with primaryHost and secondaryHost or as a string representing the primary.
+* The order credentials are assessed is consistent: If parameters are passed in, they and they alone are honored. There is no mixing (ex, if users pass in host, they won't get the access key from your env var). If no parameters are passed in, the env vars are used. Within both those strategies, the order of evaluation is emulator (in the case of EMULATED env var only), connection string, account/key or SAS, anonymous. If account/key and SAS are passed in, an error is thrown indicating the credentials are invalid.
+* Removed the ability to create a storage service from a config file.
+* azure.create*Service supports secondaryHost only, but either primaryHost or secondaryHost must be provided.
+* Storage service client constructors take the sasToken rather than a credentials object, meaning that the SharedAccessSignature class no longer needs to be used by consumers.
+* Ensure request is always built/signed for every retry attempt.
+* Custom retry policies should implement the shouldRetry method and return an object with the retryInterval and retryable information in it. Optionally, they can also set the locationMode and targetLocation to which the request should be sent.
+* Implemented RA-GRS support. For more information on this, please see - http://blogs.msdn.com/b/windowsazurestorage/archive/2013/12/04/introducing-read-access-geo-replicated-storage-ra-grs-for-windows-azure-storage.aspx
+* Service properties updated: replaced metrics with hour metrics and minute metrics, added cors support, added defaults if properties are unspecified to reduce invalid xml exceptions.
+* Added maximum execution time, settable for all requests via {blob|queue|table}service.defaultMaximumExecutionTime or for an individual request via options.maximumExecutionTime. This applies to all requests except blob downloads.
+* The blob, queue and table services no longer set/modify any values within the options object optionally passed in by the user for every API.
+* Fixed an issue where null, empty and white-space only metadata header values were allowed.
+* "timeout" query parameter will not be sent to the server if not set by the user. In order to set the timeout per API, please use options.timeoutIntervalInMs. To set it for all requests made via a particular service, please use {blob|queue|table}Service.defaultTimeoutIntervalInMs.
+* ECONNRESET is handled in the retry policy filter.
+* DevStore with secondary access is supported.
+* Set*Acl takes signed identifiers as a parameter - before it was in options.
+* GenerateSharedAccessSignature() produces a query string rather than an object.
+* The SharedKey class has the methods to create shared access signatures. These should not be in the SharedAccessSignature class because one can only create a SAS if they have the account/key.
+* The service client no longer evaluates the port and protocol set on it. Before, if storageserviceclient.host was called and port and protocol had been changed after host was set, host would be incorrect.
+* Removed SharedKeyLite and SharedKeyLiteTable in favor of SharedKey and SharedKeyTable which were already the defaults.
+* Added separate utility files for Blob, Queue, Table, and Storage. These contain useful enums that were previously found in a single Constants file as well as new utility functions. The old Constants file will mostly include internal-use constants.
+
+BLOB
+* createBlobServiceWithSas has been provided to create a blobService to use with a Shared Access Signature. Users can create a blobService using azure.createBlobServiceWithSas(host, sasToken).
+* Anonymous access for the blob service is supported.
+* Added support for 2013-08-15 Blob SAS changes.
+* Renamed listBlobs to listBlobsSegmented and added listBlobsSegmentedWithPrefix. listBlobsSegmented takes in currentToken and listBlobsSegmentedWithPrefix takes in prefix and currentToken along with other parameters. Please look at the documentation of these APIs for a list of parameters that users can set on the options object. These APIs return only error, result and response. The result contains entries which is a list of blobs and a continuation token for successive listing operations.
+* Renamed copyBlob to startCopyBlob.
+* Renamed putBlockBlobFromStream to _putBlockBlobFromStream and putBlockBlobFromFile to _putBlockBlobFromFile. These are internal methods and should not be called by users directly. Please use createBlockBlobFromStream and createBlockBlobFromFile.
+* Renamed page methods: listBlobRegions to listPageRanges, createBlobPagesFromText to createPagesFromText, clearBlobPages to clearPageRanges.
+* Renamed block methods: createBlobBlockFromStream to createBlockFromStream, createBlobBlockFromText to createBlockFromText, commitBlobBlocks to commitBlocks, listBlobBlocks to listBlocks.
+* BlobService lease methods also work with container leases, simply specify null for the blob parameter.
+* Added changeLease method to modify the lease ID of an active lease.
+* Fixed lease issues, break lease allows a leaseBreakPeriod of 0, lease time header is returned as an int rather than a string.
+* Added snapshot delete options: when deleting a blob with snapshots, users can decide to delete blob and snapshots or just snapshots. The options are provided in BlobUtilities.SnapshotDeleteOptions.*.
+* deleteBlob callback does not return isSuccessful.
+* Added does{Container|Blob}Exist methods in blobservice that can be used to determine if a particular container or blob exists.
+* Added delete{Container|Blob}IfExists methods in blobservice that can be used to delete a container or a blob only when they exist.
+* Added ContentMD5 validation for blob downloads. This is turned on by default for all block blob downloads and all page blob range downloads as long as the range is less than 4MB. In order to turn this off, set options.disableContentMD5Validation to true explicitly.
+* x-ms-range-get-content-md5 is set internally by the library and users do not have to specify it in the options.
+* Removed the option of doing range downloads while downloading a blob to text.
+* Added sequence number support for page blobs. Users can set the sequence number of a page blob using blobService.setPageBlobSequenceNumber and manage concurrency issues using x-ms-if-sequence-number-le, x-ms-if-sequence-number-lt and x-ms-if-sequence-number-eq. Please see http://msdn.microsoft.com/en-us/library/azure/ee691975.aspx for more details about using sequence numbers.
+* Removed createBlob API. Please use createPageBlob and createBlockBlob* APIs to create the respective blobs.
+* Renamed createPagesFromText to _createPagesFromText. This is an internal method and should not be called by users directly.
+* Added resizePageBlob that can be used to resize a page blob.
+* createPageBlob takes in the blob's sequence number using options.sequenceNumber.
+* All the BlobService APIs that took cacheControl/cacheControlHeader, contentType/contentTypeHeader, contentEncoding/contentEncodingHeader, contentLanguage/contentLanguageHeader, contentMD5/contentMD5Header in options only take cacheControl, contentType, contentEncoding, contentLanguage and contentMD5. These are the values that will be set on the blob at the server.
+* createPagesFromStream takes in the following 2 options - useTransactionalMD5 to calculate and send/validate content MD5 for each transaction and contentMD5 which is an optional hash value. When contentMD5 is provided, the client library uses that instead of trying to calculate it based on the data being uploaded.
+* createBlockBlobFromText, createBlockFromStream and createBlockFromText allows users to set useTransactionalMD5 on options to calculate and send/validate content MD5 for each transaction.
+* Added createWriteStreamToBlockBlob, createWriteStreamToNewPageBlob and createWriteStreamToExistingPageBlob that provide a stream for writing to the blob.
+* Added createReadStream that provides a stream for reading from the blob.
+* blobService can have a default parallelOperationThreadCount which specifies the number of parallel upload operations that may be performed when uploading a blob that is greater than the value specified by singleBlobPutUploadThresholdInBytes. This value can be set using blobService.parallelOperationThreadCount. The default value set on blobService is 1.
+* createBlockBlobFromText supports text Buffers in addition to strings.
+* createBlockBlobFromText will throw an error if the uploaded content exceeds 64MB.
+* BlobService getBlobUrl has been renamed to getUrl as it can also produce container urls. It can no longer create a SAS token (it used to take sharedAccessPolicy) but can take a sasToken produced by the generateSharedAccessSignature method and produce a url with that.
+
+QUEUE
+* Added Shared Access Signatures for queues. createQueueServiceWithSas has been provided to create a queueService to use with a Shared Access Signature. Users can create a queueService using azure.createQueueServiceWithSas(host, sasToken).
+* Renamed listQueues to listQueuesSegmented and added listQueuesSegmentedWithPrefix. listQueuesSegmented takes in currentToken and listQueuesSegmentedWithPrefix takes in prefix and currentToken along with other parameters. Please look at the documentation of these APIs for a list of parameters that users can set on the options object. These APIs return only error, result and response. The result contains entries which is a list of queues and a continuation token for successive listing operations.
+* deleteQueue and deleteMessage callbacks do not return isSuccessful.
+* Added an option in the queue service to turn base 64 encoding off.
+
+TABLE
+* Added Shared Access Signatures for tables. createTableServiceWithSas has been provided to create a tableService to use with a Shared Access Signature. Users can create a tableService using azure.createTableServiceWithSas(host, sasToken).
+* Added JSON support for tables and removed AtomPub. For the different flavours of JSON supported, please see - http://blogs.msdn.com/b/windowsazurestorage/archive/2013/12/05/windows-azure-tables-introducing-json.aspx.
+* Renamed queryTables to listTablesSegmented and added listTablesSegmentedWithPrefix. listTablesSegmented takes in currentToken and listTablesSegmentedWithPrefix takes in prefix and currentToken along with options and callback. Please look at the documentation of these APIs for a list of parameters that users can set on the options object. These APIs return only error, result and response. The result contains entries which is a list of tables and a continuation token for successive listing operations.
+* deleteTable and deleteEntity callbacks do not return isSuccessful.
+* queryEntities in TableService returns 3 parameters instead of 4: the entities and queryResultContinuation parameters are returned within a queryResult object.
+* Added support for disabling echo content in inserts. By default, inserts do not echo content.
+* Changed table error parsing so that the code string and message string are directly accessible from the error object.
+* Removed the getTable method; doesTableExist works similarly.
+* createTable does not request content back from the service, but still returns an object containing the TableName.
+* Renamed queryEntity in TableService to retrieveEntity.
+* Modified how batches work. Instead of turning the service batch mode on/off, a batch is a separate entity like query. Batches are constructed and then executed.
+* queryEntities in TableService requires a continuation token.
+* TableService updateEntity, mergeEntity and deleteEntity do not take a checkEtag option. The entity's etag is sent if it exists, otherwise * is sent.
+* retrieveEntity and queryEntities accept empty partition and row keys.
+* Added entity-property-creation helper methods. Users can use the entityGenerator provided in TableUtilities and create entity properties as follows:
+ var entGen = TableUtilities.entityGenerator;
+ var entity = { PartitionKey: entGen.String('part2'),
+ RowKey: entGen.String('row1'),
+ boolValueTrue: entGen.Boolean(true),
+ boolValueFalse: entGen.Boolean(false),
+ intValue: entGen.Int32(42),
+ dateValue: entGen.DateTime(new Date(Date.UTC(2011, 10, 25))),
+ complexDateValue: entGen.DateTime(new Date(Date.UTC(2013, 02, 16, 01, 46, 20)))
+ };
+* Removed TableQuery whereKeys method. Instead of tableQuery.whereKeys, tableService.retrieveEntity should be used.
+* Removed TableQuery whereNextKeys method. Instead of tableQuery.whereNextKeys, tableService.queryEntities takes currentToken which can be retrieved from a previous queryEntities call in results.
+* Removed TableQuery from method. Instead of tableQuery.from, tableService.queryEntities takes table and tableQuery may be null to represent retrieving all entities in the table.
+* TableQuery select is an instance method for consistency with top and where. Instead of TableQuery.select('foo'), use new TableQuery().select('foo').
+* TableQuery provides helper methods to create filter strings to use with the where clause for a query. Query strings may also include type specifiers where necessary.
+ For example, to query on a long value, users could do the following:
+ var tableQuery = new TableQuery().where(TableQuery.int64Filter('Int64Field', TableUtilities.QueryComparisons.EQUAL, '4294967296'));
+ OR
+ var tableQuery = new TableQuery().where('Int64Field == ?int64?', '4294967296');
+
+2013.01.15 Version 0.8.0
+* Added the Preview Service Management libraries as separate modules
+* Added ability to consume PEM files directly from the Service Management libraries
+* Added support for createOrUpdate and createRegistrationId in the Notification Hubs libraries
+
+2013.01.10 Version 0.7.19
+* Lock validator version
+
+2013.11.27 Version 0.7.18
+* Lock xmlbuilder version
+
+2013.11.5 Version 0.7.17
+* Added getBlob and createBlob operations that support stream piping
+* Added compute, management, network, serviceBus, sql, storage management, store and subscription preview wrappers
+* Multiple bugfixes
+
+2013.10.16 Version 0.7.16
+* Improved API documentation
+* Updated Virtual Machines API to 2013-06-01
+* Added website management preview wrappers
+* Multiple bugfixes
+
+2013.08.19 Version 0.7.15
+* Multiple storage fixes
+* Fix issue with Notification Hubs template message sending
+
+2013.08.12 Version 0.7.14
+* Multiple storage fixes
+* Documentation improvements
+* Added support for large blobs upload / download
+
+2013.08.08 Version 0.7.13
+* Lock request version
+
+2013.07.29 Version 0.7.12
+* Added MPNS support
+* Added Service management vnet operations support
+
+2013.07.10 Version 0.7.11
+* Hooked up new configuration system to storage APIs
+* Support for AZURE_STORAGE_CONNECTION_STRING environment variable
+* Included API for websites management
+* Fixed UTF-8 support in table batch submit
+
+2013.06.26 Version 0.7.10
+* Various fixes in storage APIs
+
+2013.06.19 Version 0.7.9
+* First part of new SDK configuration system
+* Support for AZURE_SERVICEBUS_CONNECTION_STRING environment variable
+* Updated SAS generation logic to include version number
+* Infrastructure support for creating passwordless VMs
+
+2013.06.13 Version 0.7.8
+* Updates to HDInsight operations
+
+2013.06.06 Version 0.7.7
+* Added support for Android notification through Service Bus Notification Hubs
+* Support prefixes when listing tables
+* Support '$logs' as a valid blob container name to support reading diagnostic information
+* Fix for network configuration serialization for subnets
+
+2013.05.30 Version 0.7.6
+* Added list, delete and create cluster operations for HD Insight.
+
+2013.05.15 Version 0.7.5
+* Fixed registration hubs issue with requiring access key when shared key was provided.
+* Fixed registration hubs issue with listByTag, Channel and device token
+
+2013.05.09 Version 0.7.4
+* Fixed encoding issue with partition and row keys in table storage query
+
+2013.05.01 Version 0.7.3
+* Fixed issue #680: BlobService.getBlobUrl puts permissions in SAS url even if not given
+* Changes to test suite & sdk to run in other environments
+* Notification hubs registrations
+* Support in ServiceManagementClient for role reboot and reimage
+
+2013.04.05 Version 0.7.2
+* Removing workaround for SSL issue and forcing node version to be outside the > 0.8 && < 0.10.3 range where the issue occurs
+
+2013.04.03 Version 0.7.1
+* Adding (limited) support for node 0.10
+* Fixing issue regarding registering providers when using websites or mobiles services
+
+2013.03.25 Version 0.7.0
+* Breaking change: Primitive types will be stored for table storage.
+* Adding support for creating and deleting affinity groups
+* Replacing http-mock by nock and making all tests use it by default
+* Adding notification hubs messages for WNS and APNS
+* Add Strict SSL validation for server certificates
+* Add support for creating subscriptions that expire
+
+2013.03.12 Version 0.6.11
+* Added constraint to package.json to restrict to node versions < 0.9.
+
+2013.02.11 Version 0.6.10
+* Added helper date.* functions for generating SAS expirations (secondsFromNow, minutesFromNow, hoursFromNow, daysFromNow)
+* Added SQL classes for managing SQL Servers, Databases and Firewall rules
+* Updating to use latest xml2js
+
+2012.12.12 Version 0.6.9
+* Exporting WebResource, Client classes from package to support CLI.
+* Install message updated to remind users the CLI is now a separate package.
+
+2012.11.20 Version 0.6.8
+ * CLI functionality has been pulled out into a new "azure-cli" module. See https://github.com/WindowsAzure/azure-sdk-tools-xplat for details.
+ * Add support for sb: in ServiceBus connection strings.
+ * Add functions to ServiceManagement for managing storage accounts.
+ * Merged #314 from @smarx for allowing empty partition keys on the client.
+ * Merged #447 from @anodejs for array enumeration and exception on batch response.
+ * Various other fixes
+
+2012.10.15 Version 0.6.7
+ * Adding connection strings support for storage and service bus
+ * Fixing issue with EMULATED and explicit variables making the later more relevant
+ * Adding Github support
+ * Adding website application settings support
+
+2012.10.12 Version 0.6.6
+ * Using fixed version of commander.js to avoid bug in commander.js 1.0.5
+
+2012.10.01 Version 0.6.5
+ * Bugfixing
+
+2012.09.18 Version 0.6.4
+ * Multiple Bugfixes around blob streaming
+
+2012.09.09 Version 0.6.3
+ * Fixing issue with xml2js
+
+2012.08.15 Version 0.6.2
+ * Multiple Bugfixes
+
+2012.07.02 Version 0.6.1
+ * Multiple Bugfixes
+ * Adding subscription setting and listing functionality.
+
+2012.06.06 Version 0.6.0
+ * Adding CLI tool
+ * Multiple Bugfixes
+
+2012.04.19 Version 0.5.3
+ * Service Runtime Wrappers
+ * Multiple Bugfixes
+ * Unit tests converted to mocha and code coverage made easy through JSCoverage
+
+2012.02.10 Version 0.5.2
+ * Service Bus Wrappers
+ * Storage Services UT run against a mock server.
+ * Node.exe version requirement lowered to raise compatibility.
+ * Multiple Bugfixes
+
+2011.12.14 Version 0.5.1
+ * Multiple bug fixes
+
+2011.12.09 Version 0.5.0
+ * Initial Release
diff --git a/src/node_modules/azure-storage/ISSUE_TEMPLATE.md b/src/node_modules/azure-storage/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..dba6d32
--- /dev/null
+++ b/src/node_modules/azure-storage/ISSUE_TEMPLATE.md
@@ -0,0 +1,16 @@
+### Which service(blob, file, queue, table) does this issue concern?
+
+
+### Which version of the SDK was used?
+
+
+### What's the Node.js/Browser version?
+
+
+### What problem was encountered?
+
+
+### Steps to reproduce the issue?
+
+
+### Have you found a mitigation/solution?
diff --git a/src/node_modules/azure-storage/LICENSE.txt b/src/node_modules/azure-storage/LICENSE.txt
new file mode 100644
index 0000000..21254fc
--- /dev/null
+++ b/src/node_modules/azure-storage/LICENSE.txt
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/README.md b/src/node_modules/azure-storage/README.md
new file mode 100644
index 0000000..3cd96db
--- /dev/null
+++ b/src/node_modules/azure-storage/README.md
@@ -0,0 +1,560 @@
+# Microsoft Azure Storage SDK for Node.js and JavaScript for Browsers
+
+[![NPM version](https://badge.fury.io/js/azure-storage.svg)](http://badge.fury.io/js/azure-storage)
+
+* Master [![Build Status](https://travis-ci.org/Azure/azure-storage-node.svg?branch=master)](https://travis-ci.org/Azure/azure-storage-node/branches) [![Coverage Status](https://coveralls.io/repos/Azure/azure-storage-node/badge.svg?branch=master&service=github)](https://coveralls.io/github/Azure/azure-storage-node?branch=master)
+* Dev [![Build Status](https://travis-ci.org/Azure/azure-storage-node.svg?branch=dev)](https://travis-ci.org/Azure/azure-storage-node/branches) [![Coverage Status](https://coveralls.io/repos/Azure/azure-storage-node/badge.svg?branch=dev&service=github)](https://coveralls.io/github/Azure/azure-storage-node?branch=dev)
+
+This project provides a Node.js package and a browser compatible [JavaScript Client Library](https://github.com/Azure/azure-storage-node#azure-storage-javascript-client-library-for-browsers) that makes it easy to consume and manage Microsoft Azure Storage Services.
+
+> This README page is a reference to the SDK v2. For the new SDK v10, go to [Storage SDK v10 for JavaScript](https://github.com/Azure/azure-storage-js).
+
+| SDK Name | Version | Description | NPM/API Reference Links |
+|------------------------------------------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Storage SDK v10 for JavaScript](https://github.com/Azure/azure-storage-js) | v10 | The next generation Storage SDK (Blob/Queue/File, async and promise support) | [NPM](https://www.npmjs.com/package/@azure/storage-blob) - [Reference](https://docs.microsoft.com/en-us/javascript/api/overview/azure/storage/client?view=azure-node-preview) |
+| [Storage SDK v2 for JavaScript](https://github.com/Azure/azure-storage-node) | v2 | Legacy Storage SDK in this repository (Blob/Queue/File/Table, callback style) | [NPM](https://www.npmjs.com/package/azure-storage) - [Reference](https://docs.microsoft.com/en-us/javascript/api/azure-storage/?view=azure-node-latest) |
+| [Azure Management SDKs for JavaScript](https://github.com/Azure/azure-sdk-for-node) | v2 | Management SDKs including Storage Resource Provider APIs | [NPM](https://www.npmjs.com/package/azure) - [Reference](https://github.com/Azure/azure-sdk-for-node#documentation) |
+
+# Features
+
+- Blobs
+ - Create/Delete Containers
+ - Create/Read/Update/Delete Blobs
+- Tables
+ - Create/Delete Tables
+ - Query/Create/Read/Update/Delete Entities
+- Files
+ - Create/Delete Shares
+ - Create/Delete Directories
+ - Create/Read/Update/Delete Files
+- Queues
+ - Create/Delete Queues
+ - Insert/Peek Queue Messages
+ - Advanced Queue Operations
+- Service Properties
+ - Get Service Properties
+ - Set Service Properties
+
+Please check details on API reference documents:
+
+* [Microsoft official API document on docs.microsoft.com](https://docs.microsoft.com/en-us/javascript/api/azure-storage/?view=azure-node-latest)
+* [Generated API references on GitHub pages](http://azure.github.io/azure-storage-node)
+
+# Getting Started
+
+## Install
+
+```shell
+npm install azure-storage
+```
+
+## Usage
+
+```Javascript
+var azure = require('azure-storage');
+```
+
+When using the Storage SDK, you must provide connection information for the storage account to use. This can be provided using:
+
+* Environment variables - **AZURE_STORAGE_ACCOUNT** and **AZURE_STORAGE_ACCESS_KEY**, or **AZURE_STORAGE_CONNECTION_STRING**.
+
+* Constructors - For example, `var tableSvc = azure.createTableService(accountName, accountKey);`
+
+### Blob Storage
+
+The **createContainerIfNotExists** method can be used to create a
+container in which to store a blob:
+
+```Javascript
+var azure = require('azure-storage');
+var blobService = azure.createBlobService();
+blobService.createContainerIfNotExists('taskcontainer', {
+ publicAccessLevel: 'blob'
+}, function(error, result, response) {
+ if (!error) {
+ // if result = true, container was created.
+ // if result = false, container already existed.
+ }
+});
+```
+
+To upload a file (assuming it is called task1-upload.txt and it is placed in the same folder as the script below), the method **createBlockBlobFromLocalFile** can be used.
+
+```Javascript
+var azure = require('azure-storage');
+var blobService = azure.createBlobService();
+
+blobService.createBlockBlobFromLocalFile('mycontainer', 'taskblob', 'task1-upload.txt', function(error, result, response) {
+ if (!error) {
+ // file uploaded
+ }
+});
+```
+
+
+For page blobs, use **createPageBlobFromLocalFile**. There are other methods for uploading blobs also, such as **createBlockBlobFromText** or **createPageBlobFromStream**.
+
+There are also several ways to download block and page blobs. For example, **getBlobToStream** downloads the blob to a stream:
+
+```Javascript
+var blobService = azure.createBlobService();
+var fs = require('fs');
+blobService.getBlobToStream('mycontainer', 'taskblob', fs.createWriteStream('output.txt'), function(error, result, response) {
+ if (!error) {
+ // blob retrieved
+ }
+});
+```
+
+To create a Shared Access Signature (SAS), use the **generateSharedAccessSignature** method. Additionally you can use the **date** helper functions to easily create a SAS that expires at some point relative to the current time.
+
+```Javascript
+var azure = require('azure-storage');
+var blobService = azure.createBlobService();
+
+var startDate = new Date();
+var expiryDate = new Date(startDate);
+expiryDate.setMinutes(startDate.getMinutes() + 100);
+startDate.setMinutes(startDate.getMinutes() - 100);
+
+var sharedAccessPolicy = {
+ AccessPolicy: {
+ Permissions: azure.BlobUtilities.SharedAccessPermissions.READ,
+ Start: startDate,
+ Expiry: expiryDate
+ }
+};
+
+var token = blobService.generateSharedAccessSignature(containerName, blobName, sharedAccessPolicy);
+var sasUrl = blobService.getUrl(containerName, blobName, token);
+```
+
+### Table Storage
+
+To ensure a table exists, call **createTableIfNotExists**:
+
+```Javascript
+var azure = require('azure-storage');
+var tableService = azure.createTableService();
+tableService.createTableIfNotExists('mytable', function(error, result, response) {
+ if (!error) {
+ // result contains true if created; false if already exists
+ }
+});
+```
+A new entity can be added by calling **insertEntity** or **insertOrReplaceEntity**:
+
+```Javascript
+var azure = require('azure-storage');
+var tableService = azure.createTableService();
+var entGen = azure.TableUtilities.entityGenerator;
+var entity = {
+ PartitionKey: entGen.String('part2'),
+ RowKey: entGen.String('row1'),
+ boolValueTrue: entGen.Boolean(true),
+ boolValueFalse: entGen.Boolean(false),
+ intValue: entGen.Int32(42),
+ dateValue: entGen.DateTime(new Date(Date.UTC(2011, 10, 25))),
+ complexDateValue: entGen.DateTime(new Date(Date.UTC(2013, 02, 16, 01, 46, 20)))
+};
+tableService.insertEntity('mytable', entity, function(error, result, response) {
+ if (!error) {
+ // result contains the ETag for the new entity
+ }
+});
+```
+
+
+Instead of creating entities manually, you can use **entityGenerator**:
+
+```Javascript
+var azure = require('azure-storage');
+var entGen = azure.TableUtilities.entityGenerator;
+var task = {
+ PartitionKey: entGen.String('hometasks'),
+ RowKey: entGen.String('1'),
+ description: entGen.String('take out the trash'),
+ dueDate: entGen.DateTime(new Date(Date.UTC(2015, 6, 20)))
+};
+```
+
+The method **retrieveEntity** can then be used to fetch the entity that was just inserted:
+
+```Javascript
+var azure = require('azure-storage');
+var tableService = azure.createTableService();
+tableService.retrieveEntity('mytable', 'part2', 'row1', function(error, result, response) {
+ if (!error) {
+ // result contains the entity
+ }
+});
+```
+
+The method **replaceEntity** or **insertOrReplaceEntity** can be called to update/edit an existing entry. In the following example we assume that an entity `'part2', 'row1'` with a field `'taskDone'` set to `false` already exists.
+
+```Javascript
+var azure = require('azure-storage');
+var tableService = azure.createTableService();
+var entity = {
+ PartitionKey: entGen.String('part2'),
+ RowKey: entGen.String('row1'),
+ taskDone: entGen.Boolean(true),
+};
+
+tableService.insertOrReplaceEntity('mytable', entity, function(error, result, response) {
+ if (!error) {
+ // result contains the entity with field 'taskDone' set to `true`
+ }
+});
+```
+
+Use **TableQuery** to build complex queries:
+
+```Javascript
+var azure = require('azure-storage');
+var tableService = azure.createTableService();
+var query = new azure.TableQuery()
+ .top(5)
+ .where('PartitionKey eq ?', 'part2');
+
+tableService.queryEntities('mytable', query, null, function(error, result, response) {
+ if (!error) {
+ // result.entries contains entities matching the query
+ }
+});
+```
+
+### Queue Storage
+
+The **createQueueIfNotExists** method can be used to ensure a queue exists:
+
+```Javascript
+var azure = require('azure-storage');
+var queueService = azure.createQueueService();
+queueService.createQueueIfNotExists('taskqueue', function(error) {
+ if (!error) {
+ // Queue exists
+ }
+});
+```
+
+The **createMessage** method can then be called to insert the message into the queue:
+
+```Javascript
+var queueService = azure.createQueueService();
+queueService.createMessage('taskqueue', 'Hello world!', function(error) {
+ if (!error) {
+ // Message inserted
+ }
+});
+```
+
+It is then possible to call the **getMessage** method, process the message and then call **deleteMessage** inside the callback. This two-step process ensures messages don't get lost when they are removed from the queue.
+
+```Javascript
+var queueService = azure.createQueueService(),
+ queueName = 'taskqueue';
+queueService.getMessages(queueName, function(error, serverMessages) {
+ if (!error) {
+ // Process the message in less than 30 seconds, the message
+ // text is available in serverMessages[0].messageText
+
+ queueService.deleteMessage(queueName, serverMessages[0].messageId, serverMessages[0].popReceipt, function(error) {
+ if (!error) {
+ // Message deleted
+ }
+ });
+ }
+});
+```
+
+### File Storage
+
+The **createShareIfNotExists** method can be used to create a
+share in which to store a file or a directory of files:
+
+```Javascript
+var azure = require('azure-storage');
+var fileService = azure.createFileService();
+fileService.createShareIfNotExists('taskshare', function(error, result, response) {
+ if (!error) {
+ // if result = true, share was created.
+ // if result = false, share already existed.
+ }
+});
+```
+
+To create a directory, the method **createDirectoryIfNotExists** can be used.
+
+```Javascript
+var azure = require('azure-storage');
+var fileService = azure.createFileService();
+
+fileService.createDirectoryIfNotExists('taskshare', 'taskdirectory', function(error, result, response) {
+ if (!error) {
+ // if result.created = true, share was created.
+ // if result.created = false, share already existed.
+ }
+});
+```
+
+To upload a file (assuming it is called task1-upload.txt and it is placed in the same folder as the script below), the method **createFileFromLocalFile** can be used.
+
+```Javascript
+var azure = require('azure-storage');
+var fileService = azure.createFileService();
+
+fileService.createFileFromLocalFile('taskshare', 'taskdirectory', 'taskfile', 'task1-upload.txt', function(error, result, response) {
+ if (!error) {
+ // file uploaded
+ }
+});
+```
+
+To upload a file from a stream, the method **createFileFromStream** can be used. The var `myFileBuffer` in the script below is a native Node Buffer, or ArrayBuffer object if within a browser environment.
+
+```Javascript
+ var stream = require('stream');
+ var azure = require('azure-storage');
+ var fileService = azure.createFileService();
+
+ var fileStream = new stream.Readable();
+ fileStream.push(myFileBuffer);
+ fileStream.push(null);
+
+ fileService.createFileFromStream('taskshare', 'taskdirectory', 'taskfile', fileStream, myFileBuffer.length, function(error, result, response) {
+ if (!error) {
+ // file uploaded
+ }
+ });
+```
+
+To create a file from a text string, the method **createFileFromText** can be used. A Node Buffer or ArrayBuffer object containing the text can also be supplied.
+
+```Javascript
+ var azure = require('azure-storage');
+ var fileService = azure.createFileService();
+
+ var text = 'Hello World!';
+
+ fileService.createFileFromText('taskshare', 'taskdirectory', 'taskfile', text, function(error, result, response) {
+ if (!error) {
+ // file created
+ }
+ });
+```
+
+There are also several ways to download files. For example, **getFileToStream** downloads the file to a stream:
+
+```Javascript
+var fileService = azure.createFileService();
+var fs = require('fs');
+fileService.getFileToStream('taskshare', 'taskdirectory', 'taskfile', fs.createWriteStream('output.txt'), function(error, result, response) {
+ if (!error) {
+ // file retrieved
+ }
+});
+```
+
+### Service Properties
+
+The **getServiceProperties** method can be used to fetch the logging, metrics and CORS settings on your storage account:
+
+```Javascript
+var azure = require('azure-storage');
+var blobService = azure.createBlobService();
+
+blobService.getServiceProperties(function(error, result, response) {
+ if (!error) {
+ var serviceProperties = result;
+ // properties are fetched
+ }
+});
+```
+
+The **setServiceProperties** method can be used to modify the logging, metrics and CORS settings on your storage account:
+
+```Javascript
+var azure = require('azure-storage');
+var blobService = azure.createBlobService();
+
+var serviceProperties = generateServiceProperties();
+
+blobService.setServiceProperties(serviceProperties, function(error, result, response) {
+ if (!error) {
+ // properties are set
+ }
+});
+
+function generateServiceProperties() {
+ return serviceProperties = {
+ Logging: {
+ Version: '1.0',
+ Delete: true,
+ Read: true,
+ Write: true,
+ RetentionPolicy: {
+ Enabled: true,
+ Days: 10,
+ },
+ },
+ HourMetrics: {
+ Version: '1.0',
+ Enabled: true,
+ IncludeAPIs: true,
+ RetentionPolicy: {
+ Enabled: true,
+ Days: 10,
+ },
+ },
+ MinuteMetrics: {
+ Version: '1.0',
+ Enabled: true,
+ IncludeAPIs: true,
+ RetentionPolicy: {
+ Enabled: true,
+ Days: 10,
+ },
+ },
+ Cors: {
+ CorsRule: [
+ {
+ AllowedOrigins: ['www.azure.com', 'www.microsoft.com'],
+ AllowedMethods: ['GET', 'PUT'],
+ AllowedHeaders: ['x-ms-meta-data*', 'x-ms-meta-target*', 'x-ms-meta-xyz', 'x-ms-meta-foo'],
+ ExposedHeaders: ['x-ms-meta-data*', 'x-ms-meta-source*', 'x-ms-meta-abc', 'x-ms-meta-bcd'],
+ MaxAgeInSeconds: 500,
+ },
+ {
+ AllowedOrigins: ['www.msdn.com', 'www.asp.com'],
+ AllowedMethods: ['GET', 'PUT'],
+ AllowedHeaders: ['x-ms-meta-data*', 'x-ms-meta-target*', 'x-ms-meta-xyz', 'x-ms-meta-foo'],
+ ExposedHeaders: ['x-ms-meta-data*', 'x-ms-meta-source*', 'x-ms-meta-abc', 'x-ms-meta-bcd'],
+ MaxAgeInSeconds: 500,
+ },
+ ],
+ },
+ };
+}
+```
+
+When modifying the service properties, you can fetch the properties and then modify the them to prevent overwriting the existing settings.
+
+```Javascript
+var azure = require('azure-storage');
+var blobService = azure.createBlobService();
+
+blobService.getServiceProperties(function(error, result, response) {
+ if (!error) {
+ var serviceProperties = result;
+
+ // modify the properties
+
+ blobService.setServiceProperties(serviceProperties, function(error, result, response) {
+ if (!error) {
+ // properties are set
+ }
+ });
+ }
+});
+```
+
+### Retry Policies
+
+By default, no retry will be performed with service instances newly created by Azure storage client library for Node.js.
+Two pre-written retry polices [ExponentialRetryPolicyFilter](http://azure.github.io/azure-storage-node/ExponentialRetryPolicyFilter.html) and [LinearRetryPolicyFilter](http://azure.github.io/azure-storage-node/LinearRetryPolicyFilter.html) are available with modifiable settings, and can be used through associating filter.
+Any custom retry logic may be used by customizing RetryPolicyFilter instance.
+
+For how to use pre-written retry policies and how to define customized retry policy, please refer to **retrypolicysample** in samples directory.
+
+## Code Samples
+
+How-Tos focused around accomplishing specific tasks are available on the [Microsoft Azure Node.js Developer Center](http://azure.microsoft.com/en-us/develop/nodejs/).
+
+* [How to use the Blob Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-blob-storage/)
+
+* [How to use the Table Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-table-storage/)
+
+* [How to use the Queue Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-queues/)
+
+# Running Tests
+
+Unit tests can then be run from the module's root directory using:
+
+```shell
+npm test
+```
+
+Running test is also supported by Grunt by:
+
+```shell
+grunt # mochaTest as the default task
+```
+
+By default the unit tests are ran with Nock recording data. To run tests against real storage account, please set environment variable to turn off Nock by:
+
+```
+set NOCK_OFF=true
+```
+
+and set up the following environment variable for storage account credentials by
+
+```Batchfile
+set AZURE_STORAGE_CONNECTION_STRING="valid storage connection string"
+```
+
+To record the data in a test pass against real storage account for future Nock usage:
+
+```Batchfile
+set AZURE_NOCK_RECORD=true
+```
+
+In order to be able to use a proxy like fiddler, an additional environment variable should be set up:
+
+```Batchfile
+set NODE_TLS_REJECT_UNAUTHORIZED=0
+set HTTP_PROXY=http://127.0.0.1:8888
+```
+
+On Linux, please use `export` other than `set` to set the variables.
+
+# Azure Storage JavaScript Client Library for Browsers
+
+Azure Storage Node.js Client Library is compatible with [Browserify](http://browserify.org/). This means you can bundle your Node.js application which depends on the Node.js Client Library using Browserify.
+
+You can also choose to download the JavaScript Client Library provided by us, or generate the library by yourself. Please refer to the [README.md](https://github.com/Azure/azure-storage-node/blob/master/browser/README.md) under `browser` folder for detailed usage guidelines.
+
+## Downloading Azure Storage JavaScript Client Library
+
+It's recommended to use the Azure Storage JavaScript Client Library provided by us. Please [download the latest library](https://aka.ms/downloadazurestoragejs).
+
+## Generating Azure Storage JavaScript Client Library
+
+We also provide browserify bundle scripts which generate Azure Storage JavaScript Client Library. The bundle script reduces the size of the Storage Client Library by splitting into smaller files, one per storage service. For more detailed information, refer to [README.md](https://github.com/Azure/azure-storage-node/blob/master/browser/README.md) under `browser` folder.
+
+# JsDoc
+
+JsDoc can be generated by `grunt jsdoc`.
+
+To load the docs by devserver after generation, run `grunt doc` and then browse the docs at [http://localhost:8888](http://localhost:8888).
+
+# Need Help?
+
+Be sure to check out the Microsoft Azure [Developer Forums on MSDN](http://go.microsoft.com/fwlink/?LinkId=234489) if you have trouble with the provided code or use StackOverflow.
+
+# Learn More
+
+- [Microsoft Azure Node.js Developer Center](http://azure.microsoft.com/en-us/develop/nodejs/)
+- [Azure Storage Team Blog](http://blogs.msdn.com/b/windowsazurestorage/)
+
+# Contribute
+
+We gladly accept community contributions.
+
+- Issues: Please report bugs using the Issues section of GitHub
+- Forums: Interact with the development teams on StackOverflow or the Microsoft Azure Forums
+- Source Code Contributions: If you would like to become an active contributor to this project please follow the instructions provided in [Contributing.md](CONTRIBUTING.md).
+
+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.
+
+For general suggestions about Microsoft Azure please use our [UserVoice forum](http://feedback.azure.com/forums/34192--general-feedback).
diff --git a/src/node_modules/azure-storage/browser/ChangeLog.md b/src/node_modules/azure-storage/browser/ChangeLog.md
new file mode 100644
index 0000000..252b00d
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/ChangeLog.md
@@ -0,0 +1,140 @@
+Note: This is the change log file for Azure Storage JavaScript Client Library.
+
+2019.04 Version 2.10.103
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.10.3.
+* Fixed callback not being called in _getBlobToLocalFile.
+* Removed retryInfo.retryable check in retrypolicyfilter.js.
+* Removed comment about maxResults.
+* Fixed Travis-CI failed validation.
+* Updated latest links and descriptions to V10 SDK in readme.md.
+
+2018.10 Version 2.10.102
+
+ALL
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.10.2.
+* Optimized browser samples and other documents.
+* Added JSv10 link and docs.microsoft.com link.
+
+FILE
+* Fixed an issue that empty text isn’t supported in `createFileFromText`.
+
+2018.08 Version 2.10.101
+
+ALL
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.10.1.
+* Fixed a bug that content type value is incorrect for json.
+* Fixed an issue that user agent is set in browser environment.
+
+2018.06 Version 2.10.100
+
+ALL
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.10.0.
+* Updated storage service version to 2018-03-28.
+
+BLOB
+* Fixed a bug that `DeleteRetentionPolicy.Days` should be `number` instead of `string` when calling `getServiceProperties`.
+* Added a method `getAccountProperties` to `blobService`.
+* Added a method `createBlockFromURL` to `blobService`.
+* Added support for static website service properties (in preview).
+
+2018.05 Version 2.9.100-preview
+
+ALL
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.9.0-preview.
+* Updated storage service version to 2017-11-09.
+* Added `/* eslint-disable */` to generated JS files to avoid eslint warnings when using with create-react-app.
+* Added `progress` event for `SpeedSummary` class, which will be triggered when every progress updates.
+
+BLOB
+* Added `createBlobServiceWithTokenCredential()` to create `BlobService` object with bearer tokens such as OAuth access token (in preview).
+* Added support for '$web' as a valid blob container name for static website.
+* Added support for write-once read-many containers (in preview).
+* The `Get Container Properties` and `List Containers` APIs now return two new properties indicating whether the container has an immutability policy or a legal hold.
+* The `Get Blob Properties` and `List Blobs` APIs now return the creation time of the blob as a property.
+
+QUEUE
+* Added `createQueueServiceWithTokenCredential()` to create `QueueService` object with bearer tokens such as OAuth access token (in preview).
+
+2018.04 Version 2.8.100
+
+* Fixed a bug that retry policy will not retry for XHR error in browsers.
+* Updated README.md under browser folder to make it more clear about the zip file downloading link.
+* Updated github.io API reference title to include JavaScript.
+* Updated local HTTP server requirements for IE11 and Chrome 56 in samples and documents.
+* Added support for running UT/FT in browsers like Chrome based on Karma, with command `npm run jstest`.
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.8.2.
+
+2018.03 Version 0.2.8-preview.15
+
+* Supported UMD module standard.
+* Dropped `azure-storage.common.js`.
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.8.1.
+
+2018.02 Version 0.2.8-preview.14
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.8.0.
+
+2017.12 Version 0.2.7-preview.13
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.7.0.
+
+2017.10 Version 0.2.6-preview.12
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.6.0.
+
+2017.09 Version 0.2.5-preview.11
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.5.0.
+
+2017.08 Version 0.2.4-preview.10
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.4.0.
+
+2017.08 Version 0.2.3-preview.9
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.3.0.
+
+2017.08 Version 0.2.2-preview.8
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.2.2.
+
+2017.07 Version 0.2.2-preview.7
+
+* Added browser specific APIs for blobs and files uploading.
+ * `BlobService.createBlockBlobFromBrowserFile`
+ * `BlobService.createPageBlobFromBrowserFile`
+ * `BlobService.createAppendBlobFromBrowserFile`
+ * `BlobService.appendFromBrowserFile`
+ * `FileService.createFileFromBrowserFile`
+* Updated samples with above new added APIs.
+* Dropped dependency to browserify-fs.
+
+2017.07 Version 0.2.2-preview.6
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.2.1.
+
+2017.06 Version 0.2.2-preview.5
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.2.0.
+
+2017.05 Version 0.2.1-preview.4
+
+* Reduced footprint of the generated JavaScript files.
+* Removed 7 local-file related APIs which are limited by browser's sandbox.
+
+2017.03 Version 0.2.1-preview.3
+
+* Fixed missing 100% upload progress issue in blob sample for uploading blobs smaller than 32MB.
+* Added speedSummary code example in the blob & file samples.
+
+2017.03 Version 0.2.1-preview.2
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.1.0.
+
+2017.03 Version 0.2.0-preview.1
+
+* Generated browser compatible JavaScript files based on Microsoft Azure Storage SDK for Node.js 2.0.0.
+* Added bundle scripts to generate Azure Storage JavaScript Client Library.
+* Added npm command `npm run genjs` to generate JavaScript Client Library.
+* Added samples for Azure Storage JavaScript Client Library.
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/README.md b/src/node_modules/azure-storage/browser/README.md
new file mode 100644
index 0000000..f6bc1c8
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/README.md
@@ -0,0 +1,109 @@
+# Azure Storage JavaScript Client Library for Browsers
+
+## Downloading
+
+It's recommended to use the Azure Storage JavaScript Client Library provided by us. Please [download the latest library](https://aka.ms/downloadazurestoragejs).
+
+There are 8 generated JavaScript files for Azure Storage JavaScript Client Library:
+- `azure-storage.blob.js` and `azure-storage.blob.min.js` contain the Azure Storage blob service operation logic
+- `azure-storage.table.js` and `azure-storage.table.min.js` contain the Azure Storage table service operation logic
+- `azure-storage.queue.js` and `azure-storage.queue.min.js` contain the Azure Storage queue service operation logic
+- `azure-storage.file.js` and `azure-storage.file.min.js` contain the Azure Storage file service operation logic
+
+We also provide samples to guide you quickly start with the Azure Storage JavaScript Client Library. In the [JavaScript Client Library zip file](https://aka.ms/downloadazurestoragejs) or following online links, you will find 4 HTML samples:
+- [sample-blob.html](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-blob.html) demonstrates how to operate with Azure Storage blob service in the browser
+- [sample-table.html](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-table.html) demonstrates how to operate with Azure Storage table service in the browser
+- [sample-queue.html](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-queue.html) demonstrates how to operate with Azure Storage queue service in the browser
+- [sample-file.html](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-file.html) demonstrates how to operate with Azure Storage file service in the browser
+
+After generating the JavaScript Client Library, you can try the samples in browsers such as Chrome/Edge/Firefox directly.
+
+**Note**: An HTTP server should be set to host the samples for IE11 and Chrome (56 or newer versions).
+
+Or you can directly try with following online samples:
+- [sample-blob](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-blob.html)
+- [sample-table](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-table.html)
+- [sample-queue](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-queue.html)
+- [sample-file](https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-file.html)
+
+## Module Support
+
+Above JavaScript files are all [UMD compatible](https://github.com/umdjs/umd). You can load them in a CommonJS or AMD environment by JavaScript module loaders. If no module system is found, following global variables will be set:
+- `AzureStorage.Blob`
+- `AzureStorage.Table`
+- `AzureStorage.Queue`
+- `AzureStorage.File`
+
+## Compatibility
+
+Compatibility with mobile browsers have not been fully validated, please open issues when you get errors.
+
+# Running Tests against Browsers
+
+Running tests against Chrome by default. The Storage Account should be configured with CORS support before running test. Please see above online samples about how to configure CORS rules for an account.
+
+```
+set AZURE_STORAGE_CONNECTION_STRING="valid storage connection string"
+npm install
+npm run jstest
+```
+
+## Generating a Custom Azure Storage JavaScript Client Library
+
+If you wish to customize the library and generate the Azure Storage JavaScript Client Library, you can follow the following steps.
+
+We provide browserify bundle scripts which generate Azure Storage JavaScript Client Library. The bundle script reduces the size of the Storage Client Library by splitting into smaller files, one per storage service.
+
+The generated JavaScript Client Library includes 8 separated JavaScript files:
+- `azure-storage.blob.js`
+- `azure-storage.table.js`
+- `azure-storage.queue.js`
+- `azure-storage.file.js`
+- `azure-storage.blob.min.js`
+- `azure-storage.table.min.js`
+- `azure-storage.queue.min.js`
+- `azure-storage.file.min.js`
+
+Let's get started to generate the Azure Storage JavaScript Client Library!
+
+### Step 1: Cloning Repo
+
+Azure Storage JavaScript Client Library is generated from Azure Storage SDK for Node.js. Clone `azure-storage-node` repo with following command:
+
+```Batchfile
+git clone https://github.com/Azure/azure-storage-node.git
+```
+
+### Step 2: Installing Node.js Modules
+
+Change to the root directory of the cloned repo:
+
+```Batchfile
+cd azure-storage-node
+```
+
+Install the dependent Node.js modules:
+
+```Batchfile
+npm install
+```
+
+### Step 3: Generating JavaScript Client Library with Bundle Scripts
+
+We provide bundle scripts to help quickly generate the JavaScript Client Library. At the root directory of the cloned repo:
+
+```Batchfile
+npm run genjs [VERSION_NUMBER]
+```
+
+### Step 4: Finding the Generated JavaScript Files
+
+If everything goes well, the generated JavaScript files should be saved to `azure-storage-node/browser/bundle`. There will be 8 generated JavaScript files totally:
+- `azure-storage.blob.js`
+- `azure-storage.table.js`
+- `azure-storage.queue.js`
+- `azure-storage.file.js`
+- `azure-storage.blob.min.js`
+- `azure-storage.table.min.js`
+- `azure-storage.queue.min.js`
+- `azure-storage.file.min.js`
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/azure-storage.blob.export.js b/src/node_modules/azure-storage/browser/azure-storage.blob.export.js
new file mode 100644
index 0000000..3bd7a28
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/azure-storage.blob.export.js
@@ -0,0 +1,74 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+module.exports.generateDevelopmentStorageCredentials = function (proxyUri) {
+ var devStore = 'UseDevelopmentStorage=true;';
+ if(proxyUri){
+ devStore += 'DevelopmentStorageProxyUri=' + proxyUri;
+ }
+
+ return devStore;
+};
+
+var BlobService = require('../lib/services/blob/blobservice.browser');
+
+module.exports.BlobService = BlobService;
+module.exports.BlobUtilities = require('../lib/services/blob/blobutilities');
+
+module.exports.createBlobService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new BlobService(storageAccountOrConnectionString, storageAccessKey, host, null);
+};
+
+module.exports.createBlobServiceWithSas = function (host, sasToken) {
+ return new BlobService(null, null, host, sasToken);
+};
+
+module.exports.createBlobServiceWithTokenCredential = function (host, tokenCredential) {
+ return new BlobService(null, null, host, null, null, tokenCredential);
+};
+
+module.exports.createBlobServiceAnonymous = function (host) {
+ return new BlobService(null, null, host, null);
+};
+
+var azureCommon = require('../lib/common/common.browser');
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var SharedKey = azureCommon.SharedKey;
+
+module.exports.generateAccountSharedAccessSignature = function(storageAccountOrConnectionString, storageAccessKey, sharedAccessAccountPolicy)
+{
+ var storageSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey);
+ var sharedKey = new SharedKey(storageSettings._name, storageSettings._key);
+
+ return sharedKey.generateAccountSignedQueryString(sharedAccessAccountPolicy);
+};
+
+module.exports.Constants = azureCommon.Constants;
+module.exports.StorageUtilities = azureCommon.StorageUtilities;
+module.exports.AccessCondition = azureCommon.AccessCondition;
+
+module.exports.SR = azureCommon.SR;
+module.exports.StorageServiceClient = StorageServiceClient;
+module.exports.Logger = azureCommon.Logger;
+module.exports.WebResource = azureCommon.WebResource;
+module.exports.Validate = azureCommon.validate;
+module.exports.date = azureCommon.date;
+module.exports.TokenCredential = azureCommon.TokenCredential;
+
+// Other filters
+module.exports.LinearRetryPolicyFilter = azureCommon.LinearRetryPolicyFilter;
+module.exports.ExponentialRetryPolicyFilter = azureCommon.ExponentialRetryPolicyFilter;
+module.exports.RetryPolicyFilter = azureCommon.RetryPolicyFilter;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/azure-storage.file.export.js b/src/node_modules/azure-storage/browser/azure-storage.file.export.js
new file mode 100644
index 0000000..61e7226
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/azure-storage.file.export.js
@@ -0,0 +1,65 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+module.exports.generateDevelopmentStorageCredentials = function (proxyUri) {
+ var devStore = 'UseDevelopmentStorage=true;';
+ if(proxyUri){
+ devStore += 'DevelopmentStorageProxyUri=' + proxyUri;
+ }
+
+ return devStore;
+};
+
+var FileService = require('../lib/services/file/fileservice.browser');
+
+module.exports.FileService = FileService;
+module.exports.FileUtilities = require('../lib/services/file/fileutilities');
+
+module.exports.createFileService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new FileService(storageAccountOrConnectionString, storageAccessKey, host);
+};
+
+module.exports.createFileServiceWithSas = function (hostUri, sasToken) {
+ return new FileService(null, null, hostUri, sasToken);
+};
+
+var azureCommon = require('../lib/common/common.browser');
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var SharedKey = azureCommon.SharedKey;
+
+module.exports.generateAccountSharedAccessSignature = function(storageAccountOrConnectionString, storageAccessKey, sharedAccessAccountPolicy)
+{
+ var storageSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey);
+ var sharedKey = new SharedKey(storageSettings._name, storageSettings._key);
+
+ return sharedKey.generateAccountSignedQueryString(sharedAccessAccountPolicy);
+};
+
+module.exports.Constants = azureCommon.Constants;
+module.exports.StorageUtilities = azureCommon.StorageUtilities;
+module.exports.AccessCondition = azureCommon.AccessCondition;
+
+module.exports.SR = azureCommon.SR;
+module.exports.StorageServiceClient = StorageServiceClient;
+module.exports.Logger = azureCommon.Logger;
+module.exports.WebResource = azureCommon.WebResource;
+module.exports.Validate = azureCommon.validate;
+module.exports.date = azureCommon.date;
+
+// Other filters
+module.exports.LinearRetryPolicyFilter = azureCommon.LinearRetryPolicyFilter;
+module.exports.ExponentialRetryPolicyFilter = azureCommon.ExponentialRetryPolicyFilter;
+module.exports.RetryPolicyFilter = azureCommon.RetryPolicyFilter;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/azure-storage.queue.export.js b/src/node_modules/azure-storage/browser/azure-storage.queue.export.js
new file mode 100644
index 0000000..45726ee
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/azure-storage.queue.export.js
@@ -0,0 +1,71 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+module.exports.generateDevelopmentStorageCredentials = function (proxyUri) {
+ var devStore = 'UseDevelopmentStorage=true;';
+ if(proxyUri){
+ devStore += 'DevelopmentStorageProxyUri=' + proxyUri;
+ }
+
+ return devStore;
+};
+
+var QueueService = require('../lib/services/queue/queueservice');
+
+module.exports.QueueService = QueueService;
+module.exports.QueueUtilities = require('../lib/services/queue/queueutilities');
+module.exports.QueueMessageEncoder = require('../lib/services/queue/queuemessageencoder');
+
+module.exports.createQueueService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new QueueService(storageAccountOrConnectionString, storageAccessKey, host);
+};
+
+module.exports.createQueueServiceWithSas = function(hostUri, sasToken) {
+ return new QueueService(null, null, hostUri, sasToken);
+};
+
+module.exports.createQueueServiceWithTokenCredential = function (host, tokenCredential) {
+ return new QueueService(null, null, host, null, null, tokenCredential);
+};
+
+var azureCommon = require('../lib/common/common.browser');
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var SharedKey = azureCommon.SharedKey;
+
+module.exports.generateAccountSharedAccessSignature = function(storageAccountOrConnectionString, storageAccessKey, sharedAccessAccountPolicy)
+{
+ var storageSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey);
+ var sharedKey = new SharedKey(storageSettings._name, storageSettings._key);
+
+ return sharedKey.generateAccountSignedQueryString(sharedAccessAccountPolicy);
+};
+
+module.exports.Constants = azureCommon.Constants;
+module.exports.StorageUtilities = azureCommon.StorageUtilities;
+module.exports.AccessCondition = azureCommon.AccessCondition;
+
+module.exports.SR = azureCommon.SR;
+module.exports.StorageServiceClient = StorageServiceClient;
+module.exports.Logger = azureCommon.Logger;
+module.exports.WebResource = azureCommon.WebResource;
+module.exports.Validate = azureCommon.validate;
+module.exports.date = azureCommon.date;
+module.exports.TokenCredential = azureCommon.TokenCredential;
+
+// Other filters
+module.exports.LinearRetryPolicyFilter = azureCommon.LinearRetryPolicyFilter;
+module.exports.ExponentialRetryPolicyFilter = azureCommon.ExponentialRetryPolicyFilter;
+module.exports.RetryPolicyFilter = azureCommon.RetryPolicyFilter;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/azure-storage.table.export.js b/src/node_modules/azure-storage/browser/azure-storage.table.export.js
new file mode 100644
index 0000000..9a93dd2
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/azure-storage.table.export.js
@@ -0,0 +1,66 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+module.exports.generateDevelopmentStorageCredentials = function (proxyUri) {
+ var devStore = 'UseDevelopmentStorage=true;';
+ if(proxyUri){
+ devStore += 'DevelopmentStorageProxyUri=' + proxyUri;
+ }
+
+ return devStore;
+};
+
+var TableService = require('../lib/services/table/tableservice');
+module.exports.TableService = TableService;
+module.exports.TableQuery = require('../lib/services/table/tablequery');
+module.exports.TableBatch = require('../lib/services/table/tablebatch');
+module.exports.TableUtilities = require('../lib/services/table/tableutilities');
+
+module.exports.createTableService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new TableService(storageAccountOrConnectionString, storageAccessKey, host);
+};
+
+module.exports.createTableServiceWithSas = function (hostUri, sasToken) {
+ return new TableService(null, null, hostUri, sasToken);
+};
+
+var azureCommon = require('../lib/common/common.browser');
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var SharedKey = azureCommon.SharedKey;
+
+module.exports.generateAccountSharedAccessSignature = function(storageAccountOrConnectionString, storageAccessKey, sharedAccessAccountPolicy)
+{
+ var storageSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey);
+ var sharedKey = new SharedKey(storageSettings._name, storageSettings._key);
+
+ return sharedKey.generateAccountSignedQueryString(sharedAccessAccountPolicy);
+};
+
+module.exports.Constants = azureCommon.Constants;
+module.exports.StorageUtilities = azureCommon.StorageUtilities;
+module.exports.AccessCondition = azureCommon.AccessCondition;
+
+module.exports.SR = azureCommon.SR;
+module.exports.StorageServiceClient = StorageServiceClient;
+module.exports.Logger = azureCommon.Logger;
+module.exports.WebResource = azureCommon.WebResource;
+module.exports.Validate = azureCommon.validate;
+module.exports.date = azureCommon.date;
+
+// Other filters
+module.exports.LinearRetryPolicyFilter = azureCommon.LinearRetryPolicyFilter;
+module.exports.ExponentialRetryPolicyFilter = azureCommon.ExponentialRetryPolicyFilter;
+module.exports.RetryPolicyFilter = azureCommon.RetryPolicyFilter;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/bundle.js b/src/node_modules/azure-storage/browser/bundle.js
new file mode 100644
index 0000000..4572ca7
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/bundle.js
@@ -0,0 +1,77 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var browserify = require('browserify');
+var fs = require('fs');
+var path = require('path');
+var UglifyJS = require('uglify-js');
+
+var version = process.argv[2] || process.env.AZURE_STORAGE_JAVASCRIPT_VERSION || '';
+var license = [
+ '// Azure Storage JavaScript Client Library ' + version,
+ '// Copyright (c) Microsoft and contributors. All rights reserved.',
+ '/* eslint-disable */'
+].join('\n') + '\n';
+
+var outputFolder = 'bundle';
+var outputFolderPath = path.resolve(__dirname, outputFolder);
+
+console.log('Generating Azure Storage JavaScript Client Library to ' + outputFolderPath + ' ...');
+
+if (version === '') {
+ console.warn(
+ 'No version number provided.',
+ 'You can set up a version number by first parameter of bundle.js or environment value AZURE_STORAGE_JAVASCRIPT_VERSION'
+ );
+}
+
+if (!fs.existsSync(outputFolderPath)) {
+ fs.mkdirSync(outputFolderPath);
+}
+
+function build(exportFilePath, outputFilePath, moduleName, isMinify) {
+ browserify(exportFilePath, {standalone: moduleName}).bundle(function (err, src) {
+ if (err) {
+ console.error('Failed when parsing', exportFilePath, err);
+ return;
+ }
+
+ var code = (src || '').toString();
+ if (isMinify) {
+ result = UglifyJS.minify(code.trim());
+ if (result.error) {
+ console.error('Minify failed when parsing', exportFilePath, err);
+ return;
+ }
+
+ code = result.code;
+ }
+
+ var ws = fs.createWriteStream(outputFilePath);
+ ws.write(license);
+ ws.write(code);
+ ws.end();
+ });
+}
+
+build(path.resolve(__dirname, 'azure-storage.blob.export.js'), path.resolve(outputFolderPath, 'azure-storage.blob.js'), 'AzureStorage.Blob');
+build(path.resolve(__dirname, 'azure-storage.table.export.js'), path.resolve(outputFolderPath, 'azure-storage.table.js'), 'AzureStorage.Table');
+build(path.resolve(__dirname, 'azure-storage.queue.export.js'), path.resolve(outputFolderPath, 'azure-storage.queue.js'), 'AzureStorage.Queue');
+build(path.resolve(__dirname, 'azure-storage.file.export.js'), path.resolve(outputFolderPath, 'azure-storage.file.js'), 'AzureStorage.File');
+build(path.resolve(__dirname, 'azure-storage.blob.export.js'), path.resolve(outputFolderPath, 'azure-storage.blob.min.js'), 'AzureStorage.Blob', true);
+build(path.resolve(__dirname, 'azure-storage.table.export.js'), path.resolve(outputFolderPath, 'azure-storage.table.min.js'), 'AzureStorage.Table', true);
+build(path.resolve(__dirname, 'azure-storage.queue.export.js'), path.resolve(outputFolderPath, 'azure-storage.queue.min.js'), 'AzureStorage.Queue', true);
+build(path.resolve(__dirname, 'azure-storage.file.export.js'), path.resolve(outputFolderPath, 'azure-storage.file.min.js'), 'AzureStorage.File', true);
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/samples/cors.PNG b/src/node_modules/azure-storage/browser/samples/cors.PNG
new file mode 100644
index 0000000..4f6a97f
Binary files /dev/null and b/src/node_modules/azure-storage/browser/samples/cors.PNG differ
diff --git a/src/node_modules/azure-storage/browser/samples/sample-blob.html b/src/node_modules/azure-storage/browser/samples/sample-blob.html
new file mode 100644
index 0000000..43364e4
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/samples/sample-blob.html
@@ -0,0 +1,498 @@
+
+
+
+
+
+ Azure Storage JavaScript Client Library Sample for Blob Operations
+
+
+
+
+
+
Azure Storage JavaScript Client Library Sample for Blob Operations
+
+
In this sample, we will demonstrate common scenarios for Azure Blob Storage that includes creating, listing and deleting containers and blobs.
+
+
Azure Blob storage is a service for storing large amounts of unstructured object data, such as text or binary data, that can be accessed from anywhere in the world via HTTP or HTTPS. You can use Blob storage to expose data publicly to the world, or to store application data privately.
+
+
+
+ Note: You may need set up a HTTP server to host this sample for IE11 and latest Chrome.
+
+
+
+
Contents:
+
+
+
Step 1: Preparing an Azure Storage account with CORS rules set
+
Cross-origin resource sharing, or CORS, must be configured on the Azure Storage account to be accessed directly from JavaScript in the browser.
+ You are able to set the CORS rules for specific Azure Storage account on the Azure Portal.
+ The "Allowed origins" could be set to "*" to allow all the origins in this sample.
+ For more information about CORS, see Cross-Origin Resource Sharing (CORS).
+
+
+
Step 2: Importing Azure Storage JavaScript Client Library
+
+ Importing azure-storage.blob.js
in your HTML file for blob operations.
+
+
+<script src="azure-storage.blob.js"></script>
+
+
+
Step 3: Creating an Azure Storage Blob Service Object
+
+ The BlobService
object lets you work with containers and blobs.
+ Following code creates a BlobService
object with storage account and SAS Token.
+
+
+var blobUri = 'https://' + 'STORAGE_ACCOUNT' + '.blob.core.windows.net';
+var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, 'SAS_TOKEN');
+
+
+ You can load Azure Storage JavaScript Client Library in a CommonJS or AMD environment by JavaScript module loaders. If no module system is found, global variable AzureStorage.Blob
will be set, which is the start point where we can create service objects for blob and access to the storage utilities.
+
+
+
+
How to get full detailed API definitions? Currently, the JavaScript Client Library shares almost the same API definitions with Node.js SDK, besides Node.js runtime specific APIs.
+ Please check API details on
Azure Storage API reference documents. The JavaScript global variable
AzureStorage.Blob
is just like the object
require('azure-storage')
returns in Node.js, but limits to Blob related interfaces.
+ Go to
BlobService to view possible methods provided by
BlobService
class.
+
+
+
+
+
Warning: Azure Storage JavaScript Client Library also supports creating
BlobService
based on Storage Account Key for authentication besides SAS Token.
+ However, for security concerns, we recommend use of a limited time SAS Token, generated by a backend web server using a
Stored Access Policy.
+
+
+
+
Step 4: Container Operations
+
+ A container provides a grouping of blobs. All blobs must be in a container. An account can contain an unlimited number of containers. A container can store an unlimited number of blobs. Note that the container name must be lowercase.
+ BlobService
object provides plenty of interfaces for container operations.
+
+
+
List Containers
+
BlobService
provides listContainersSegmented
and listContainersSegmentedWithPrefix
for retrieving the containers list under a storage account.
+
+blobService.listContainersSegmented(null, function (error, results) {
+ if (error) {
+ // List container error
+ } else {
+ for (var i = 0, container; container = results.entries[i]; i++) {
+ // Deal with container object
+ }
+ }
+});
+
+
+
Create Container
+
BlobService
provides createContainer
and createContainerIfNotExists
for creating a container under a storage account.
+
+blobService.createContainerIfNotExists('mycontainer', function(error, result) {
+ if (error) {
+ // Create container error
+ } else {
+ // Create container successfully
+ }
+});
+
+
+
Delete Container
+
BlobService
provides deleteContainer
and deleteContainerIfExists
for deleting a container under a storage account.
+
+blobService.deleteContainerIfExists('mycontainer', function(error, result) {
+ if (error) {
+ // Delete container error
+ } else {
+ // Delete container successfully
+ }
+});
+
+
+
Executable Example
+
+ The sample will try to create an Azure Storage blob service object based on SAS Token authorization.
+ Enter your Azure Storage account name and SAS Token here, and executable examples in following steps dependent on the settings here.
+ Make sure you have set the CORS rules for the Azure Storage blob service, and the SAS Token is in valid period.
+
+
+
+
+
+
In the following executable example, you can try to list all the containers under your storage account settings, and try to create or delete one container from your account.
+
+ Click button to view the container list under your Azure Storage account
+ -
+
Click button to create a container under your Azure Storage account:
+
+
+ Click "Delete" button in the container list to delete the container under your Azure Storage account
+ Click "Select" button to select and operate with the blobs in next step
+
+
+
+
Step 5: Blob Operations
+
Blob: A file of any type and size. Azure Storage offers three types of blobs: block blobs, page blobs, and append blobs.
+
Block blobs are ideal for storing text or binary files, such as documents and media files. Append blobs are similar to block blobs in that they are made up of blocks, but they are optimized for append operations, so they are useful for logging scenarios. A single block blob can contain up to 50,000 blocks of up to 100 MB each, for a total size of slightly more than 4.75 TB (100 MB X 50,000). A single append blob can contain up to 50,000 blocks of up to 4 MB each, for a total size of slightly more than 195 GB (4 MB X 50,000).
+
Page blobs can be up to 1 TB in size, and are more efficient for frequent read/write operations. Azure Virtual Machines use page blobs as OS and data disks.
+
For details about naming containers and blobs, see Naming and Referencing Containers, Blobs, and Metadata.
+
+
List Blobs
+
BlobService
provides listBlobsSegmented
and listBlobsSegmentedWithPrefix
for retrieving the blobs list under a container.
+
+blobService.listBlobsSegmented('mycontainer', null, function (error, results) {
+ if (error) {
+ // List blobs error
+ } else {
+ for (var i = 0, blob; blob = results.entries[i]; i++) {
+ // Deal with blob object
+ }
+ }
+});
+
+
Upload Blob
+
BlobService
provides createBlockBlobFromBrowserFile
, createPageBlobFromBrowserFile
, createAppendBlobFromBrowserFile
and appendFromBrowserFile
for uploading or appending a blob from an HTML file in browsers.
+
+
+
Uploading blob from stream. You can set up the blob name as well as the size of this uploading session.
+
+// If one file has been selected in the HTML file input element
+var file = document.getElementById('fileinput').files[0];
+
+var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;
+blobService.singleBlobPutThresholdInBytes = customBlockSize;
+
+var finishedOrError = false;
+var speedSummary = blobService.createBlockBlobFromBrowserFile('mycontainer', file.name, file, {blockSize : customBlockSize}, function(error, result, response) {
+ finishedOrError = true;
+ if (error) {
+ // Upload blob failed
+ } else {
+ // Upload successfully
+ }
+});
+refreshProgress();
+
+
Checking the upload progress with speedSummary
object.
+
+speedSummary.on('progress', function () {
+ var process = speedSummary.getCompletePercent();
+ displayProcess(process);
+});
+
+
+
+
Warning:
+ By default, the
speedSummary.getCompletePercent()
only updates progress when a block is uploaded to server. There are 2 default settings that may influence the upload progress display.
+
+
+ blobService.singleBlobPutThresholdInBytes
is the maximum size (default 32MB), in bytes, of a blob before it must be separated into blocks.
+ - Option
{blockSize: SizeInBytes}
of blobService.createBlockBlobFromStream()
is the size (default 4MB) of every block in the storage layer.
+
+
+ This means, by default, blobs smaller than 32MB will only get the progress update when the upload is over, and blobs larger than 32MB will update the process every 4MB.
+ For slow connections or progress reporting for small blobs, you can customize both the two settings into samller values such as 1MB or 512KB. Thus the progress will update with the smaller step you set.
+ However, very small block sizes will impact the storage performance especially for a large blob.
+
+
+
+
Download Blob
+
+ BlobService
provides interfaces for downloading a blob into browser memory.
+ Because of browser's sandbox limitation, we cannot save the downloaded data trunks into disk until we get all the data trunks of a blob into browser memory.
+ The browser's memory size is also limited especially for downloading huge blobs, so it's recommended to download a blob in browser with SAS Token authorized link directly.
+
+
+ Shared access signatures (SAS) are a secure way to provide granular access to blobs and containers without providing your storage account name or keys. Shared access signatures are often used to provide limited access to your data, such as allowing a mobile app to access blobs.
+ The following code example generates a new shared access policy that allows the shared access signatures holder to perform read operations on the myblob blob, and expires 100 minutes after the time it is created.
+
+
+
+ Note: You can choose to use the SAS Token in browser side, or generate a temporary SAS Token dynamically in your server side with Azure Storage C# or Node.js SDKs etc. according to your security requirements.
+
+
+
+var downloadLink = blobService.getUrl('mycontainer', 'myblob', 'SAS_TOKEN');
+
+
+
Delete Blob
+
BlobService
provides deleteContainer
and deleteContainerIfExists
for deleting a blob under a storage account.
+
+blobService.deleteBlobIfExists(container, blob, function(error, result) {
+ if (error) {
+ // Delete blob failed
+ } else {
+ // Delete blob successfully
+ }
+});
+
+
Executable Example
+
After clicked the "Select" button on the container list in last step, you are able to operate with the blobs under the selected container.
+
+
+
+ Click button to view the blobs under your selected container
+
+ Click button to upload a local file to current container after selecting a file:
+
+
+ Click "Delete" button to delete the blob
+ Click "Download" link to download a blob to local
+
+
+
+
Uploaded Bytes:
+
+
+
+
+
Step 6: Creating your JavaScript Application based on Azure Storage JavaScript Client Library
+
+ - Setting CORS rules for your selected Azure-Storage account blob service.
+ - Including functional file(s) needed, such as "azure-storage.blob.js" for blob operation.
+ - Using keyword "AzureStorage.Blob" to access to Azure storage JavaScript APIs for blobs.
+ - Referring to API documents for detailed API definitions.
+
+
You can view the source code of this sample for detailed reference.
+
+
+
+
+
+
+
diff --git a/src/node_modules/azure-storage/browser/samples/sample-file.html b/src/node_modules/azure-storage/browser/samples/sample-file.html
new file mode 100644
index 0000000..2125cc3
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/samples/sample-file.html
@@ -0,0 +1,575 @@
+
+
+
+
+
+ Azure Storage JavaScript Client Library Sample for File Operations
+
+
+
+
+
+
Azure Storage JavaScript Client Library Sample for File Operations
+
+
In this sample, we will demonstrate common scenarios for Azure File Storage that includes creating, listing and deleting file shares, directories and files.
+
+
Azure File storage is a service for storing large amounts of unstructured object data, such as text or binary data, that can be accessed from anywhere in the world via HTTP or HTTPS. You can use file storage to expose data publicly to the world, or to store application data privately.
+
With Azure File storage, you can migrate legacy applications that rely on file shares to Azure quickly and without costly rewrites. Applications running in Azure virtual machines or cloud services or from on-premises clients can mount a file share in the cloud, just as a desktop application mounts a typical SMB share. Any number of application components can then mount and access the File storage share simultaneously. In this sample, you are able to create a file service with storage account and SAS Token. Based on the file service, you could create a file share, list files, upload files and delete files.
+
+
+
+ Note: You may need set up a HTTP server to host this sample for IE11 and latest Chrome.
+
+
+
+
Contents:
+
+
+
Step 1: Preparing an Azure Storage account with CORS rules set
+
Cross-origin resource sharing, or CORS, must be configured on the Azure Storage account to be accessed directly from JavaScript in the browser.
+ You are able to set the CORS rules for specific Azure Storage account on the Azure Portal.
+ The "Allowed origins" could be set to "*" to allow all the origins in this sample.
+ For more information about CORS, see Cross-Origin Resource Sharing (CORS).
+
+
+
Step 2: Importing Azure Storage JavaScript Files
+
+ Importing azure-storage.file.js
in your HTML file for file operations.
+
+
+<script src="azure-storage.file.js"></script>
+
+
+
Step 3: Creating an Azure Storage File Service Object
+
+ The FileService
object lets you work with files and directories.
+ Following code creates a FileService
object with storage account and SAS Token.
+
+
+var fileUri = 'https://' + 'STORAGE_ACCOUNT' + '.file.core.windows.net';
+var fileService = AzureStorage.File.createFileServiceWithSas(fileUri, 'SAS_TOKEN');
+
+
+ You can load Azure Storage JavaScript Client Library in a CommonJS or AMD environment by JavaScript module loaders. If no module system is found, global variable AzureStorage.File
will be set, which is the start point where we can create service objects for file and access to the storage utilities.
+
+
+
+
How to get full detailed API definitions? Currently, the JavaScript Client Library shares almost the same API definitions with Node.js SDK, besides Node.js runtime specific APIs.
+ Please check API details on
Azure Storage API reference documents. The JavaScript global variable
AzureStorage.File
is just like the object
require('azure-storage')
returns in Node.js, but limits to File related interfaces.
+ Go to
FileService to view possible methods provided by
FileService
class.
+
+
+
+
+
Warning: Azure Storage JavaScript Client Library also supports creating
FileService
based on Storage Account Key for authentication besides SAS Token.
+ However, for security concerns, we recommend use of a limited time SAS Token, generated by a backend web server using a
Stored Access Policy.
+
+
+
+
Step 4: File Share Operations
+
Share: A File storage share is an SMB file share in Azure. All directories and files must be created in a parent share. An account can contain an unlimited number of shares, and a share can store an unlimited number of files, up to the 5 TB total capacity of the file share.
+
+
List File Shares
+
FileService
provides listSharesSegmented
and listSharesSegmentedWithPrefix
for listing file shares under a storage account.
+
+fileService.listSharesSegmented(null, function(error, result) {
+ if(error) {
+ // List shares error
+ } else {
+ for (var i = 0, share; share = results.entries[i]; i++) {
+ // Deal with share object
+ }
+ }
+});
+
+
+
Create File Share
+
FileService
provides createShare
and createShareIfNotExists
for creating a file share under a storage account.
+
+fileService.createShareIfNotExists('myshare', function(error, result) {
+ if(error) {
+ // Create share error
+ } else {
+ // Create share successfully
+ }
+});
+
+
+
Delete File Share
+
FileService
provides deleteShare
and deleteShareIfExists
for deleting a file share under a storage account.
+
+fileService.deleteShareIfExists('myshare', function(error, result) {
+ if(error) {
+ // Delete share error
+ } else {
+ // Delete share successfully
+ }
+});
+
+
+
Executable Example
+
The sample will try to create an Azure Storage file service object based on SAS Token authorization. Enter your Azure Storage account name and SAS Token here. Make sure you have set the CORS rules for the Azure Storage file service, and the SAS Token is in valid period.
+
+
+
Azure Storage file service provides plenty of interfaces for file operations. In following example, you can try to list all the file shares under your storage account, and try to create or delete one file share from your account.
+
+ Click button to view the file share list under your Azure Storage account
+ -
+
Click button to create a file share under your Azure Storage account
+
+
+ Click "Delete" button to delete the file share under your Azure Storage account
+ Click "Select" button to operate with the directories and files in next step
+
+
+
+
Step 5: Directory and File Operations
+
Directory in storage is an optional hierarchy of directories.
+
File: A file in the share. A file may be up to 1 TB in size.
+
+
List Files and Directories
+
FileService
provides listFilesAndDirectoriesSegmented
for listing directories and files under a file share.
+
+fileService.listFilesAndDirectoriesSegmented('myfileshare', '', null, function(error, result, response) {
+ if(error) {
+ // List table entity error
+ } else {
+ for (var i = 0, dir; dir = results.entries.directories[i]; i++) {
+ // Deal with directory object
+ }
+ for (var i = 0, file; file = results.entries.files[i]; i++) {
+ // Deal with file object
+ }
+ }
+});
+
+
+
Create Directory
+
FileService
provides createDirectory
and createDirectoryIfNotExists
for creating directories under a file share.
+
+fileService.createDirectoryIfNotExists('myfileshare', 'mydirectory', function(error, result, response) {
+ if(error) {
+ // Create directory error
+ } else {
+ // Create directory successfully
+ }
+});
+
+
+
Delete Directory
+
FileService
provides deleteDirectory
and deleteDirectoryIfExists
for deleting directories under a file share.
+
+fileService.deleteDirectoryIfExists('myfileshare', 'mydirectory', function(error, result, response) {
+ if(error) {
+ // Delete directory error
+ } else {
+ // Delete directory successfully
+ }
+});
+
+
+
Upload File
+
FileService
provides createFileFromBrowserFile
for uploading a file from an HTML file in browsers.
+
+
+
Uploading file from stream. You can set up the file name as well as the size of this uploading session.
+
+// If one file has been selected in the HTML file input element
+var files = document.getElementById('fileinput').files;
+var file = files[0];
+
+var finishedOrError = false;
+var speedSummary = fileService.createFileFromBrowserFile('myfileshare', 'mydirectory', file.name, file, {}, function(error, result, response) {
+ finishedOrError = true;
+ if (error) {
+ // Upload file failed
+ } else {
+ // Upload successfully
+ }
+});
+refreshProgress();
+
+
Checking the upload progress with speedSummary object.
+
+speedSummary.on('progress', function () {
+ var process = speedSummary.getCompletePercent();
+ displayProcess(process);
+});
+
+
Download File
+
+ FileService
provides interfaces for downloading a file into browser memory directly.
+ Because of browser's sandbox limitation, we cannot save the downloaded data trunks into disk until we get all the data trunks of a file into browser memory.
+ The browser's memory size is also limited especially for downloading huge files, so it's recommended to download a file in browser with SAS Token authorized link directly.
+
+
+ Shared access signatures (SAS) are a secure way to provide granular access to files and directories without providing your storage account name or keys. Shared access signatures are often used to provide limited access to your data, such as allowing a mobile app to access files.
+ The following code example generates a new shared access policy that allows the shared access signatures holder to perform read operations on the myfile file, and expires 100 minutes after the time it is created.
+
+
+
+ Note: You can choose to use the SAS Token in browser side, or generate a temporary SAS Token dynamically in your server side with Azure Storage C# or Node.js SDKs etc. according to your security requirements.
+
+
+
+var downloadLink = fileService.getUrl('myshare', 'mydirectory', 'myfile', 'SAS_TOKEN');
+
+
+
Delete File
+
FileService
provides deleteFile
and deleteFileIfExists
for deleting files under a file share.
+
+fileService.deleteFileIfExists('myfileshare', 'mydirectory', 'myfile', function(error, result, response) {
+ if(error) {
+ // Delete file error
+ } else {
+ // Delete file successfully
+ }
+});
+
+
+
Executable Example
+
After clicked the "Select" button on the file share list, you are able to operate with the directories and files under the selected file share.
+
+ Click button to view the directories and files under your selected file share
+ Click button to create a directory share under your current directory
+
+
+ Click button to return to upper level directory
+ Click button to upload a local file to current directory
+
+ Click "Delete" button to delete the directory or file
+ Click "Download" link to download a file to local
+
+
+
Current Path:
+
Uploaded Bytes:
+
+
+
+
Step 6: Creating your JavaScript Application based on Azure Storage JavaScript Client Library
+
+ - Setting CORS rules for your selected Azure-Storage account file service.
+ - Including functional file(s) needed, such as "azure-storage.file.js" for file operation.
+ - Using keyword "AzureStorage.File" to access to Azure storage JavaScript APIs for files.
+ - Referring to API documents for detailed API definitions.
+
+
You can view the source code of this sample for detailed reference.
+
+
+
+
+
+
+
diff --git a/src/node_modules/azure-storage/browser/samples/sample-queue.html b/src/node_modules/azure-storage/browser/samples/sample-queue.html
new file mode 100644
index 0000000..99ffe51
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/samples/sample-queue.html
@@ -0,0 +1,462 @@
+
+
+
+
+
+ Azure Storage JavaScript Client Library Sample for Queue Operations
+
+
+
+
+
+
Azure Storage JavaScript Client Library Sample for Queue Operations
+
+
In this sample, we will demonstrate common scenarios for Azure Queue Storage that includes creating, listing and deleting queues and messages.
+
+
+
Azure Storage queue service provides cloud messaging between application components. In designing applications for scale, application components are often decoupled, so that they can scale independently. Queue storage delivers asynchronous messaging for communication between application components, whether they are running in the cloud, on the desktop, on an on-premises server, or on a mobile device. Queue storage also supports managing asynchronous tasks and building process work flows.
+
+
+
+
+ Note: You may need set up a HTTP server to host this sample for IE11 and latest Chrome.
+
+
+
+
Contents:
+
+
+
Step 1: Preparing an Azure Storage account with CORS rules set
+
Cross-origin resource sharing, or CORS, must be configured on the Azure Storage account to be accessed directly from JavaScript in the browser.
+ You are able to set the CORS rules for specific Azure Storage account on the Azure Portal.
+ The "Allowed origins" could be set to "*" to allow all the origins in this sample.
+ For more information about CORS, see Cross-Origin Resource Sharing (CORS).
+
+
+
Step 2: Importing Azure Storage JavaScript Client Library
+
+ Importing azure-storage.queue.js
in your HTML file for queue operations.
+
+
+<script src="azure-storage.queue.js"></script>
+
+
+
Step 3: Creating an Azure Storage Queue Service Object
+
+ The QueueService
object lets you work with queues and messages.
+ Following code creates a QueueService
object with storage account and SAS Token.
+
+
+var queueUri = 'https://' + 'STORAGE_ACCOUNT' + '.queue.core.windows.net';
+var queueService = AzureStorage.Queue.createQueueServiceWithSas(queueUri, 'SAS_TOKEN');
+
+
+ You can load Azure Storage JavaScript Client Library in a CommonJS or AMD environment by JavaScript module loaders. If no module system is found, global variable AzureStorage.Queue
will be set, which is the start point where we can create service objects for queue and access to the storage utilities.
+
+
+
+
How to get full detailed API definitions? Currently, the JavaScript Client Library shares almost the same API definitions with Node.js SDK, besides Node.js runtime specific APIs.
+ Please check API details on
Azure Storage API reference documents. The JavaScript global variable
AzureStorage.Queue
is just like the object
require('azure-storage')
returns in Node.js, but limits to Queue related interfaces.
+ Go to
QueueService to view possible methods provided by
QueueService
class.
+
+
+
+
+
Warning: Azure Storage JavaScript Client Library also supports creating
QueueService
based on Storage Account Key for authentication besides SAS Token.
+ However, for security concerns, we recommend use of a limited time SAS Token, generated by a backend web server using a
Stored Access Policy.
+
+
+
+
Step 4: Queue Operations
+
+ Azure Queue storage is a service for storing large numbers of messages that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS. A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account.
+
+
+
List Queues
+
QueueService
provides listQueuesSegmented
and listQueuesSegmentedWithPrefix
for retrieving the queue list under your storage account.
+
+queueService.listQueuesSegmented(null, function (error, results) {
+ if (error) {
+ // List queue error
+ } else {
+ for (var i = 0, queue; queue = results.entries[i]; i++) {
+ // Deal with queue object
+ }
+ }
+});
+
+
+
Create Queue
+
QueueService
provides createQueue
and createQueueIfNotExists
for creating a queue under a storage account.
+
+queueService.createQueueIfNotExists('myqueue', function(error, result) {
+ if (error) {
+ // Create queue error
+ } else {
+ // Create queue successfully
+ }
+});
+
+
+
Delete Queue
+
QueueService
provides deleteQueue
and deleteQueueIfExists
for deleting a queue under a storage account.
+
+queueService.deleteQueueIfExists('myqueue', function(error, result) {
+ if (error) {
+ // Delete queue error
+ } else {
+ // Delete queue successfully
+ }
+});
+
+
+
Executable Example
+
The sample will try to create an Azure Storage queue service object based on SAS Token authorization. Enter your Azure Storage account name and SAS Token here. Make sure you have set the CORS rules for the Azure Storage queue service, and the SAS Token is in valid period.
+
+
+
Azure Storage queue service provides plenty of interfaces for queue operations. In following example, you can try to list all the queues under your storage account, and try to create or delete one queue from your account.
+
+ Click button to view the queue list under your Azure Storage account
+ Click button to create a queue under your Azure Storage account:
+
+
+ Click "Delete" button to delete the queue under your Azure Storage account
+ Click "Select" button to select a queue and operate with the queue messages in next step
+
+
+
+
Step 5: Message Operations
+
A storage Message, in any format, of up to 64 KB. The maximum time that a message can remain in the queue is 7 days.
+
+
+ Note: Azure Storage JavaScript Client Library provides var encoder = new AzureStorage.Queue.QueueMessageEncoder.TextBase64QueueMessageEncoder()
which is a Base64 encoder and docoder.
+ If a message content string is encoded with encoder.encode()
, remember to decode it with encoder.decode()
after peek the message.
+
+
+
+
Peek Messages
+
QueueService
provides peekMessage
and peekMessages
for retrieving the messages list under a queue.
+
+queueService.peekMessages('myqueue', {numOfMessages: 32}, function (error, results) {
+ if (error) {
+ // Peek messages error
+ } else {
+ for (var i = 0, message; message = results[i]; i++) {
+ // Deal with message object
+ }
+ }
+});
+
+
+
Create Message
+
QueueService
provides createMessage
for creating a new message to a queue.
+
+var encoder = new AzureStorage.Queue.QueueMessageEncoder.TextBase64QueueMessageEncoder();
+queueService.createMessage('myqueue', encoder.encode('mymessage'), function (error, results, response) {
+ if (error) {
+ // Create message error
+ } else {
+ // Create message successfully
+ }
+});
+
+
+
Dequeue Message
+
QueueService
provides getMessages
and deleteMessage
for dequeuing next message in a queue.
+
+queueService.getMessages('myqueue', function(error, result, response) {
+ if(!error){
+ // Message text is in messages[0].messageText
+ var message = result[0];
+ queueService.deleteMessage('myqueue', message.messageId, message.popReceipt, function(error, response){
+ if(!error){
+ //message deleted
+ }
+ });
+ }
+});
+
+
+
Update Message
+
QueueService
provides getMessages
and updateMessage
for updating next message in a queue.
+
+var encoder = new AzureStorage.Queue.QueueMessageEncoder.TextBase64QueueMessageEncoder();
+queueService.getMessages('myqueue', function(error, result, response) {
+ if(!error){
+ // Got the message
+ var message = result[0];
+ queueService.updateMessage('myqueue', message.messageId, message.popReceipt, 10, {messageText: encoder.encode('new text')}, function(error, result, response){
+ if(!error){
+ // Message updated successfully
+ }
+ });
+ }
+});
+
+
+
Executable Example
+
After clicked the "Select" button on the queue list in last step, you are able to operate with the queue messages under the selected queue.
+
+ Click button to refresh the message list in your selected queue
+ Click button to create a message in your selected queue:
+
+
+ Click button to update the top queue message in your selected queue (Dequeued messages will be invisible for 30s by default.):
+
+
+ Click button to dequeue the top queue message in your selected queue:
+
+
+
+
+
Step 6: Creating your JavaScript Application based on Azure Storage JavaScript Client Library
+
+ - Setting CORS rules for your selected Azure-Storage account queue service.
+ - Including functional file(s) needed, such as "azure-storage.queue.js" for queue operation.
+ - Using keyword "AzureStorage.Queue" to access to Azure storage JavaScript APIs for queues.
+ - Referring to API documents for detailed API definitions.
+
+
You can view the source code of this sample for detailed reference.
+
+
+
+
+
+
diff --git a/src/node_modules/azure-storage/browser/samples/sample-table.html b/src/node_modules/azure-storage/browser/samples/sample-table.html
new file mode 100644
index 0000000..183a04c
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/samples/sample-table.html
@@ -0,0 +1,437 @@
+
+
+
+
+
+ Azure Storage JavaScript Client Library Sample for Table Operations
+
+
+
+
+
+
Azure Storage JavaScript Client Library Sample for Table Operations
+
+
In this sample, we will demonstrate common scenarios for Azure Table Storage that includes creating, listing and deleting tables and entities.
+
+
+
Azure Storage table is a service that stores structured NoSQL data in the cloud. Table storage is a key/attribute store with a schemaless design. Because Table storage is schemaless, it's easy to adapt your data as the needs of your application evolve. Access to data is fast and cost-effective for all kinds of applications. Table storage is typically significantly lower in cost than traditional SQL for similar volumes of data.
+
+
+
+
+ Note: You may need set up a HTTP server to host this sample for IE11 and latest Chrome.
+
+
+
+
Contents:
+
+
+
Step 1: Preparing an Azure Storage account with CORS rules set
+
Cross-origin resource sharing, or CORS, must be configured on the Azure Storage account to be accessed directly from JavaScript in the browser.
+ You are able to set the CORS rules for specific Azure Storage account on the Azure Portal.
+ The "Allowed origins" could be set to "*" to allow all the origins in this sample.
+ For more information about CORS, see Cross-Origin Resource Sharing (CORS).
+
+
+
Step 2: Importing Azure Storage JavaScript Client Library
+
+ Importing azure-storage.table.js
in your HTML file for table operations.
+
+
+<script src="azure-storage.table.js"></script>
+
+
+
Step 3: Creating an Azure Storage Table Service Object
+
+ The TableService
object lets you work with table and entities.
+ Following code creates a TableService
object with storage account and SAS Token.
+
+
+var tableUri = 'https://' + 'STORAGE_ACCOUNT' + '.table.core.windows.net';
+var tableService = AzureStorage.Table.createTableServiceWithSas(tableUri, 'SAS_TOKEN');
+
+
+ You can load Azure Storage JavaScript Client Library in a CommonJS or AMD environment by JavaScript module loaders. If no module system is found, global variable AzureStorage.Table
will be set, which is the start point where we can create service objects for table and access to the storage utilities.
+
+
+
+
How to get full detailed API definitions? Currently, the JavaScript Client Library shares almost the same API definitions with Node.js SDK, besides Node.js runtime specific APIs.
+ Please check API details on
Azure Storage API reference documents. The JavaScript global variable
AzureStorage.Table
is just like the object
require('azure-storage')
returns in Node.js, but limits to Table related interfaces.
+ Go to
TableService to view possible methods provided by
TableService
class.
+
+
+
+
+
Warning: Azure Storage JavaScript Client Library also supports creating
TableService
based on Storage Account Key for authentication besides SAS Token.
+ However, for security concerns, we recommend use of a limited time SAS Token, generated by a backend web server using a
Stored Access Policy.
+
+
+
+
Step 4: Table Operations
+
+ Table: A table is a collection of entities. Tables don't enforce a schema on entities, which means a single table can contain entities that have different sets of properties. The number of tables that a storage account can contain is limited only by the storage account capacity limit.
+
+
+
List Tables
+
TableService
provides listTablesSegmented
and listTablesSegmentedWithPrefix
for retrieving the table list under your storage account.
+
+tableService.listTablesSegmented(null, {maxResults : 200}, function (error, results) {
+ if (error) {
+ // List tables error
+ } else {
+ for (var i = 0, table; table = results.entries[i]; i++) {
+ // Deal with table object
+ }
+ }
+});
+
+
+
Create Table
+
TableService
provides createTable
and createTableIfNotExists
for creating a table under a storage account.
+
+tableService.createTableIfNotExists('mytable', function(error, result) {
+ if (error) {
+ // Create table error
+ } else {
+ // Create table successfully
+ }
+});
+
+
+
Delete Table
+
TableService
provides deleteTable
and deleteTableIfExists
for deleting a table under a storage account.
+
+tableService.deleteTableIfExists('mytable', function(error, result) {
+ if (error) {
+ // Delete table error
+ } else {
+ // Delete table successfully
+ }
+});
+
+
+
Executable Example
+
The sample will try to create an Azure Storage table service object based on SAS Token authorization. Enter your Azure Storage account name and SAS Token here. Make sure you have set the CORS rules for the Azure Storage table service, and the SAS Token is in valid period.
+
+
+
Azure Storage table service provides plenty of interfaces for table operations. In following example, you can try to list all the tables under your storage account, and try to create or delete one table from your account.
+
+ Click button to view the table list under your Azure Storage account
+ Click button to create a table under your Azure Storage account
+
+
+ Click "Delete" button to delete the table under your Azure Storage account
+ Click "Select" button to operate with the table entities in next step
+
+
+
+
Step 5: Table Entities Operations
+
Entity: An entity is a set of properties, similar to a database row. An entity can be up to 1MB in size.
+
Properties: A property is a name-value pair. Each entity can include up to 252 properties to store data. Each entity also has 3 system properties that specify a partition key, a row key, and a timestamp. Entities with the same partition key can be queried more quickly, and inserted/updated in atomic operations. An entity's row key is its unique identifier within a partition.
+
+
Query Entities
+
TableService
provides queryEntities
for querying a table under a storage account.
+
+var tableQuery = new AzureStorage.Table.TableQuery().top(200);
+tableService.queryEntities('mytable', tableQuery, null, function(error, result) {
+ if (error) {
+ // Query entities error
+ } else {
+ for (var i = 0, entity; entity = results.entries[i]; i++) {
+ // Deal with entity object
+ }
+ }
+});
+
+
+
Insert or Replace Entity
+
TableService
provides insertEntity
, insertOrReplaceEntity
and insertOrMergeEntity
for adding a table entity under a storage account.
+
+var insertEntity = {
+ PartitionKey: {'_': 'partitionKey'},
+ RowKey: {'_': 'rowKey'}
+};
+
+tableService.insertOrReplaceEntity('mytable', insertEntity, function(error, result, response) {
+ if(error) {
+ // Insert table entity error
+ } else {
+ // Insert table entity successfully
+ }
+});
+
+
+
Delete Entity
+
TableService
provides deleteEntity
for deleting a table entity under a storage account.
+
+var deleteEntity = {
+ PartitionKey: {'_': 'partitionKey'},
+ RowKey: {'_': 'rowKey'}
+};
+
+tableService.deleteEntity('mytable', deleteEntity, function(error, result, response) {
+ if(error) {
+ // Delete table entity error
+ } else {
+ // Delete table entity successfully
+ }
+});
+
+
+
Executable Example
+
After clicked the "Select" button on the table list, you are able to operate with the table entities under the selected table.
+
+
+
+
Step 6: Creating your JavaScript Application based on Azure Storage JavaScript Client Library
+
+ - Setting CORS rules for your selected Azure-Storage account table service.
+ - Including functional file(s) needed, such as "azure-storage.table.js" for table operation.
+ - Using keyword "AzureStorage.Table" to access to Azure storage JavaScript APIs for tables.
+ - Referring to API documents for detailed API definitions.
+
+
You can view the source code of this sample for detailed reference.
+
+
+
+
+
+
+
diff --git a/src/node_modules/azure-storage/browser/test/blob/blobservice-upload.js b/src/node_modules/azure-storage/browser/test/blob/blobservice-upload.js
new file mode 100644
index 0000000..9f9708e
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/test/blob/blobservice-upload.js
@@ -0,0 +1,411 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+var assert = require('assert');
+var TestSuite = require('../../../test/framework/test-suite');
+var testUtil = require('../../../test/framework/util');
+
+var suite = new TestSuite('blobservice-upload-browser');
+
+if (testUtil.isBrowser()) {
+ var azure = AzureStorage.Blob;
+ var containerNamesPrefix = 'upload-test-container-';
+ var blobNamesPrefix = 'upload-teset-blob-';
+ var containerName;
+ var blobName;
+
+ describe('BlobServiceUpload', function () {
+ before(function (done) {
+ blobService = azure.createBlobService(process.env['AZURE_STORAGE_CONNECTION_STRING']);
+ assert.notEqual(null, blobService, 'blobService should not be null');
+
+ containerName = suite.getName(containerNamesPrefix);
+ blobService.createContainerIfNotExists(containerName, function (err) {
+ assert.equal(err, null);
+ done();
+ });
+ });
+
+ after(function (done) {
+ blobService.deleteContainerIfExists(containerName, function (err) {
+ assert.equal(err, null);
+ done();
+ });
+ });
+
+ beforeEach(function () {
+ blobName = suite.getName(blobNamesPrefix);
+ });
+
+ afterEach(function () {
+ });
+
+ describe('createBlockBlobFromBrowserFile', function () {
+ it('upload block blob with invalid type should not work', function () {
+ try {
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, 'abcde', function (err, res, resp) { });
+ } catch (e) {
+ assert.notEqual(e, null);
+ }
+ });
+
+ it('upload block blob with md5 calculation should work', function (done) {
+ var size = 7 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, file, { storeBlobContentMD5: true }, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ assert.notEqual(res.contentSettings.contentMD5, null);
+ done();
+ });
+ });
+ });
+
+ it('upload block blob with 0 bytes should work', function (done) {
+ var size = 0;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.blobType, AzureStorage.Blob.Constants.BlobConstants.BlobTypes.BLOCK);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload block blob with 4 * 1024 * 1024 - 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 - 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload block blob with 4 * 1024 * 1024 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload block blob with 4 * 1024 * 1024 + 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 + 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload block blob with 128 * 1024 * 1024 bytes should work', function (done) {
+ var size = 128 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createBlockBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+ });
+
+ describe('createPageBlobFromBrowserFile', function () {
+ it('upload page blob with invalid type should not work', function () {
+ try {
+ blobService.createPageBlobFromBrowserFile(containerName, blobName, 'abcde', function (err, res, resp) { });
+ } catch (e) {
+ assert.notEqual(e, null);
+ }
+ });
+
+ it('upload page blob with md5 calculation should work', function (done) {
+ var size = 3 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createPageBlobFromBrowserFile(containerName, blobName, file, { storeBlobContentMD5: true }, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ assert.notEqual(res.contentSettings.contentMD5, null);
+ done();
+ });
+ });
+ });
+
+ it('upload page blob with 0 bytes should work', function (done) {
+ var file = testUtil.getBrowserFile(blobName, 0);
+ blobService.createPageBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.blobType, AzureStorage.Blob.Constants.BlobConstants.BlobTypes.PAGE);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, 0);
+ done();
+ });
+ });
+ });
+
+ it('upload page blob with 4 * 1024 * 1024 - 1 bytes should not work', function () {
+ var size = 4 * 1024 * 1024 - 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ try {
+ blobService.createPageBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) { });
+ } catch (e) {
+ assert.notEqual(e, null);
+ }
+ });
+
+ it('upload page blob with 4 * 1024 * 1024 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createPageBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload page blob with 128 * 1024 * 1024 bytes should work', function (done) {
+ var size = 128 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createPageBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+ });
+
+ describe('createAppendBlobFromBrowserFile', function () {
+ it('upload append blob with invalid type should not work', function () {
+ try {
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, 'abcde', function (err, res, resp) { });
+ } catch (e) {
+ assert.notEqual(e, null);
+ }
+ });
+
+ it('upload append blob with md5 calculation should work', function (done) {
+ var size = 7 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, { storeBlobContentMD5: true }, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ assert.notEqual(res.contentSettings.contentMD5, null);
+ done();
+ });
+ });
+ });
+
+ it('upload append blob with 0 bytes should work', function (done) {
+ var file = testUtil.getBrowserFile(blobName, 0);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.blobType, AzureStorage.Blob.Constants.BlobConstants.BlobTypes.APPEND);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, 0);
+ done();
+ });
+ });
+ });
+
+ it('upload append blob with 4 * 1024 * 1024 - 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 - 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload append blob with 4 * 1024 * 1024 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload append blob with 4 * 1024 * 1024 + 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 + 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload append blob with 128 * 1024 * 1024 bytes should work', function (done) {
+ var size = 128 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+ });
+
+ describe('appendFromBrowserFile', function () {
+ beforeEach(function (done) {
+ var size = 2 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.createAppendBlobFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('append blob with 0 bytes should work', function (done) {
+ var file = testUtil.getBrowserFile(blobName, 0);
+ blobService.appendFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.blobType, AzureStorage.Blob.Constants.BlobConstants.BlobTypes.APPEND);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, 2 * 1024 * 1024);
+ done();
+ });
+ });
+ });
+
+ it('append blob with 4 * 1024 * 1024 - 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 - 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.appendFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size + 2 * 1024 * 1024);
+ done();
+ });
+ });
+ });
+
+ it('append blob with 4 * 1024 * 1024 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.appendFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size + 2 * 1024 * 1024);
+ done();
+ });
+ });
+ });
+
+ it('append blob with 4 * 1024 * 1024 + 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 + 1;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.appendFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size + 2 * 1024 * 1024);
+ done();
+ });
+ });
+ });
+
+ it('append blob with 128 * 1024 * 1024 bytes should work', function (done) {
+ var size = 128 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(blobName, size);
+ blobService.appendFromBrowserFile(containerName, blobName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ blobService.getBlobProperties(containerName, blobName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, blobName);
+ assert.equal(res.contentLength, size + 2 * 1024 * 1024);
+ done();
+ });
+ });
+ });
+ });
+ });
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/test/bundle.js b/src/node_modules/azure-storage/browser/test/bundle.js
new file mode 100644
index 0000000..d2c913e
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/test/bundle.js
@@ -0,0 +1,62 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var browserify = require('browserify');
+var fs = require('fs');
+var path = require('path');
+
+var bs = browserify([
+ path.resolve(__dirname, '../../test/services/queue/queueservice-tests.js'),
+ path.resolve(__dirname, '../../test/services/table/tablebatch-tests.js'),
+ path.resolve(__dirname, '../../test/services/table/tabledatatype-tests.js'),
+ path.resolve(__dirname, '../../test/services/table/tablepayload-tests.js'),
+ path.resolve(__dirname, '../../test/services/table/tablequery-tests.js'),
+ path.resolve(__dirname, '../../test/services/table/tableservice-gb-tests.js'),
+ path.resolve(__dirname, '../../test/services/table/tableservice-tests.js'),
+ path.resolve(__dirname, '../../test/services/blob/blobservice-archive-tests.js'),
+ path.resolve(__dirname, '../../test/services/blob/blobservice-container-tests.js'),
+ path.resolve(__dirname, '../../test/services/blob/blobservice-lease-tests.js'),
+ path.resolve(__dirname, '../../test/services/blob/blobservice-sse-tests.js'),
+ path.resolve(__dirname, '../../test/services/blob/blobservice-tests.js'),
+ path.resolve(__dirname, '../../test/services/blob/blobservice-uploaddownload-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-directory-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-file-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-share-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-sharesnapshot-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-sse-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-tests.js'),
+ path.resolve(__dirname, '../../test/services/file/fileservice-uploaddownload-tests.js'),
+ path.resolve(__dirname, '../../test/common/connectionstringparsertests.js'),
+ path.resolve(__dirname, '../../test/common/secondarytests.js'),
+ path.resolve(__dirname, '../../test/common/servicesettingstests.js'),
+ path.resolve(__dirname, '../../test/common/servicestatstests.js'),
+ path.resolve(__dirname, '../../test/common/sharedkey-tests.js'),
+ path.resolve(__dirname, '../../test/common/storageserviceclienttests.js'),
+ path.resolve(__dirname, '../../test/common/storageservicesettingstests.js'),
+ path.resolve(__dirname, '../../test/common/filters/exponentialretrypolicyfilter-tests.js'),
+ path.resolve(__dirname, '../../test/common/filters/linearretrypolicyfilter-tests.js'),
+ path.resolve(__dirname, '../../test/common/util/iso8061date-tests.js'),
+ path.resolve(__dirname, '../../test/common/util/util-tests.js'),
+ path.resolve(__dirname, '../../test/common/util/validate-tests.js'),
+ path.resolve(__dirname, '../../test/azure-tests.js'),
+ path.resolve(__dirname, '../../test/accountsas-tests.js'),
+ path.resolve(__dirname, './file/fileservice-upload.js'),
+ path.resolve(__dirname, './blob/blobservice-upload.js')
+], { require: ['https'] }).bundle();
+
+bs.pipe(
+ fs.createWriteStream(path.resolve(__dirname, './browser.tests.bundled.js'))
+);
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/browser/test/file/fileservice-upload.js b/src/node_modules/azure-storage/browser/test/file/fileservice-upload.js
new file mode 100644
index 0000000..2514829
--- /dev/null
+++ b/src/node_modules/azure-storage/browser/test/file/fileservice-upload.js
@@ -0,0 +1,155 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+var assert = require('assert');
+var TestSuite = require('../../../test/framework/test-suite');
+var testUtil = require('../../../test/framework/util');
+
+var suite = new TestSuite('fileservice-upload-browser');
+
+if (testUtil.isBrowser()) {
+ var azure = AzureStorage.File;
+ var shareNamesPrefix = 'upload-test-share-';
+ var fileNamesPrefix = 'upload-test-file-';
+ var shareName;
+ var fileName;
+
+ describe('FileServiceUpload', function () {
+ before(function (done) {
+ fileService = azure.createFileService(process.env['AZURE_STORAGE_CONNECTION_STRING']);
+ assert.notEqual(null, fileService, 'FileService should not be null');
+
+ shareName = suite.getName(shareNamesPrefix);
+ fileService.createShareIfNotExists(shareName, function (err) {
+ assert.equal(err, null);
+ done();
+ });
+ });
+
+ after(function (done) {
+ fileService.deleteShareIfExists(shareName, function (err) {
+ assert.equal(err, null);
+ done();
+ });
+ });
+
+ beforeEach(function () {
+ fileName = suite.getName(fileNamesPrefix);
+ });
+
+ afterEach(function (done) {
+ fileService.deleteFileIfExists(shareName, '', fileName, function (err) {
+ assert.equal(err, null);
+ done();
+ });
+ });
+
+ describe('createFileFromBrowserFile', function () {
+ it('upload file with invalid type should not work', function () {
+ try {
+ fileService.createFileFromBrowserFile(shareName, '', fileName, 'abcde', function (err, res, resp) {});
+ } catch (e) {
+ assert.notEqual(e, null);
+ }
+ });
+
+ it('upload file with md5 calculation should work', function (done) {
+ var size = 33 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(fileName, size);
+ fileService.createFileFromBrowserFile(shareName, '', fileName, file, { storeFileContentMD5: true}, function (err, res, resp) {
+ assert.equal(err, null);
+ fileService.getFileProperties(shareName, '', fileName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, fileName);
+ assert.equal(res.contentLength, size);
+ assert.notEqual(res.contentSettings.contentMD5, null);
+ done();
+ });
+ });
+ });
+
+ it('upload file with 0 bytes should work', function (done) {
+ var file = testUtil.getBrowserFile(fileName, 0);
+ fileService.createFileFromBrowserFile(shareName, '', fileName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ fileService.getFileProperties(shareName, '', fileName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, fileName);
+ assert.equal(res.contentLength, 0);
+ done();
+ });
+ });
+ });
+
+ it('upload file with 4 * 1024 * 1024 - 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 - 1;
+ var file = testUtil.getBrowserFile(fileName, size);
+ fileService.createFileFromBrowserFile(shareName, '', fileName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ fileService.getFileProperties(shareName, '', fileName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, fileName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload file with 4 * 1024 * 1024 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(fileName, size);
+ fileService.createFileFromBrowserFile(shareName, '', fileName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ fileService.getFileProperties(shareName, '', fileName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, fileName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload file with 4 * 1024 * 1024 + 1 bytes should work', function (done) {
+ var size = 4 * 1024 * 1024 + 1;
+ var file = testUtil.getBrowserFile(fileName, size);
+ fileService.createFileFromBrowserFile(shareName, '', fileName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ fileService.getFileProperties(shareName, '', fileName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, fileName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+
+ it('upload file with 128 * 1024 * 1024 bytes should work', function (done) {
+ var size = 128 * 1024 * 1024;
+ var file = testUtil.getBrowserFile(fileName, size);
+ fileService.createFileFromBrowserFile(shareName, '', fileName, file, function (err, res, resp) {
+ assert.equal(err, null);
+ fileService.getFileProperties(shareName, '', fileName, function (err, res) {
+ assert.equal(err, null);
+ assert.equal(res.name, fileName);
+ assert.equal(res.contentLength, size);
+ done();
+ });
+ });
+ });
+ });
+ });
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/examples/samples/blobuploaddownloadsample.js b/src/node_modules/azure-storage/examples/samples/blobuploaddownloadsample.js
new file mode 100644
index 0000000..9a8ef73
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/blobuploaddownloadsample.js
@@ -0,0 +1,246 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* 1. Demonstrates how to upload all files from a given directory in parallel
+*
+* 2. Demonstrates how to download all files from a given blob container to a given destination directory.
+*
+* 3. Demonstrate making requests using AccessConditions.
+*/
+
+var fs = require('fs');
+
+var azure;
+if (fs.existsSync('absolute path to azure-storage.js')) {
+ azure = require('absolute path to azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+
+var container = 'updownsample3';
+var blob = 'updownsample';
+var blobAccess = 'updownaccesssample';
+
+var blobService = azure.createBlobService()
+ .withFilter(new azure.ExponentialRetryPolicyFilter());
+
+// optionally set a proxy
+/*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+};
+
+blobService.setProxy(proxy);
+*/
+
+function uploadSample() {
+ var processArguments = process.argv;
+ if (processArguments.length !== 4) {
+ console.log('Incorrect number of arguments. Should be: srcPath destPath');
+ process.exit(1);
+ }
+
+ var srcPath = processArguments[2];
+ var destPath = processArguments[3];
+
+ console.log('Starting blobuploaddownloadsample.');
+
+ // Create the container
+ createContainer(container, function () {
+
+ // Demonstrates how to upload all files from a given directoy
+ uploadBlobs(srcPath, container, function () {
+
+ // Demonstrates how to download all files from a given
+ // blob container to a given destination directory.
+ downloadBlobs(container, destPath, function () {
+
+ // Demonstrate making requests using AccessConditions.
+ useAccessCondition(container, function () {
+
+ // Delete the container
+ deleteContainer(container, function () {
+ console.log('Ending blobuploaddownloadsample.');
+ });
+ });
+ });
+ });
+ });
+}
+
+function createContainer (container, callback) {
+ // Create the container.
+ blobService.createContainerIfNotExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Created the container ' + container);
+ callback();
+ }
+ });
+}
+
+function uploadBlobs(sourceDirectoryPath, containerName, callback) {
+ console.log('Entering uploadBlobs.');
+
+ // validate directory is valid.
+ if (!fs.existsSync(sourceDirectoryPath)) {
+ console.log(sourceDirectoryPath + ' is an invalid directory path.');
+ } else {
+ // Search the directory and generate a list of files to upload.
+ walk(sourceDirectoryPath, function (error, files) {
+ if (error) {
+ console.log(error);
+ } else {
+ var finished = 0;
+
+ // generate and schedule an upload for each file
+ files.forEach(function (file) {
+ var blobName = file.replace(/^.*[\\\/]/, '');
+
+ blobService.createBlockBlobFromLocalFile(containerName, blobName, file, function (error) {
+ finished++;
+
+ if (error) {
+ console.log(error);
+ } else {
+ console.log(' Blob ' + blobName + ' upload finished.');
+
+ if (finished === files.length) {
+ // Wait until all workers complete and the blobs are uploaded to the server.
+ console.log('All files uploaded');
+ callback();
+ }
+ }
+ });
+ });
+ }
+ });
+ }
+}
+
+function downloadBlobs(containerName, destinationDirectoryPath, callback) {
+ console.log('Entering downloadBlobs.');
+
+ // Validate directory
+ if (!fs.existsSync(destinationDirectoryPath)) {
+ console.log(destinationDirectoryPath + ' does not exist. Attempting to create this directory...');
+ fs.mkdirSync(destinationDirectoryPath);
+ console.log(destinationDirectoryPath + ' created.');
+ }
+
+ // NOTE: does not handle pagination.
+ blobService.listBlobsSegmented(containerName, null, function (error, result) {
+ if (error) {
+ console.log(error);
+ } else {
+ var blobs = result.entries;
+ var blobsDownloaded = 0;
+
+ blobs.forEach(function (blob) {
+ blobService.getBlobToLocalFile(containerName, blob.name, destinationDirectoryPath + '/' + blob.name, function (error2) {
+ blobsDownloaded++;
+
+ if (error2) {
+ console.log(error2);
+ } else {
+ console.log(' Blob ' + blob.name + ' download finished.');
+
+ if (blobsDownloaded === blobs.length) {
+ // Wait until all workers complete and the blobs are downloaded
+ console.log('All files downloaded');
+ callback();
+ }
+ }
+ });
+ });
+ }
+ });
+}
+
+function useAccessCondition(containerName, callback) {
+ console.log('Entering useAccessCondition.');
+
+ // Create a blob.
+ blobService.createBlockBlobFromText(containerName, blobAccess, 'hello', function (error, blobInformation) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log(' Created the blob ' + blobInformation.name);
+ console.log(' Blob Etag is: ' + blobInformation.etag);
+
+ // Use the If-not-match ETag condition to access the blob. By
+ // using the IfNoneMatch condition we are asserting that the blob needs
+ // to have been modified in order to complete the request. In this
+ // sample no other client is accessing the blob, so this will fail as
+ // expected.
+ var options = { accessConditions: { EtagNonMatch: blobInformation.etag} };
+ blobService.createBlockBlobFromText(containerName, blobInformation.name, 'new hello', options, function (error2) {
+ if (error2 && error2.statusCode === 412 && error2.code === 'ConditionNotMet') {
+ console.log('Attempted to recreate the blob with the if-none-match access condition and got the expected exception.');
+ callback();
+ } else {
+ console.log(' Blob was incorrectly updated');
+ if (error2) {
+ console.log(error2);
+ }
+ }
+ });
+ }
+ });
+}
+
+function deleteContainer (container, callback) {
+ // Delete the container.
+ blobService.deleteContainerIfExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the container ' + container);
+ callback();
+ }
+ });
+}
+
+// Utility function
+
+var walk = function (dir, done) {
+ var results = [];
+ fs.readdir(dir, function (err, list) {
+ if (err) return done(err);
+ var i = 0;
+ (function next() {
+ var file = list[i++];
+ if (!file) return done(null, results);
+ file = dir + '/' + file;
+ fs.stat(file, function (err2, stat) {
+ if (stat && stat.isDirectory()) {
+ walk(file, function (err3, res) {
+ results = results.concat(res);
+ next();
+ });
+ } else {
+ results.push(file);
+ next();
+ }
+ });
+ })();
+ });
+};
+
+uploadSample();
diff --git a/src/node_modules/azure-storage/examples/samples/continuationsample.js b/src/node_modules/azure-storage/examples/samples/continuationsample.js
new file mode 100644
index 0000000..b58d3f3
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/continuationsample.js
@@ -0,0 +1,159 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* This sample demonstrates how to handle continuation tokens and virtual "pages" of results when performing a listing
+* operation on the blob service.
+*
+* This sample peformsthe following steps:
+*
+* 0. Create container.
+*
+* 1. Create 50 blobs.
+*
+* 2. List the first 10(page size) blobs.
+*
+* 3. Check whether there are more results.
+*
+* 4. Repeat 2 and 3 until complete.
+*
+*/
+
+var fs = require('fs');
+
+var azure;
+if (fs.existsSync('absolute path to azure-storage.js')) {
+ azure = require('absolute path to azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+
+var container = 'paginationsample';
+var blob = 'contsample';
+var blobs = [];
+
+var blobService = azure.createBlobService()
+ .withFilter(new azure.ExponentialRetryPolicyFilter());
+
+// optionally set a proxy
+/*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+};
+
+blobService.setProxy(proxy);
+*/
+
+var totalBlobsCount;
+var pageSize;
+
+function continuationSample () {
+ var processArguments = process.argv;
+ if (processArguments.length !== 4) {
+ console.log('Incorrect number of arguments. Should be: numBlobs pageSize [deleteContainer]\nTry: 51 10');
+ process.exit(1);
+ }
+
+ totalBlobsCount = parseInt(processArguments[2], 10);
+ pageSize = parseInt(processArguments[3], 10);
+
+ console.log('Starting continuationSample.');
+
+ // Create the container
+ createContainer(container, function () {
+
+ console.log('Entering createBlobs.');
+
+ // Upload blobs from text.
+ createBlobs(totalBlobsCount, function () {
+ var options = {
+ maxResults: pageSize,
+ include: 'metadata',
+ locationMode: azure.StorageUtilities.LocationMode.PRIMARY_THEN_SECONDARY
+ };
+
+ console.log('Entering listBlobs.');
+
+ // List blobs using continuation tokens.
+ listBlobs(options, null, function () {
+
+ // Delete the container
+ deleteContainer(container, function () {
+ console.log('Ending continuationSample.');
+ });
+ });
+ });
+ });
+}
+
+function createContainer (container, callback) {
+ // Create the container.
+ blobService.createContainerIfNotExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Created the container ' + container);
+ callback();
+ }
+ });
+}
+
+function createBlobs(currentBlobsCount, callback) {
+ // Upload totalBlobsCount blobs to the container.
+ var options = {};
+ options.metadata = {'hello':'world'};
+
+ blobService.createBlockBlobFromText(container, blob + currentBlobsCount, 'blob' + currentBlobsCount, options, function (error) {
+ if (error) {
+ console.log(error);
+ } else if (currentBlobsCount > 1) {
+ createBlobs(--currentBlobsCount, callback);
+ } else {
+ console.log(' Created ' + totalBlobsCount + ' blobs.');
+ callback();
+ }
+ });
+}
+
+function listBlobs (options, token, callback) {
+ blobService.listBlobsSegmented(container, token, options, function(error, result) {
+ blobs.push.apply(blobs, result.entries);
+ var token = result.continuationToken;
+ if(token) {
+ console.log(' Received a page of results. There are ' + result.entries.length + ' blobs on this page.');
+ listBlobs(options, token, callback);
+ }
+ else {
+ console.log(' Completed listing. There are ' + blobs.length + ' blobs');
+ callback();
+ }
+ });
+}
+
+function deleteContainer (container, callback) {
+ // Delete the container.
+ blobService.deleteContainerIfExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the container ' + container);
+ callback();
+ }
+ });
+}
+
+continuationSample();
diff --git a/src/node_modules/azure-storage/examples/samples/requestresponseeventssample.js b/src/node_modules/azure-storage/examples/samples/requestresponseeventssample.js
new file mode 100644
index 0000000..c5b6017
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/requestresponseeventssample.js
@@ -0,0 +1,96 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* Demonstrates how to define sendingrequest and receivedresponse event handlers.
+*/
+var fs = require('fs');
+
+var azure;
+if (fs.existsSync('absolute path to azure-storage.js')) {
+ azure = require('absolute path to azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+
+var container = 'sendingrequestevent3';
+
+// The service object which will define the event handlers
+var blobService = azure.createBlobService();
+
+// optionally set a proxy
+/*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+};
+
+blobService.setProxy(proxy);
+blobService2.setProxy(proxy);
+*/
+
+// the sending request event handler
+var sendingRequestHandler = function (webresource) {
+ webresource.withHeader('x-ms-custom-header', 'value');
+ console.log(' sending request event handler called');
+};
+
+// the response received event handler
+var responseReceivedHandler = function (response) {
+ console.log(' received response event handler called');
+};
+
+function eventHandlersSample () {
+ console.log('Starting eventHandlersSample.');
+
+ // set the event handlers
+ blobService.on('sendingRequestEvent', sendingRequestHandler);
+ blobService.on('receivedResponseEvent', responseReceivedHandler);
+
+ // create and delete a container with these handlers
+ createContainer(container, function () {
+ // Delete the container
+ deleteContainer(container, function () {
+ console.log('Ending eventHandlersSample.');
+ });
+ });
+}
+
+function createContainer (container, callback) {
+ // Create the container.
+ blobService.createContainer(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Created the container ' + container);
+ callback();
+ }
+ });
+}
+
+function deleteContainer (container, callback) {
+ // Delete the container.
+ blobService.deleteContainer(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the container ' + container);
+ callback();
+ }
+ });
+}
+
+eventHandlersSample();
diff --git a/src/node_modules/azure-storage/examples/samples/retrypolicysample.js b/src/node_modules/azure-storage/examples/samples/retrypolicysample.js
new file mode 100644
index 0000000..a359a84
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/retrypolicysample.js
@@ -0,0 +1,230 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* Demonstrates how to use pre-written retry policies and how to define a customized retry policy.
+*
+* In the sample for pre-written retry policies, we simply show how to use pre-written retry policies.
+*
+* In the sample for customized retry policy, we define a customized retry policy,
+* which retries on the "The specified container is being deleted" exception besides the server exceptions.
+*
+* Note that only in the cloud(not the storage emulator), "The specified container is being deleted" exceptions will be
+* sent if users immediately recreate a container after delete it.
+*/
+
+var fs = require('fs');
+if (!fs.existsSync) {
+ fs.existsSync = require('path').existsSync;
+}
+
+var azure;
+if (fs.existsSync('absolute path to azure-storage.js')) {
+ azure = require('absolute path to azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+
+var RetryPolicyFilter = azure.RetryPolicyFilter;
+var LocationMode = azure.StorageUtilities.LocationMode;
+
+var container = 'customretrypolicysample';
+
+var blobService;
+
+/**
+ * Demonstrate how to use pre-written retry policies.
+ * By default, no retry will be performed with service instances newly created.
+ * Several pre-written retry policies are available with modifiable settings,
+ * and can be used through associating filter.
+ */
+function setRetries() {
+ console.log('Starting Sample 1 - setRetries.');
+
+ // By default, no retry will be performed with all kinds of services created
+ // by Azure storage client library for Node.js.
+ var blobServiceWithoutRetry = azure.createBlobService();
+ console.log('BlobService instance created, no retry will be performed by default.');
+
+ // There are two pre-written retry policies: ExponentialRetryPolicyFilter
+ // and LinearRetryPolicyFilter can be used with modifiable settings.
+ // Use an exponential retry with customized settings.
+ var fileServiceWithExponentialRetry = azure.createFileService().withFilter(
+ new azure.ExponentialRetryPolicyFilter(
+ 3, // retryCount is set to 3 times.
+ 4000, // retryInterval is set to 4 seconds.
+ 3000, // minRetryInterval is set to 3 seconds.
+ 120000 // maxRetryInterval is set to 120 seconds.
+ ));
+ console.log('FileService instance created and associated with ExponentialRetryPolicyFilter.');
+ console.log(' Retries will be performed with exponential back-off.');
+
+ // Use a default linear retry policy.
+ var tableServiceWithLinearRetry = azure.createTableService().withFilter(
+ new azure.LinearRetryPolicyFilter()); // By default, retryCount is set to 3 times and retryInterval is set to 30 seconds.
+ console.log('TableService instance created and associated with LinearRetryPolicyFilter,');
+ console.log(' Retries will be performed with linear back-off.');
+
+ console.log('Ending Sample 1 - setRetries.');
+}
+
+/**
+ * Demonstrate how to use custom retry policy.
+ * Any custom retry logic may be used by simply creating and setting RetryPolicyFilter instance.
+ */
+function setCustomRetryPolicy() {
+ console.log('Starting Sample 2 - setCustomRetryPolicy.');
+
+ // Step 1 : Set the retry policy to customized retry policy which will
+ // not retry on any failing status code other than the excepted one.
+ var retryOnContainerBeingDeleted = new RetryPolicyFilter();
+ retryOnContainerBeingDeleted.retryCount = 5;
+ retryOnContainerBeingDeleted.retryInterval = 5000;
+
+ retryOnContainerBeingDeleted.shouldRetry = function (statusCode, retryData) {
+ console.log(' Made the request at ' + new Date().toUTCString() + ', received StatusCode: ' + statusCode);
+
+ var retryInfo = {};
+
+ // retries on any bad status code other than 409
+ if (statusCode >= 300 && statusCode !== 409 && statusCode !== 500) {
+ retryInfo.retryable = false;
+ } else {
+ var currentCount = (retryData && retryData.retryCount) ? retryData.retryCount : 0;
+
+ retryInfo = {
+ retryInterval: this.retryInterval + 2000 * currentCount,
+ retryable: currentCount < this.retryCount
+ };
+ }
+
+ return retryInfo;
+ };
+
+ blobService = azure.createBlobService().withFilter(retryOnContainerBeingDeleted);
+
+ // optionally set a proxy
+ /*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+ };
+
+ blobService.setProxy(proxy);*/
+
+
+ // Step 2: Create the container
+ createContainer(function () {
+
+ // Step 3: Fetch attributes from the container using LocationMode.SECONDARY_THEN_PRIMARY
+ fetchAttributesContainer(function () {
+
+ // Step 4: Lease the container
+ leaseContainer(function () {
+
+ // Step 5: Lease the container again, retrying until it succeeds
+ leaseContainer(function () {
+
+ // Step 6: Delete the container
+ deleteContainer(function () {
+ console.log('Ending Sample 2 - setCustomRetryPolicy.');
+ });
+ });
+ });
+ });
+ });
+}
+
+function createContainer(callback) {
+ console.log('Entering createContainer.');
+
+ // Create the container.
+ blobService.createContainerIfNotExists(container, function (error, containerResult) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log(' Container info ');
+ console.log(containerResult);
+ console.log('Created the container ' + container);
+ callback();
+ }
+ });
+}
+
+function fetchAttributesContainer(callback) {
+ console.log('Entering fetchAttributesContainer.');
+
+ var options = {
+ locationMode: LocationMode.SECONDARY_THEN_PRIMARY
+ };
+
+ // Get the properties of the container.
+ blobService.getContainerProperties(container, options, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Downloaded container properties from ' + container);
+ callback();
+ }
+ });
+}
+
+function leaseContainer(callback) {
+ console.log('Entering leaseContainer.');
+
+ // Try to acquire the lease.
+ blobService.acquireLease(container, null, {leaseDuration: 15}, function (error, lease) {
+ if (error) {
+ console.log(error);
+ }
+ else {
+ console.log('Acquired lease from ' + container + ' with leaseid' + lease.id);
+ callback();
+ }
+ });
+}
+
+function deleteContainer(callback) {
+ console.log('Entering deleteContainer.');
+
+ // Break the lease.
+ blobService.breakLease(container, null, {leaseBreakPeriod: 0}, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log(' Broke the lease on the container ' + container);
+ }
+
+ // Delete the container.
+ blobService.deleteContainer(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the container ' + container);
+ callback();
+ }
+ });
+ });
+}
+
+function runAllSamples() {
+ console.log("Starting retrypolicySample.");
+ setRetries();
+ setCustomRetryPolicy();
+ console.log("Ending retrypolicySample.");
+}
+
+runAllSamples();
diff --git a/src/node_modules/azure-storage/examples/samples/sassample.js b/src/node_modules/azure-storage/examples/samples/sassample.js
new file mode 100644
index 0000000..ee9ff15
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/sassample.js
@@ -0,0 +1,218 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* In this sample, we demonstrate how to generate and use the blob level shared access signature and the container level
+* shared access signature.
+*
+* In the blob level shared access signature sample, there are the following steps:
+*
+* 1. Create a container and a blob.
+*
+* 2. Generate a shared access signature for the blob and download the blob using it.
+*
+* 3. Upload a "ReadWrite" policy and a "Read" permission to the container.
+*
+* 4. Generate a shared access signature for the blob using the policy id and download the blob using it.
+*/
+
+var fs = require('fs');
+var assert = require('assert');
+
+var azure;
+if (fs.existsSync('../../lib/azure-storage.js')) {
+ azure = require('../../lib/azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+var BlobUtilities = azure.BlobUtilities;
+
+var container = 'container-sassample';
+var blob = 'blob-sassample';
+
+var blobService = azure.createBlobService();
+
+// optionally set a proxy
+/*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+};
+
+blobService.setProxy(proxy);
+blobService2.setProxy(proxy);
+*/
+
+function sasSample () {
+ console.log('Starting sasSample.');
+
+ // Create the container.
+ createContainer(function () {
+
+ // Create a blob.
+ createBlob( function () {
+
+ // Create a shared access signature and use it to download the blob just created.
+ downloadBlobUsingSharedAccessSignature(function () {
+
+ // Add Shared Access policies to the container
+ createPolicies(function () {
+
+ // Use the read policy just created
+ usePermissions(function () {
+
+ // Delete the container
+ deleteContainer(function () {
+ console.log('Ending sasSample.');
+ });
+ });
+ });
+ });
+ });
+ });
+}
+
+function createContainer (callback) {
+ // Create the container.
+ blobService.createContainerIfNotExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Created the container ' + container);
+ callback();
+ }
+ });
+}
+
+function createBlob (callback) {
+ // Create the blob
+ blobService.createBlockBlobFromText(container, blob, 'test blob', function (error) {
+ if (error) {
+ console.log(error);
+ }
+ else {
+ console.log('Created the blob ' + container);
+ callback();
+ }
+ });
+}
+
+function downloadBlobUsingSharedAccessSignature (callback) {
+ var startDate = new Date();
+ var expiryDate = new Date(startDate);
+ expiryDate.setMinutes(startDate.getMinutes() + 5);
+
+ var sharedAccessPolicy = {
+ AccessPolicy: {
+ Permissions: BlobUtilities.SharedAccessPermissions.READ,
+ Start: startDate,
+ Expiry: expiryDate
+ }
+ };
+
+ var sharedAccessSignatureToken = blobService.generateSharedAccessSignature(container, blob, sharedAccessPolicy);
+
+ var sharedBlobService = azure.createBlobServiceWithSas(blobService.host, sharedAccessSignatureToken);
+
+ // Download the blob by using the shared access signature URL.
+ sharedBlobService.getBlobProperties(container, blob, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Downloaded the blob ' + blob + ' by using the shared access signature URL: \n ' + sharedBlobService.getUrl(container, blob, sharedAccessSignatureToken));
+ }
+
+ callback();
+ });
+}
+
+function createPolicies (callback) {
+ // Create a "ReadWrite" policy and a "Read" policy.
+ var readWriteStartDate = new Date();
+ var readWriteExpiryDate = new Date(readWriteStartDate);
+ readWriteExpiryDate.setMinutes(readWriteStartDate.getMinutes() + 10);
+
+ var signedIdentifiers = {
+ readwrite: {
+ Start: readWriteStartDate,
+ Expiry: readWriteExpiryDate,
+ Permissions: 'rw'
+ },
+ read: {
+ Expiry: readWriteStartDate,
+ Permissions: 'r'
+ }
+ };
+
+ // Wait 30 seconds for the container acl to be processed
+ var func = function () {
+ var options = { publicAccessLevel: BlobUtilities.BlobContainerPublicAccessType.CONTAINER };
+ blobService.setContainerAcl(container, signedIdentifiers, options, function(error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Uploaded the permissions for the container ' + container);
+ callback();
+ }
+ });
+ };
+
+ setTimeout(func, 30000);
+}
+
+function usePermissions (callback) {
+ // Read, write the blob using the shared access signature from "ReadWrite" policy.
+ var readWriteAccessPolicy = {
+ Id: 'readwrite'
+ };
+
+ var headers = {
+ cacheControl: 'no-transform',
+ contentDisposition: 'attachment',
+ contentEncoding: 'gzip',
+ contentLanguage: 'tr,en',
+ contentType: 'text/html'
+ };
+
+ var sharedAccessSignatureToken = blobService.generateSharedAccessSignature(container, null, {Id: 'readwrite'}, headers);
+
+ var sharedBlobService = azure.createBlobServiceWithSas(blobService.host, sharedAccessSignatureToken);
+
+ sharedBlobService.getBlobProperties(container, blob, function (error, result) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Downloaded the blob ' + blob + ' by using the shared access signature URL: \n ' + sharedBlobService.getUrl(container, blob, sharedAccessSignatureToken));
+
+ }
+
+ callback();
+ });
+}
+
+function deleteContainer (callback) {
+ // Delete the container.
+ blobService.deleteContainerIfExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the container ' + container);
+ callback();
+ }
+ });
+}
+
+sasSample();
diff --git a/src/node_modules/azure-storage/examples/samples/snapshotsample.js b/src/node_modules/azure-storage/examples/samples/snapshotsample.js
new file mode 100644
index 0000000..b1069bf
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/snapshotsample.js
@@ -0,0 +1,219 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* This sample is used to provide an overview of blob snapshots and how to work with them.
+*
+* 1. Upload blocks and commit them.
+*
+* 2. Take a snapshot for that blob.
+*
+* 3. Re-upload one of the three blocks and commit them.
+*
+* 4. Get the snapshot.
+*
+* 5. List blobs including snapshots.
+*
+* 6. Delete the snapshot.
+*/
+
+var fs = require('fs');
+
+var azure;
+if (fs.existsSync('absolute path to azure-storage.js')) {
+ azure = require('absolute path to azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+
+var BlobUtilities = azure.BlobUtilities;
+
+var container = 'snapshotsample';
+var blob = 'snapshotsample';
+
+var blockList = ['b1', 'b2', 'b3'];
+var blockContent = ['content1', 'content2', 'content3'];
+var blockContentAlternative2 = 'alternative2';
+
+var blobService = azure.createBlobService();
+
+// optionally set a proxy
+/*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+};
+
+blobService.setProxy(proxy);*/
+
+function snapshotSample () {
+ var processArguments = process.argv;
+ if (processArguments.length !== 2) {
+ console.log('Incorrect number of arguments. No arguments should be given.');
+ process.exit(1);
+ }
+
+ console.log('Starting snapshotSample.');
+
+ // Create the container
+ createContainer(function () {
+
+ // Upload a blob
+ uploadBlockBlob(function () {
+
+ // Create a snapshot of the blob
+ createSnapshot(function (snapshot) {
+
+ // Update the blob
+ blockContent[1] = blockContentAlternative2;
+ uploadBlockBlob(function () {
+
+ // Create a snapshot of the modified blob
+ getSnapshotToText(snapshot, function () {
+
+ // List the blob and its snapshots
+ listSnapshots(function () {
+
+ // Delete the snapshots
+ deleteSnapshots(function () {
+
+ // Delete the container
+ deleteContainer(function () {
+ console.log('Ending snapshotSample.');
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+}
+
+function createContainer (callback) {
+ // Create the container.
+ blobService.createContainerIfNotExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Created the container ' + container);
+ callback();
+ }
+ });
+}
+
+function uploadBlockBlob(callback) {
+ // Upload 3 blocks and commit them.
+ var blocks = 0;
+ var blobCallbackCounter = function (block) {
+ ++blocks;
+ if (blocks === blockList.length) {
+ console.log(' Created ' + blocks + ' blocks.');
+
+ blobService.commitBlocks(container, blob, {LatestBlocks: blockList}, function (error4) {
+ if (error4) {
+ console.log(error4);
+ }
+ else {
+ console.log('Committed the blob ' + blob);
+ callback();
+ }
+ });
+ }
+ }
+
+ for(var i = 0; i < blockList.length; i++) {
+ console.log(' Uploading a block. ID: ' + blockList[i] + ' Content: ' + blockContent[i]);
+ blobService.createBlockFromText(blockList[i], container, blob, blockContent[i], blockContent[i].length, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ blobCallbackCounter();
+ }
+ });
+ }
+}
+
+function createSnapshot(callback) {
+ // Creates a snapshot.
+ blobService.createBlobSnapshot(container, blob, function (error, snapshot) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Created a snapshot for the blob ' + blob);
+ callback(snapshot);
+ }
+ });
+}
+
+function getSnapshotToText(snapshot, callback) {
+ // Gets a snapshot.
+ blobService.getBlobToText(container, blob, {snapshotId: snapshot}, function (error, text) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Snapshot ' + blob + '?' + snapshot + ' text: ' + text);
+ callback();
+ }
+ });
+}
+
+function listSnapshots (callback) {
+ // List the blobs, including snapshots
+ blobService.listBlobsSegmented(container, null, { include: BlobUtilities.BlobListingDetails.SNAPSHOTS }, function (error, results) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Listing the blobs under the container ' + container);
+
+ results.entries.forEach(function (blob) {
+ var snapshot = '';
+ if (blob.snapshot) {
+ snapshot = '; BlobSnapshot: ' + blob.snapshot;
+ }
+ console.log(' BlobName: ' + blob.name + snapshot);
+ });
+
+ callback();
+ }
+ });
+};
+
+function deleteSnapshots (callback) {
+ // Delete the snapshot.
+ blobService.deleteBlob(container, blob, { deleteSnapshots: BlobUtilities.SnapshotDeleteOptions.SNAPSHOTS_ONLY }, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the snapshots.');
+ callback();
+ }
+ });
+};
+
+function deleteContainer (callback) {
+ // Delete the container.
+ blobService.deleteContainerIfExists(container, function (error) {
+ if (error) {
+ console.log(error);
+ } else {
+ console.log('Deleted the container ' + container);
+ callback();
+ }
+ });
+}
+
+snapshotSample();
diff --git a/src/node_modules/azure-storage/examples/samples/tablequerysample.js b/src/node_modules/azure-storage/examples/samples/tablequerysample.js
new file mode 100644
index 0000000..477c9ec
--- /dev/null
+++ b/src/node_modules/azure-storage/examples/samples/tablequerysample.js
@@ -0,0 +1,165 @@
+var fs = require('fs');
+var assert = require('assert');
+var util = require('util');
+var http = require('http');
+
+var azure;
+if (fs.existsSync('absolute path to azure-storage.js')) {
+ azure = require('absolute path to azure-storage');
+} else {
+ azure = require('azure-storage');
+}
+
+var TableQuery = azure.TableQuery;
+var TableUtilities = azure.TableUtilities;
+var eg = TableUtilities.entityGenerator;
+
+var tableName = 'tablequerysample';
+var tableService = azure.createTableService();
+
+// optionally set a proxy
+/*var proxy = {
+ protocol: 'http:',
+ host: '127.0.0.1',
+ port: 8888
+};
+
+tableService.setProxy(proxy);*/
+
+var entity1 = {
+ PartitionKey: eg.String('partition1'),
+ RowKey: eg.String('row1'),
+ integerfield: eg.Int32(1),
+ stringfield: eg.String('stringfield value'),
+ longfield: eg.Int64('92233720368547758')
+};
+
+var entity2 = {
+ PartitionKey: eg.String('partition1'),
+ RowKey: eg.String('row2'),
+ stringfield: eg.String('stringfield value'),
+ longfield: eg.Int64('8547758')
+};
+
+function performTableQuery() {
+ // Create the table
+ tableService.createTable(tableName, function (error1) {
+ assert.equal(error1, null);
+
+ // Insert the entities
+ insertEntities(function() {
+
+ // Return all entities
+ queryAllEntities(function () {
+
+ // Return entities Where certain conditions are met
+ queryEntitiesWhere(function () {
+
+ // Return the Top n entities
+ queryEntitiesTop(function () {
+
+ // Return Select fields from entities
+ queryEntitiesSelect(function () {
+
+ // Delete the table
+ tableService.deleteTable(tableName, function (error2) {
+ assert.equal(error2, null);
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+}
+
+function insertEntities(callback) {
+ // insert the entities
+ tableService.insertEntity(tableName, entity1, function (error1) {
+ assert.equal(error1, null);
+ tableService.insertEntity(tableName, entity2, function (error2) {
+ assert.equal(error2, null);
+ callback();
+ });
+ });
+}
+
+function queryAllEntities(callback) {
+ // Select all fields
+ tableService.queryEntities(tableName, null, null, function (error, result) {
+ assert.equal(error, null);
+ assert.notEqual(result, null);
+ assert.notEqual(result.entries, null);
+
+ var entities = result.entries;
+ assert.equal(entities.length, 2);
+ var entityResult = entities[0];
+ assert.equal(entityResult.stringfield._, entity1.stringfield._);
+ assert.equal(entityResult.longfield._, entity1.longfield._);
+
+ callback();
+ });
+}
+
+function queryEntitiesWhere(callback) {
+ // Select only the entries where the longfield is great than 10,000,000
+
+ // equivalently: var tableQuery = new TableQuery().where('longfield == ?int64?', '10000000');
+ var tableQuery = new TableQuery().where(TableQuery.int64Filter('longfield', TableUtilities.QueryComparisons.GREATER_THAN, '10000000'));
+
+ tableService.queryEntities(tableName, tableQuery, null, function (error, result) {
+ assert.equal(error, null);
+ assert.notEqual(result, null);
+ assert.notEqual(result.entries, null);
+
+ var entities = result.entries;
+ assert.equal(entities.length, 1);
+
+ var entityResult = entities[0];
+ assert.equal(entityResult.longfield._, entity1.longfield._);
+
+ callback();
+ });
+}
+
+function queryEntitiesTop(callback) {
+ // Select only the top entry
+ var tableQuery = new TableQuery().top(1);
+
+ tableService.queryEntities(tableName, tableQuery, null, function (error, result) {
+ assert.equal(error, null);
+ assert.notEqual(result, null);
+ assert.notEqual(result.entries, null);
+
+ var entities = result.entries;
+ assert.equal(entities.length, 1);
+
+ var entityResult = entities[0];
+ assert.equal(entityResult.integerfield._, entity1.integerfield._);
+ assert.equal(entityResult.longfield._, entity1.longfield._);
+
+ callback();
+ });
+}
+
+function queryEntitiesSelect(callback) {
+ // Select specific field
+ var tableQuery = new TableQuery().select('integerfield');
+
+ tableService.queryEntities(tableName, tableQuery, null, function (error, result) {
+ assert.equal(error, null);
+ assert.notEqual(result, null);
+ assert.notEqual(result.entries, null);
+
+ var entities = result.entries;
+ assert.equal(entities.length, 2);
+
+ var entityResult = entities[0];
+ assert.equal(entityResult.integerfield._, entity1.integerfield._);
+ assert.equal(entityResult.longfield, undefined);
+
+ callback();
+ });
+}
+
+performTableQuery();
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/gruntfile.js b/src/node_modules/azure-storage/gruntfile.js
new file mode 100644
index 0000000..4abffa2
--- /dev/null
+++ b/src/node_modules/azure-storage/gruntfile.js
@@ -0,0 +1,71 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+module.exports = function(grunt) {
+ //init stuff
+ grunt.initConfig({
+
+ //jsdoc config
+ jsdoc: {
+ dist: {
+ src: [
+ 'README.md',
+ 'lib/azure-storage.js',
+ 'lib/common/filters/retrypolicyfilter.js',
+ 'lib/common/filters/linearretrypolicyfilter.js',
+ 'lib/common/filters/exponentialretrypolicyfilter.js',
+ 'lib/common/services/storageutilities.js',
+ 'lib/services/blob/blobservice.core.js',
+ 'lib/services/blob/blobservice.node.js',
+ 'lib/services/blob/blobservice.browser.js',
+ 'lib/services/blob/models/blobresult.js',
+ 'lib/services/blob/models/containerresult.js',
+ 'lib/services/blob/models/leaseresult.js',
+ 'lib/services/blob/blobutilities.js',
+ 'lib/services/queue/queueservice.js',
+ 'lib/services/queue/queuemessageencoder.js',
+ 'lib/services/queue/queueutilities.js',
+ 'lib/services/queue/models/queueresult.js',
+ 'lib/services/queue/models/queuemessageresult.js',
+ 'lib/services/table/tableservice.js',
+ 'lib/services/table/tablebatch.js',
+ 'lib/services/table/tablequery.js',
+ 'lib/services/table/tableutilities.js',
+ 'lib/services/file/fileservice.core.js',
+ 'lib/services/file/fileservice.node.js',
+ 'lib/services/file/fileservice.browser.js',
+ 'lib/services/file/fileutilities.js',
+ 'lib/services/file/models/shareresult.js',
+ 'lib/services/file/models/directoryresult.js',
+ 'lib/services/file/models/fileresult.js',
+ 'lib/common/services/storageserviceclient.js',
+ 'lib/common/diagnostics/logger.js'
+ ],
+ options: {
+ destination: 'docs',
+ template: 'node_modules/ink-docstrap/template',
+ configure: 'jsdoc/jsdoc.json'
+ }
+ }
+ },
+
+ });
+
+ grunt.loadNpmTasks('grunt-jsdoc');
+
+ grunt.registerTask('doc', ['jsdoc']);
+ grunt.registerTask('default', ['doc',]);
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/jsdoc/jsdoc.json b/src/node_modules/azure-storage/jsdoc/jsdoc.json
new file mode 100644
index 0000000..2737ecc
--- /dev/null
+++ b/src/node_modules/azure-storage/jsdoc/jsdoc.json
@@ -0,0 +1,27 @@
+{
+ "tags" : {
+ "allowUnknownTags" : true
+ },
+ "plugins" : ["plugins/markdown"],
+
+ "templates" : {
+ "cleverLinks" : false,
+ "monospaceLinks" : false,
+ "dateFormat" : "ddd MMM Do YYYY",
+ "outputSourceFiles" : true,
+ "outputSourcePath" : true,
+ "systemName" : "Microsoft Azure Storage Client Library for Node.js and JavaScript",
+ "footer" : "",
+ "navType" : "vertical",
+ "theme" : "cosmo",
+ "linenums" : true,
+ "collapseSymbols" : false,
+ "inverseNav" : true,
+ "highlightTutorialCode" : false,
+ "protocol": "fred://"
+ },
+ "markdown" : {
+ "parser" : "gfm",
+ "hardwrap" : true
+ }
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/karma.conf.js b/src/node_modules/azure-storage/karma.conf.js
new file mode 100644
index 0000000..342cc61
--- /dev/null
+++ b/src/node_modules/azure-storage/karma.conf.js
@@ -0,0 +1,90 @@
+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: [
+ 'browser/bundle/azure-storage.blob.js',
+ 'browser/bundle/azure-storage.table.js',
+ 'browser/bundle/azure-storage.queue.js',
+ 'browser/bundle/azure-storage.file.js',
+ 'browser/test/browser.tests.bundled.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: [
+ 'AZURE_STORAGE_CONNECTION_STRING',
+ 'AZURE_STORAGE_CONNECTION_STRING_SSE_ENABLED_ACCOUNT',
+ 'AZURE_STORAGE_CONNECTION_STRING_BLOB_ACCOUNT',
+ 'AZURE_STORAGE_CONNECTION_STRING_PREMIUM_ACCOUNT'
+ ],
+
+ // 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'
+ }
+ }
+ })
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/azure-storage.js b/src/node_modules/azure-storage/lib/azure-storage.js
new file mode 100644
index 0000000..9b74ade
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/azure-storage.js
@@ -0,0 +1,433 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var exports = module.exports;
+
+/**
+* Creates a connection string that can be used to create a service which runs on the storage emulator. The emulator must be downloaded separately.
+*
+* @param {string} [proxyUri] The proxyUri. By default, http://127.0.0.1
+* @return {string} A connection string representing the development storage credentials.
+* @example
+* var azure = require('azure-storage');
+* var devStoreCreds = azure.generateDevelopmentStorageCredentials();
+* var blobService = azure.createBlobService(devStoreCreds);
+*/
+exports.generateDevelopmentStorageCredentials = function (proxyUri) {
+ var devStore = 'UseDevelopmentStorage=true;';
+ if(proxyUri){
+ devStore += 'DevelopmentStorageProxyUri=' + proxyUri;
+ }
+
+ return devStore;
+};
+
+/**
+ * Table client exports.
+ * @ignore
+ */
+var TableService = require('./services/table/tableservice');
+
+exports.TableService = TableService;
+exports.TableQuery = require('./services/table/tablequery');
+exports.TableBatch = require('./services/table/tablebatch');
+exports.TableUtilities = require('./services/table/tableutilities');
+
+/**
+* Creates a new {@link TableService} object.
+* If no storageaccount or storageaccesskey are provided, the AZURE_STORAGE_CONNECTION_STRING and then the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY
+* environment variables will be used.
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @return {TableService} A new TableService object.
+*
+*/
+exports.createTableService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new TableService(storageAccountOrConnectionString, storageAccessKey, host);
+};
+
+/**
+* Creates a new {@link TableService} object using the host Uri and the SAS credentials provided.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} sasToken The Shared Access Signature token.
+* @return {TableService} A new TableService object with the SAS credentials.
+*/
+exports.createTableServiceWithSas = function (hostUri, sasToken) {
+ return new TableService(null, null, hostUri, sasToken);
+};
+
+/**
+ * Blob client exports.
+ * @ignore
+ */
+var BlobService = require('./services/blob/blobservice.node');
+
+exports.BlobService = BlobService;
+exports.BlobUtilities = require('./services/blob/blobutilities');
+
+/**
+* Creates a new {@link BlobService} object.
+* If no storageaccount or storageaccesskey are provided, the AZURE_STORAGE_CONNECTION_STRING and then the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY
+* environment variables will be used.
+*
+* @param {string} storageAccountOrConnectionString The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @return {BlobService} A new BlobService object.
+*/
+exports.createBlobService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new BlobService(storageAccountOrConnectionString, storageAccessKey, host, null);
+};
+
+/**
+* Creates a new {@link BlobService} object using the host Uri and the SAS credentials provided.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} sasToken The Shared Access Signature token.
+* @return {BlobService} A new BlobService object with the SAS credentials.
+*/
+exports.createBlobServiceWithSas = function (host, sasToken) {
+ return new BlobService(null, null, host, sasToken);
+};
+
+/**
+* Creates a new {@link BlobService} object using the host Uri and the {@link TokenCredential} provided, which supports OAuth.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {TokenCredential} tokenCredential The token credential object.
+* @return {BlobService} A new BlobService object with the {@link TokenCredential} object.
+*
+* @example
+* var azure = require('azure-storage');
+* var tokenCredential = new azure.TokenCredential('myOAuthAccessToken');
+* var blobService = azure.createBlobServiceWithTokenCredential('https://account.blob.core.windows.net', tokenCredential);
+* tokenCredential.set('updatedOAuthAccessToken');
+*/
+exports.createBlobServiceWithTokenCredential = function (host, tokenCredential) {
+ return new BlobService(null, null, host, null, null, tokenCredential);
+};
+
+/**
+* Creates a new {@link BlobService} object using the host uri and anonymous access.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @return {BlobService} A new BlobService object with the anonymous credentials.
+*/
+exports.createBlobServiceAnonymous = function (host) {
+ return new BlobService(null, null, host, null);
+};
+
+/**
+ * File client exports.
+ * @ignore
+ */
+var FileService = require('./services/file/fileservice.node');
+
+exports.FileService = FileService;
+exports.FileUtilities = require('./services/file/fileutilities');
+
+/**
+* Creates a new {@link FileService} object.
+* If no storageaccount or storageaccesskey are provided, the AZURE_STORAGE_CONNECTION_STRING and then the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY
+* environment variables will be used.
+*
+* @param {string} storageAccountOrConnectionString The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @return {FileService} A new FileService object.
+*/
+exports.createFileService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new FileService(storageAccountOrConnectionString, storageAccessKey, host);
+};
+
+/**
+* Creates a new {@link FileService} object using the host Uri and the SAS credentials provided.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} sasToken The Shared Access Signature token.
+* @return {FileService} A new FileService object with the SAS credentials.
+*/
+exports.createFileServiceWithSas = function (hostUri, sasToken) {
+ return new FileService(null, null, hostUri, sasToken);
+};
+
+/**
+ * Queue client exports.
+ * @ignore
+ */
+var QueueService = require('./services/queue/queueservice');
+
+exports.QueueService = QueueService;
+exports.QueueUtilities = require('./services/queue/queueutilities');
+exports.QueueMessageEncoder = require('./services/queue/queuemessageencoder');
+
+/**
+* Creates a new {@link QueueService} object.
+* If no storageaccount or storageaccesskey are provided, the AZURE_STORAGE_CONNECTION_STRING and then the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY
+* environment variables will be used.
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @return {QueueService} A new QueueService object.
+*/
+exports.createQueueService = function (storageAccountOrConnectionString, storageAccessKey, host) {
+ return new QueueService(storageAccountOrConnectionString, storageAccessKey, host);
+};
+
+/**
+* Creates a new {@link QueueService} object using the host Uri and the SAS credentials provided.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} sasToken The Shared Access Signature token.
+* @return {QueueService} A new QueueService object with the SAS credentials.
+*/
+exports.createQueueServiceWithSas = function(hostUri, sasToken) {
+ return new QueueService(null, null, hostUri, sasToken);
+};
+
+/**
+* Creates a new {@link QueueService} object using the host Uri and the {@link TokenCredential} provided, which supports OAuth.
+*
+* @param {string|object} host The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {TokenCredential} tokenCredential The TokenCredential object.
+* @return {QueueService} A new QueueService object with the {@link TokenCredential} object.
+*
+* @example
+* var azure = require('azure-storage');
+* var tokenCredential = new azure.TokenCredential('myOAuthAccessToken');
+* var queueService = azure.createQueueServiceWithTokenCredential('https://account.queue.core.windows.net', tokenCredential);
+* tokenCredential.set('updatedOAuthAccessToken');
+*/
+exports.createQueueServiceWithTokenCredential = function (host, tokenCredential) {
+ return new QueueService(null, null, host, null, null, tokenCredential);
+};
+
+/**
+* Account SAS
+* @ignore
+*/
+
+var azureCommon = require('./common/common.node');
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var SharedKey = azureCommon.SharedKey;
+/**
+* Generates an account shared access signature token
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {SharedAccessServices} sharedAccessPolicy.AccessPolicy.Services The services (blob, file, queue, table) for a shared access signature associated with this shared access policy.
+* Refer to `Constants.AccountSasConstants.Services`.
+* @param {SharedAccessResourceTypes} sharedAccessPolicy.AccessPolicy.ResourceTypes The resource type for a shared access signature associated with this shared access policy.
+* Refer to `Constants.AccountSasConstants.ResourceTypes`.
+* @param {SharedAccessPermissions} sharedAccessPolicy.AccessPolicy.Permissions The permissions for a shared access signature.
+* Refer to `Constants.AccountSasConstants.Permissions`.
+* @param {date} sharedAccessPolicy.AccessPolicy.Start The time at which the Shared Access Signature becomes valid.
+* @param {date} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired.
+* @param {string} sharedAccessPolicy.AccessPolicy.IPAddressOrRange The permission type. Refer to `Constants.AccountSasConstants.ResourceTypes`.
+* @param {string} sharedAccessPolicy.AccessPolicy.Protocols The possible protocols. Refer to `Constants.AccountSasConstants.ResourceTypes`.
+*/
+exports.generateAccountSharedAccessSignature = function(storageAccountOrConnectionString, storageAccessKey, sharedAccessAccountPolicy)
+{
+ var storageSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey);
+ var sharedKey = new SharedKey(storageSettings._name, storageSettings._key);
+
+ return sharedKey.generateAccountSignedQueryString(sharedAccessAccountPolicy);
+};
+
+
+/**
+* A callback that returns a response object.
+* @callback errorOrResponse
+* @param {object} error If an error occurs, will contain information about the error.
+* @param {object} response Contains information about the response returned for the operation.
+* For example, HTTP status codes and headers.
+*/
+
+/**
+* A callback that returns result and response objects.
+* @callback errorOrResult
+* @param {object} error If an error occurs, will contain information about the error.
+* @param {object} result The result of the operation.
+* @param {object} response Contains information about the response returned for the operation.
+* For example, HTTP status codes and headers.
+*/
+
+
+/**
+* Specifying conditional headers for blob service operations. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
+* @typedef {object} AccessConditions
+* @property {string} EtagMatch If the ETag for the blob matches the specified ETag.
+* Specify the wildcard character (*) to perform the operation only if the resource does exist, and fail the operation if it does not exist.
+* @property {string} EtagNonMatch If the ETag for the blob does not match the specified ETag.
+* Specify the wildcard character (*) to perform the operation only if the resource does not exist, and fail the operation if it does exist.
+* @property {Date|string} DateModifedSince If the blob has been modified since the specified date.
+* @property {Date|string} DateUnModifiedSince If the blob has not been modified since the specified date.
+* @property {Number|string} SequenceNumberLessThanOrEqual If the blob's sequence number is less than or equal to the specified value.
+* For Put Page operation only. See https://msdn.microsoft.com/en-us/library/azure/ee691975.aspx for more information.
+* @property {Number|string} SequenceNumberLessThan If the blob's sequence number is less than the specified value.
+* For Put Page operation only. See https://msdn.microsoft.com/en-us/library/azure/ee691975.aspx for more information.
+* @property {Number|string} SequenceNumberEqual If the blob's sequence number is equal to the specified value.
+* For Put Page operation only. See https://msdn.microsoft.com/en-us/library/azure/ee691975.aspx for more information.
+* @property {Number|string} MaxBlobSize If the Append Block operation would cause the blob to exceed that limit or if the blob size is already greater than the specified value.
+* For Append Block operation only. See https://msdn.microsoft.com/en-us/library/mt427365.aspx for more information.
+* @property {Number|string} MaxAppendPosition If the append position is equal to the specified value.
+* For Append Block operation only. See https://msdn.microsoft.com/en-us/library/mt427365.aspx for more information.
+*/
+
+/**
+* The properties of a storage service, including properties of Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.
+* @typedef {object} ServiceProperties
+* @property {string} DefaultServiceVersion The default version of Storage Analytics currently in use.
+* @property {LoggingProperties} Logging The Logging settings.
+* @property {MetricsProperties} HourMetrics The HourMetrics settings provide a summary of request statistics grouped by API in hourly aggregates.
+* @property {MetricsProperties} MinuteMetrics The HourMetrics settings provide request statistics grouped by API for each minute.
+* @property {object} Cors Groups all CORS rules.
+* @property {CorsRule[]} Cors.CorsRules Groups settings for a `[CORS rule]{@link CorsRule}`.
+*/
+
+/**
+* The properties of a storage account.
+* @typedef {object} AccountProperties
+* @property {string} SkuName The header that specifies storage SKU, also known as account type.
+* @property {string} AccountKind The header that describes the flavour of the storage account, also known as account kind.
+*/
+
+/**
+* The properties of a blob storage service, including properties of Storage Analytics, CORS (Cross-Origin Resource Sharing) rules and Static Webiste configurations.
+* @typedef {object} BlobServiceProperties
+* @property {string} DefaultServiceVersion The default version of Storage Analytics currently in use.
+* @property {LoggingProperties} Logging The Logging settings.
+* @property {MetricsProperties} HourMetrics The HourMetrics settings provide a summary of request statistics grouped by API in hourly aggregates.
+* @property {MetricsProperties} MinuteMetrics The HourMetrics settings provide request statistics grouped by API for each minute.
+* @property {StaticWebsiteProperties} StaticWebsite The Azure Static Website settings.
+* @property {object} Cors Groups all CORS rules.
+* @property {CorsRule[]} Cors.CorsRules Groups settings for a `[CORS rule]{@link CorsRule}`.
+*/
+
+/**
+* The Azure Static Website settings.
+* @typedef {object} StaticWebsiteProperties
+* @property {boolean} Enabled Whether feature of Static Website is enabled.
+* @property {string} IndexDocument Indicates index document page path.
+* @property {string} ErrorDocument404Path Indicates 404 document page path.
+*/
+
+/**
+* The Azure Analytics logging settings.
+* @typedef {object} LoggingProperties
+* @property {string} Version The version of Storage Analytics currently in use for logging.
+* @property {boolean} Delete Indicates whether delete requests are being logged.
+* @property {boolean} Read Indicates whether read requests are being logged.
+* @property {boolean} Write Indicates whether write requests are being logged.
+* @property {RetentionPolicy} RetentionPolicy The retention policy of the log data.
+*/
+
+/**
+* The setting of Azure Analytics summary of request stastics.
+* @typedef {object} MetricsProperties
+* @property {string} Version The version of Storage Analytics currently in use for hour metrics.
+* @property {string} Enabled Indicates whether metrics are enabled
+* @property {boolean} IncludeAPIs Indicates whether metrics generate summary statistics for called API operations.
+* @property {RetentionPolicy} RetentionPolicy The retention policy of the metrics data.
+*/
+
+/**
+* The CORS rule of a storage service.
+* @typedef {object} CorsRule
+* @property {string[]} AllowedMethods A list of HTTP methods that are allowed to be executed by the origin. For Azure Storage, permitted methods are DELETE, GET, HEAD, MERGE, POST, OPTIONS or PUT.
+* @property {string[]} AllowedOrigins A list of origin domains that are allowed via CORS, or "*" if all domains are allowed.
+* @property {string[]} AllowedHeaders A list of headers allowed to be part of the cross-origin request.
+* @property {string[]} ExposedHeaders A list of response headers to expose to CORS clients.
+* @property {number} MaxAgeInSeconds The number of seconds that the client/browser should cache a preflight response.
+*/
+
+/**
+* The Azure Analytics logging or metrics retention policy.
+* @typedef {object} RetentionPolicy
+* @property {boolean} Enabled Indicates whether a retention policy is enabled for the storage service.
+* @property {number} Days Indicates the number of days that logging data is retained. All data older than this value will be deleted.
+*/
+
+/**
+* The access policy.
+* @typedef {object} AccessPolicy
+* @property {string} Permissions The permission type.
+* @property {Date} Start The time at which the access policy becomes valid.
+* @property {Date} Expiry The time at which the access policy becomes expired.
+* @property {string} IPAddressOrRange An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @property {string} Protocols The protocols permitted for a request made with the SAS.
+* @property {string} Services The services (blob, file, queue, table) for a shared access signature associated with this shared access policy.
+* @property {string} ResourceTypes The resource type for a shared access signature associated with this shared access policy.
+*/
+
+/**
+* The service statistics.
+* @typedef {object} ServiceStats
+* @property {object} GeoReplication The geo replication stastics.
+* @property {string} GeoReplication.Status The status of the secondary location.
+* @property {Date} GeoReplication.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.
+*/
+
+/**
+* The range.
+* @typedef {object} Range
+* @property {number} start The start of the range.
+* @property {number} end The end of the range.
+*/
+
+/**
+* The range diff. Refer to https://msdn.microsoft.com/en-us/library/azure/mt736912.aspx
+* @typedef {object} RangeDiff
+* @property {number} start The start of the range.
+* @property {number} end The end of the range.
+* @property {boolean} isCleared If the range is cleared or not.
+
+*/
+
+exports.Constants = azureCommon.Constants;
+exports.StorageUtilities = azureCommon.StorageUtilities;
+exports.AccessCondition = azureCommon.AccessCondition;
+
+exports.SR = azureCommon.SR;
+exports.StorageServiceClient = StorageServiceClient;
+exports.Logger = azureCommon.Logger;
+exports.WebResource = azureCommon.WebResource;
+exports.Validate = azureCommon.validate;
+exports.date = azureCommon.date;
+exports.TokenCredential = azureCommon.TokenCredential;
+
+// Other filters
+exports.LinearRetryPolicyFilter = azureCommon.LinearRetryPolicyFilter;
+exports.ExponentialRetryPolicyFilter = azureCommon.ExponentialRetryPolicyFilter;
+exports.RetryPolicyFilter = azureCommon.RetryPolicyFilter;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/common.browser.js b/src/node_modules/azure-storage/lib/common/common.browser.js
new file mode 100644
index 0000000..ebea0f5
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/common.browser.js
@@ -0,0 +1,21 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var azureCommon = require('./common.core');
+
+azureCommon.BrowserFileReadStream = require('./streams/browserfilereadstream');
+
+module.exports = azureCommon;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/common.core.js b/src/node_modules/azure-storage/lib/common/common.core.js
new file mode 100644
index 0000000..1865cd0
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/common.core.js
@@ -0,0 +1,68 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var exports = module.exports;
+
+var azureutil = require('./util/util');
+
+require('./util/patch-xmlbuilder');
+
+var nodeVersion = azureutil.getNodeVersion();
+if (nodeVersion.major === 0 && nodeVersion.minor > 8 && !(nodeVersion.minor > 10 || (nodeVersion.minor === 10 && nodeVersion.patch >= 3))) {
+ throw new Error('The Microsoft Azure node SDK does not work with node versions > 0.9.0 and < 0.10.3. Please upgrade to node >= 0.10.3');
+}
+
+exports.xmlbuilder = require('xmlbuilder');
+exports.xml2js = require('xml2js');
+
+exports.Logger = require('./diagnostics/logger');
+exports.WebResource = require('./http/webresource');
+
+// Services
+exports.StorageServiceClient = require('./services/storageserviceclient');
+
+// Models
+exports.ServicePropertiesResult = require('./models/servicepropertiesresult');
+exports.ServiceStatsParser = require('./models/servicestatsparser');
+exports.AclResult = require('./models/aclresult');
+exports.TokenCredential = require('./models/tokencredential');
+
+// Filters
+exports.LinearRetryPolicyFilter = require('./filters/linearretrypolicyfilter');
+exports.ExponentialRetryPolicyFilter = require('./filters/exponentialretrypolicyfilter');
+exports.RetryPolicyFilter = require('./filters/retrypolicyfilter');
+
+// Signing
+exports.SharedAccessSignature = require('./signing/sharedaccesssignature');
+exports.SharedKey = require('./signing/sharedkey');
+
+// Streams
+exports.BatchOperation = require('./streams/batchoperation');
+exports.ChunkAllocator = require('./streams/chunkallocator');
+exports.ChunkStream = require('./streams/chunkstream');
+exports.ChunkStreamWithStream = require('./streams/chunkstreamwithstream');
+exports.SpeedSummary = require('./streams/speedsummary');
+exports.BufferStream = require('./streams/bufferstream');
+
+// Utilities
+exports.Constants = require('./util/constants');
+exports.SR = require('./util/sr');
+exports.date = require('./util/date');
+exports.ISO8061Date = require('./util/iso8061date');
+exports.util = require('./util/util');
+exports.validate = require('./util/validate');
+exports.StorageUtilities = require('./util/storageutilities');
+exports.AccessCondition = require('./util/accesscondition');
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/common.node.js b/src/node_modules/azure-storage/lib/common/common.node.js
new file mode 100644
index 0000000..d2a38d4
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/common.node.js
@@ -0,0 +1,22 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var azureCommon = require('./common.core');
+
+// Streams
+azureCommon.FileReadStream = require('./streams/filereadstream');
+
+module.exports = azureCommon;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/diagnostics/logger.js b/src/node_modules/azure-storage/lib/common/diagnostics/logger.js
new file mode 100644
index 0000000..7ba28c6
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/diagnostics/logger.js
@@ -0,0 +1,148 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* Creates a new Logger object
+* @class
+* The Logger class is used to write log information.
+*
+* @constructor
+*
+* @param {string} [level] The log level. Refer to Logger.LogLevels.
+* @param {object} [loggerFunction] The function to write log information.
+*/
+function Logger(level, loggerFunction) {
+ /**
+ * The log level. Refer to the Logger.LogLevels for available log levels.
+ * @name Logger#level
+ * @type {string}
+ * @see Logger.LogLevels
+ */
+ this.level = level;
+
+ this.loggerFunction = loggerFunction;
+
+ if (!this.loggerFunction) {
+ this.loggerFunction = this.defaultLoggerFunction;
+ }
+}
+
+/**
+* The available log levels.
+*
+* @const
+* @enum {string}
+*/
+Logger.LogLevels = {
+ /**
+ * System is unusable.
+ */
+ EMERGENCY: 'emergency',
+
+ /**
+ * Action must be taken immediately.
+ */
+ ALERT : 'alert',
+
+ /**
+ * Critical condition.
+ */
+ CRITICAL : 'critical',
+
+ /**
+ * Error condition.
+ */
+ ERROR : 'error',
+
+ /**
+ * Warning condition.
+ */
+ WARNING : 'warning',
+
+ /**
+ * Normal but significant condition.
+ */
+ NOTICE : 'notice',
+
+ /**
+ * Purely informational message.
+ */
+ INFO : 'info',
+
+ /**
+ * Application debug messages.
+ */
+ DEBUG : 'debug'
+};
+
+Logger.logPriority = [
+ Logger.LogLevels.EMERGENCY,
+ Logger.LogLevels.ALERT,
+ Logger.LogLevels.CRITICAL,
+ Logger.LogLevels.ERROR,
+ Logger.LogLevels.WARNING,
+ Logger.LogLevels.NOTICE,
+ Logger.LogLevels.INFO,
+ Logger.LogLevels.DEBUG
+];
+
+Logger.prototype.log = function (level, msg) {
+ this.loggerFunction(level, msg);
+};
+
+Logger.prototype.emergency = function(msg) {
+ this.log(Logger.LogLevels.EMERGENCY, msg);
+};
+
+Logger.prototype.critical = function(msg) {
+ this.log(Logger.LogLevels.CRITICAL, msg);
+};
+
+Logger.prototype.alert = function(msg) {
+ this.log(Logger.LogLevels.ALERT, msg);
+};
+
+Logger.prototype.error = function(msg) {
+ this.log(Logger.LogLevels.ERROR, msg);
+};
+
+Logger.prototype.warn = function(msg) {
+ this.log(Logger.LogLevels.WARNING, msg);
+};
+
+Logger.prototype.notice = function(msg) {
+ this.log(Logger.LogLevels.NOTICE, msg);
+};
+
+Logger.prototype.info = function(msg) {
+ this.log(Logger.LogLevels.INFO, msg);
+};
+
+Logger.prototype.debug = function(msg) {
+ this.log(Logger.LogLevels.DEBUG, msg);
+};
+
+Logger.prototype.defaultLoggerFunction = function(logLevel , msg) {
+ var currentLevelIndex = Logger.logPriority.indexOf(this.level);
+ var logLevelIndex = Logger.logPriority.indexOf(logLevel);
+ var time = new Date();
+ var timeStamp = time.toISOString();
+ if (logLevelIndex <= currentLevelIndex) {
+ console.log('[' + timeStamp + ']' + this.level + ' : ' + msg);
+ }
+};
+
+module.exports = Logger;
diff --git a/src/node_modules/azure-storage/lib/common/errors/errors.js b/src/node_modules/azure-storage/lib/common/errors/errors.js
new file mode 100644
index 0000000..1e8e852
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/errors/errors.js
@@ -0,0 +1,68 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var util = require('util');
+var _ = require('underscore');
+
+function captureStackTrace(targetObject, constructorOpt) {
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(targetObject, constructorOpt);
+ }
+}
+
+function ArgumentError(argumentName, message) {
+ captureStackTrace(this, this.constructor);
+ this.name = this.constructor.name;
+ this.argumentName = argumentName;
+ this.message = message || util.format('Invalid or missing argument supplied: %s', argumentName);
+}
+util.inherits(ArgumentError, Error);
+
+function ArgumentNullError(argumentName, message) {
+ captureStackTrace(this, this.constructor);
+ this.name = this.constructor.name;
+ this.argumentName = argumentName;
+ this.message = message || util.format('Missing argument: %s', argumentName);
+}
+
+util.inherits(ArgumentNullError, Error);
+
+function StorageError(message, properties) {
+ captureStackTrace(this, this.constructor);
+ this.name = this.constructor.name;
+ this.message = message;
+
+ if(properties){
+ _.extend(this, properties);
+ }
+}
+
+util.inherits(StorageError, Error);
+
+function TimeoutError(message) {
+ captureStackTrace(this, this.constructor);
+ this.name = this.constructor.name;
+ this.message = message;
+}
+
+util.inherits(TimeoutError, Error);
+
+module.exports.ArgumentError = ArgumentError;
+module.exports.ArgumentNullError = ArgumentNullError;
+module.exports.StorageError = StorageError;
+module.exports.TimeoutError = TimeoutError;
+module.exports.captureStackTrace = captureStackTrace;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/filters/exponentialretrypolicyfilter.js b/src/node_modules/azure-storage/lib/common/filters/exponentialretrypolicyfilter.js
new file mode 100644
index 0000000..ce269d0
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/filters/exponentialretrypolicyfilter.js
@@ -0,0 +1,95 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+'use strict';
+
+var RetryPolicyFilter = require('./retrypolicyfilter');
+/**
+* Creates a new 'ExponentialRetryPolicyFilter' instance.
+* @class
+* The ExponentialRetryPolicyFilter allows you to retry operations,
+* using an exponential back-off interval between retries.
+* To apply a filter to service operations, use `withFilter`
+* and specify the filter to be used when creating a service.
+* @constructor
+* @param {number} [retryCount=3] The client retry count.
+* @param {number} [retryInterval=30000] The client retry interval, in milliseconds.
+* @param {number} [minRetryInterval=3000] The minimum retry interval, in milliseconds.
+* @param {number} [maxRetryInterval=90000] The maximum retry interval, in milliseconds.
+*
+* @example
+* var azure = require('azure-storage');
+* var retryOperations = new azure.ExponentialRetryPolicyFilter();
+* var blobService = azure.createBlobService().withFilter(retryOperations)
+*/
+function ExponentialRetryPolicyFilter(retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
+ this.retryCount = retryCount ? retryCount : ExponentialRetryPolicyFilter.DEFAULT_CLIENT_RETRY_COUNT;
+ this.retryInterval = retryInterval ? retryInterval : ExponentialRetryPolicyFilter.DEFAULT_CLIENT_RETRY_INTERVAL;
+ this.minRetryInterval = minRetryInterval ? minRetryInterval : ExponentialRetryPolicyFilter.DEFAULT_CLIENT_MIN_RETRY_INTERVAL;
+ this.maxRetryInterval = maxRetryInterval ? maxRetryInterval : ExponentialRetryPolicyFilter.DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
+}
+
+/**
+* Represents the default client retry interval, in milliseconds.
+*/
+ExponentialRetryPolicyFilter.DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
+
+/**
+* Represents the default client retry count.
+*/
+ExponentialRetryPolicyFilter.DEFAULT_CLIENT_RETRY_COUNT = 3;
+
+/**
+* Represents the default maximum retry interval, in milliseconds.
+*/
+ExponentialRetryPolicyFilter.DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
+
+/**
+* Represents the default minimum retry interval, in milliseconds.
+*/
+ExponentialRetryPolicyFilter.DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
+
+/**
+ * Determines if the operation should be retried and how long to wait until the next retry.
+ *
+ * @param {number} statusCode The HTTP status code.
+ * @param {object} requestOptions The request options.
+ * @return {retryInfo} Information about whether the operation qualifies for a retry and the retryInterval.
+ */
+ExponentialRetryPolicyFilter.prototype.shouldRetry = function (statusCode, requestOptions) {
+ var retryData = (requestOptions && requestOptions.retryContext) ? requestOptions.retryContext : {};
+
+ // Adjust retry interval
+ var incrementDelta = Math.pow(2, retryData.retryCount) - 1;
+ var boundedRandDelta = this.retryInterval * 0.8 + Math.floor(Math.random() * (this.retryInterval * 1.2 - this.retryInterval * 0.8));
+ incrementDelta *= boundedRandDelta;
+
+ retryData.retryInterval = Math.min(this.minRetryInterval + incrementDelta, this.maxRetryInterval);
+
+ return RetryPolicyFilter._shouldRetryOnError(statusCode, requestOptions);
+};
+
+/**
+* Handles an operation with an exponential retry policy.
+*
+* @param {Object} requestOptions The original request options.
+* @param {function} next The next filter to be handled.
+*/
+ExponentialRetryPolicyFilter.prototype.handle = function (requestOptions, next) {
+ RetryPolicyFilter._handle(this, requestOptions, next);
+};
+
+module.exports = ExponentialRetryPolicyFilter;
diff --git a/src/node_modules/azure-storage/lib/common/filters/linearretrypolicyfilter.js b/src/node_modules/azure-storage/lib/common/filters/linearretrypolicyfilter.js
new file mode 100644
index 0000000..9342dfa
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/filters/linearretrypolicyfilter.js
@@ -0,0 +1,75 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+'use strict';
+
+var RetryPolicyFilter = require('./retrypolicyfilter');
+
+/**
+* Creates a new LinearRetryPolicyFilter instance.
+* @class
+* The LinearRetryPolicyFilter allows you to retry operations,
+* using an linear back-off interval between retries.
+* To apply a filter to service operations, use `withFilter`
+* and specify the filter to be used when creating a service.
+* @constructor
+* @param {number} [retryCount=3] The client retry count.
+* @param {number} [retryInterval=30000] The client retry interval, in milliseconds.
+*
+* @example
+* var azure = require('azure-storage');
+* var retryOperations = new azure.LinearRetryPolicyFilter();
+* var blobService = azure.createBlobService().withFilter(retryOperations)
+*/
+function LinearRetryPolicyFilter(retryCount, retryInterval) {
+ this.retryCount = retryCount ? retryCount : LinearRetryPolicyFilter.DEFAULT_CLIENT_RETRY_COUNT;
+ this.retryInterval = retryInterval ? retryInterval : LinearRetryPolicyFilter.DEFAULT_CLIENT_RETRY_INTERVAL;
+}
+
+/**
+* Represents the default client retry interval, in milliseconds.
+*/
+LinearRetryPolicyFilter.DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
+
+/**
+* Represents the default client retry count.
+*/
+LinearRetryPolicyFilter.DEFAULT_CLIENT_RETRY_COUNT = 3;
+
+/**
+* Determines if the operation should be retried and how long to wait until the next retry.
+*
+ * @param {number} statusCode The HTTP status code.
+ * @param {object} requestOptions The request options.
+ * @return {retryInfo} Information about whether the operation qualifies for a retry and the retryInterval.
+*/
+LinearRetryPolicyFilter.prototype.shouldRetry = function (statusCode, requestOptions) {
+ var retryData = (requestOptions && requestOptions.retryContext) ? requestOptions.retryContext : {};
+ retryData.retryInterval = this.retryInterval;
+
+ return RetryPolicyFilter._shouldRetryOnError(statusCode, requestOptions);
+};
+
+/**
+* Handles an operation with a linear retry policy.
+*
+* @param {Object} requestOptions The original request options.
+* @param {function} next The next filter to be handled.
+*/
+LinearRetryPolicyFilter.prototype.handle = function (requestOptions, next) {
+ RetryPolicyFilter._handle(this, requestOptions, next);
+};
+
+module.exports = LinearRetryPolicyFilter;
diff --git a/src/node_modules/azure-storage/lib/common/filters/retrypolicyfilter.js b/src/node_modules/azure-storage/lib/common/filters/retrypolicyfilter.js
new file mode 100644
index 0000000..7e2a977
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/filters/retrypolicyfilter.js
@@ -0,0 +1,234 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var azureutil = require('../util/util');
+var Constants = require('../util/constants');
+var StorageUtilities = require('../util/storageutilities');
+var extend = require('util')._extend;
+
+/**
+* Creates a new RetryPolicyFilter instance.
+* @class
+* The RetryPolicyFilter allows you to retry operations,
+* using a custom retry policy. Users are responsible to
+* define the shouldRetry method.
+* To apply a filter to service operations, use `withFilter`
+* and specify the filter to be used when creating a service.
+* @constructor
+* @param {number} [retryCount=30000] The client retry count.
+* @param {number} [retryInterval=3] The client retry interval, in milliseconds.
+*
+* @example
+* var azure = require('azure-storage');
+* var retryPolicy = new azure.RetryPolicyFilter();
+* retryPolicy.retryCount = 3;
+* retryPolicy.retryInterval = 3000;
+* retryPolicy.shouldRetry = function(statusCode, retryContext) {
+*
+* };
+* var blobService = azure.createBlobService().withFilter(retryPolicy);
+*/
+function RetryPolicyFilter(retryCount, retryInterval) {
+ this.retryCount = retryCount ? retryCount : RetryPolicyFilter.DEFAULT_CLIENT_RETRY_COUNT;
+ this.retryInterval = retryInterval ? retryInterval : RetryPolicyFilter.DEFAULT_CLIENT_RETRY_INTERVAL;
+}
+
+/**
+* Represents the default client retry interval, in milliseconds.
+*/
+RetryPolicyFilter.DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
+
+/**
+* Represents the default client retry count.
+*/
+RetryPolicyFilter.DEFAULT_CLIENT_RETRY_COUNT = 3;
+
+/**
+* Handles an operation with a retry policy.
+*
+* @param {Object} requestOptions The original request options.
+* @param {function} next The next filter to be handled.
+*/
+RetryPolicyFilter.prototype.handle = function (requestOptions, next) {
+ RetryPolicyFilter._handle(this, requestOptions, next);
+};
+
+/**
+* Handles an operation with a retry policy.
+*
+* @param {Object} requestOptions The original request options.
+* @param {function} next The next filter to be handled.
+*/
+RetryPolicyFilter._handle = function (self, requestOptions, next) {
+
+ var retryRequestOptions = extend({}, requestOptions);
+ retryRequestOptions.retryInterval = 0;
+
+ // Initialize retryContext because that will be passed to the shouldRetry method which users will implement
+ retryRequestOptions.retryContext = {
+ retryCount: 0,
+ error: null,
+ retryInterval: retryRequestOptions.retryInterval,
+ locationMode: retryRequestOptions.locationMode,
+ currentLocation: retryRequestOptions.currentLocation
+ };
+
+ var lastPrimaryAttempt;
+ var lastSecondaryAttempt;
+ var operation = function () {
+ // retry policies dont really do anything to the request options
+ // so move on to next
+ if (next) {
+ next(retryRequestOptions, function (returnObject, finalCallback, nextPostCallback) {
+ // Previous operation ended so update the retry data
+ if (returnObject.error) {
+ if (retryRequestOptions.retryContext.error) {
+ returnObject.error.innerError = retryRequestOptions.retryContext.error;
+ }
+
+ retryRequestOptions.retryContext.error = returnObject.error;
+ }
+
+ // If a request sent to the secondary location fails with 404 (Not Found), it is possible
+ // that the resource replication is not finished yet. So, in case of 404 only in the secondary
+ // location, the failure should still be retryable.
+ var secondaryNotFound = (retryRequestOptions.currentLocation === Constants.StorageLocation.SECONDARY) && ((returnObject.response && returnObject.response.statusCode === 404) || (returnObject.error && returnObject.error.code === 'ENOTFOUND'));
+
+ var notExceedMaxRetryCount = retryRequestOptions.retryContext.retryCount ? retryRequestOptions.retryContext.retryCount <= self.retryCount : true;
+ var retryInfo = self.shouldRetry(secondaryNotFound ? 500 : (azureutil.objectIsNull(returnObject.response) ? 306 : returnObject.response.statusCode), retryRequestOptions);
+ retryRequestOptions.retryContext.retryCount++;
+
+ if (retryInfo.ignore) {
+ returnObject.error = null;
+ }
+
+ // If the custom retry logic(shouldRetry) does not return a targetLocation, calculate based on the previous location and locationMode.
+ if(azureutil.objectIsNull(retryInfo.targetLocation)) {
+ retryInfo.targetLocation = azureutil.getNextLocation(retryRequestOptions.currentLocation, retryRequestOptions.locationMode);
+ }
+
+ // If the custom retry logic(shouldRetry) does not return a retryInterval, try to set it to the value on the instance if it is available. Otherwise, the default(30000) will be used.
+ if(azureutil.objectIsNull(retryInfo.retryInterval)) {
+ retryInfo.retryInterval = self.retryInterval;
+ }
+
+ // Only in the case of success from server but client side failure like MD5 or length mismatch, returnObject.retryable has a value(we explicitly set it to false).
+ // In this case, we should not retry the request.
+ // If the output stream already get sent to server and get error back,
+ // we should NOT retry within the SDK as the stream data is not valid anymore if we retry directly.
+ if (
+ !returnObject.outputStreamSent && returnObject.error && azureutil.objectIsNull(returnObject.retryable) && notExceedMaxRetryCount &&
+ (
+ (!azureutil.objectIsNull(returnObject.response) && retryInfo.retryable) ||
+ (
+ returnObject.error.code === 'ECONNREFUSED' ||
+ returnObject.error.code === 'ETIMEDOUT' ||
+ returnObject.error.code === 'ESOCKETTIMEDOUT' ||
+ returnObject.error.code === 'ECONNRESET' ||
+ returnObject.error.code === 'EAI_AGAIN' ||
+ returnObject.error.message === 'XHR error' // stream-http XHR network error message in browsers
+ )
+ )
+ ) {
+ if (retryRequestOptions.currentLocation === Constants.StorageLocation.PRIMARY) {
+ lastPrimaryAttempt = returnObject.operationEndTime;
+ } else {
+ lastSecondaryAttempt = returnObject.operationEndTime;
+ }
+
+ // Moreover, in case of 404 when trying the secondary location, instead of retrying on the
+ // secondary, further requests should be sent only to the primary location, as it most
+ // probably has a higher chance of succeeding there.
+ if (secondaryNotFound && (retryRequestOptions.locationMode !== StorageUtilities.LocationMode.SECONDARY_ONLY))
+ {
+ retryInfo.locationMode = StorageUtilities.LocationMode.PRIMARY_ONLY;
+ retryInfo.targetLocation = Constants.StorageLocation.PRIMARY;
+ }
+
+ // Now is the time to calculate the exact retry interval. ShouldRetry call above already
+ // returned back how long two requests to the same location should be apart from each other.
+ // However, for the reasons explained above, the time spent between the last attempt to
+ // the target location and current time must be subtracted from the total retry interval
+ // that ShouldRetry returned.
+ var lastAttemptTime = retryInfo.targetLocation === Constants.StorageLocation.PRIMARY ? lastPrimaryAttempt : lastSecondaryAttempt;
+ if (!azureutil.objectIsNull(lastAttemptTime)) {
+ var sinceLastAttempt = new Date().getTime() - lastAttemptTime.getTime();
+ if (sinceLastAttempt < 0) {
+ sinceLastAttempt = 0;
+ }
+
+ retryRequestOptions.retryInterval = retryInfo.retryInterval - sinceLastAttempt;
+ }
+ else {
+ retryRequestOptions.retryInterval = 0;
+ }
+
+ if(!azureutil.objectIsNull(retryInfo.locationMode)) {
+ retryRequestOptions.locationMode = retryInfo.locationMode;
+ }
+
+ retryRequestOptions.currentLocation = retryInfo.targetLocation;
+ operation();
+ } else {
+ if (nextPostCallback) {
+ nextPostCallback(returnObject);
+ } else if (finalCallback) {
+ finalCallback(returnObject);
+ }
+ }
+ });
+ }
+ };
+
+ operation();
+};
+
+RetryPolicyFilter._shouldRetryOnError = function (statusCode, requestOptions) {
+ var retryInfo = (requestOptions && requestOptions.retryContext) ? requestOptions.retryContext : {};
+
+ // Non-timeout Cases
+ if (statusCode >= 300 && statusCode != 408) {
+ // Always no retry on "not implemented" and "version not supported"
+ if (statusCode == 501 || statusCode == 505) {
+ retryInfo.retryable = false;
+ return retryInfo;
+ }
+
+ // When absorbConditionalErrorsOnRetry is set (for append blob)
+ if (requestOptions && requestOptions.absorbConditionalErrorsOnRetry) {
+ if (statusCode == 412) {
+ // When appending block with precondition failure and their was a server error before, we ignore the error.
+ if (retryInfo.lastServerError) {
+ retryInfo.ignore = true;
+ retryInfo.retryable = true;
+ } else {
+ retryInfo.retryable = false;
+ }
+ } else if (statusCode >= 500 && statusCode < 600) {
+ // Retry on the server error
+ retryInfo.retryable = true;
+ retryInfo.lastServerError = true;
+ }
+ } else if (statusCode < 500) {
+ // No retry on the client error
+ retryInfo.retryable = false;
+ }
+ }
+
+ return retryInfo;
+};
+
+module.exports = RetryPolicyFilter;
diff --git a/src/node_modules/azure-storage/lib/common/http/webresource.js b/src/node_modules/azure-storage/lib/common/http/webresource.js
new file mode 100644
index 0000000..3c50153
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/http/webresource.js
@@ -0,0 +1,324 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureutil = require('../util/util');
+var SR = require('../util/sr');
+var Constants = require('../util/constants');
+var errors = require('../errors/errors');
+var ArgumentError = errors.ArgumentError;
+var HeaderConstants = Constants.HeaderConstants;
+var HttpConstants = Constants.HttpConstants;
+var HttpConstants = Constants.HttpConstants;
+var HttpVerbs = HttpConstants.HttpVerbs;
+
+function encodeSpecialCharacters(path) {
+ return path.replace(/'/g, '%27');
+}
+
+/**
+* Creates a new WebResource object.
+*
+* This class provides an abstraction over a REST call by being library / implementation agnostic and wrapping the necessary
+* properties to initiate a request.
+*
+* @constructor
+*/
+function WebResource() {
+ this.rawResponse = false;
+ this.queryString = {};
+}
+
+/**
+* Creates a new put request web resource.
+*
+* @param {string} path The path for the put operation.
+* @return {WebResource} A new webresource with a put operation for the given path.
+*/
+WebResource.put = function (path) {
+ var webResource = new WebResource();
+ webResource.path = path ? encodeSpecialCharacters(path) : null;
+ webResource.method = HttpConstants.HttpVerbs.PUT;
+ return webResource;
+};
+
+/**
+* Creates a new get request web resource.
+*
+* @param {string} path The path for the get operation.
+* @return {WebResource} A new webresource with a get operation for the given path.
+*/
+WebResource.get = function (path) {
+ var webResource = new WebResource();
+ webResource.path = path ? encodeSpecialCharacters(path) : null;
+ webResource.method = HttpConstants.HttpVerbs.GET;
+ return webResource;
+};
+
+/**
+* Creates a new head request web resource.
+*
+* @param {string} path The path for the head operation.
+* @return {WebResource} A new webresource with a head operation for the given path.
+*/
+WebResource.head = function (path) {
+ var webResource = new WebResource();
+ webResource.path = path ? encodeSpecialCharacters(path) : null;
+ webResource.method = HttpConstants.HttpVerbs.HEAD;
+ return webResource;
+};
+
+/**
+* Creates a new delete request web resource.
+*
+* @param {string} path The path for the delete operation.
+* @return {WebResource} A new webresource with a delete operation for the given path.
+*/
+WebResource.del = function (path) {
+ var webResource = new WebResource();
+ webResource.path = path ? encodeSpecialCharacters(path) : null;
+ webResource.method = HttpConstants.HttpVerbs.DELETE;
+ return webResource;
+};
+
+/**
+* Creates a new post request web resource.
+*
+* @param {string} path The path for the post operation.
+* @return {WebResource} A new webresource with a post operation for the given path.
+*/
+WebResource.post = function (path) {
+ var webResource = new WebResource();
+ webResource.path = path ? encodeSpecialCharacters(path) : null;
+ webResource.method = HttpConstants.HttpVerbs.POST;
+ return webResource;
+};
+
+/**
+* Creates a new merge request web resource.
+*
+* @param {string} path The path for the merge operation.
+* @return {WebResource} A new webresource with a merge operation for the given path.
+*/
+WebResource.merge = function (path) {
+ var webResource = new WebResource();
+ webResource.path = path ? encodeSpecialCharacters(path) : null;
+ webResource.method = HttpConstants.HttpVerbs.MERGE;
+ return webResource;
+};
+
+/**
+* Specifies a custom property in the web resource.
+*
+* @param {string} name The property name.
+* @param {string} value The property value.
+* @return {WebResource} The webresource.
+*/
+WebResource.prototype.withProperty = function (name, value) {
+ if (!this.properties) {
+ this.properties = {};
+ }
+
+ this.properties[name] = value;
+
+ return this;
+};
+
+/**
+* Specifies if the response should be parsed or not.
+*
+* @param {bool} rawResponse true if the response should not be parsed; false otherwise.
+* @return {WebResource} The webresource.
+*/
+WebResource.prototype.withRawResponse = function (rawResponse) {
+ this.rawResponse = rawResponse;
+
+ if (azureutil.objectIsNull(this.rawResponse)) {
+ this.rawResponse = true;
+ }
+
+ return this;
+};
+
+WebResource.prototype.withHeadersOnly = function (headersOnly) {
+ if (headersOnly !== undefined) {
+ this.headersOnly = headersOnly;
+ } else {
+ this.headersOnly = true;
+ }
+
+ return this;
+};
+
+/**
+* Adds an optional query string parameter.
+*
+* @param {Object} name The name of the query string parameter.
+* @param {Object} value The value of the query string parameter.
+* @param {Object} defaultValue The default value for the query string parameter to be used if no value is passed.
+* @return {Object} The web resource.
+*/
+WebResource.prototype.withQueryOption = function (name, value, defaultValue) {
+ if (!azureutil.objectIsNull(value)) {
+ this.queryString[name] = value;
+ } else if (defaultValue) {
+ this.queryString[name] = defaultValue;
+ }
+
+ return this;
+};
+
+/**
+* Adds optional query string parameters.
+*
+* Additional arguments will be the needles to search in the haystack.
+*
+* @param {Object} object The haystack of query string parameters.
+* @return {Object} The web resource.
+*/
+WebResource.prototype.withQueryOptions = function (object) {
+ if (object) {
+ for (var i = 1; i < arguments.length; i++) {
+ if (object[arguments[i]]) {
+ this.withQueryOption(arguments[i], object[arguments[i]]);
+ }
+ }
+ }
+
+ return this;
+};
+
+/**
+* Adds an optional header parameter.
+*
+* @param {Object} name The name of the header parameter.
+* @param {Object} value The value of the header parameter.
+* @return {Object} The web resource.
+*/
+WebResource.prototype.withHeader = function (name, value) {
+ if (!this.headers) {
+ this.headers = {};
+ }
+
+ if (!azureutil.IsNullOrEmptyOrUndefinedOrWhiteSpace(value)) {
+ value = value instanceof Date ? value.toUTCString() : value;
+
+ this.headers[name] = value;
+ }
+
+ return this;
+};
+
+/**
+* Adds an optional body.
+*
+* @param {Object} body The request body.
+* @return {Object} The web resource.
+*/
+WebResource.prototype.withBody = function (body) {
+ this.body = body;
+ return this;
+};
+
+/**
+* Adds optional query string parameters.
+*
+* Additional arguments will be the needles to search in the haystack.
+*
+* @param {Object} object The haystack of headers.
+* @return {Object} The web resource.
+*/
+WebResource.prototype.withHeaders = function (object) {
+ if (object) {
+ for (var i = 1; i < arguments.length; i++) {
+ if (object[arguments[i]]) {
+ this.withHeader(arguments[i], object[arguments[i]]);
+ }
+ }
+ }
+
+ return this;
+};
+
+WebResource.prototype.addOptionalMetadataHeaders = function (metadata) {
+ var self = this;
+
+ if (metadata) {
+ Object.keys(metadata).forEach(function (metadataKey) {
+ if (azureutil.IsNullOrEmptyOrUndefinedOrWhiteSpace(metadataKey)) {
+ throw new ArgumentError('metadata', SR.METADATA_KEY_INVALID);
+ }
+
+ var value = metadata[metadataKey];
+ if (azureutil.IsNullOrEmptyOrUndefinedOrWhiteSpace(value)) {
+ throw new ArgumentError('metadata', SR.METADATA_VALUE_INVALID);
+ }
+
+ var metadataHeaderName = HeaderConstants.PREFIX_FOR_STORAGE_METADATA + metadataKey;
+ var existingMetadataHeaderName = '';
+ var headers = self.headers ? self.headers : {};
+ if (Object.keys(headers).some(function (headerName) {
+ existingMetadataHeaderName = headerName;
+ return headerName.toString().toLowerCase() === metadataHeaderName.toLowerCase();
+ })) {
+ self.withHeader(existingMetadataHeaderName, self.headers[existingMetadataHeaderName] + ',' + value);
+ } else {
+ self.withHeader(metadataHeaderName, value);
+ }
+ });
+ }
+
+ return this;
+};
+
+/**
+* Determines if a status code corresponds to a valid response according to the WebResource's expected status codes.
+*
+* @param {int} statusCode The response status code.
+* @return true if the response is valid; false otherwise.
+*/
+WebResource.validResponse = function (statusCode) {
+ if (statusCode >= 200 && statusCode < 300) {
+ return true;
+ }
+
+ return false;
+};
+
+function isMethodWithBody(verb) {
+ return verb === HttpVerbs.PUT ||
+ verb === HttpVerbs.POST ||
+ verb === HttpVerbs.MERGE;
+}
+
+/**
+* Hook up the given input stream to a destination output stream if the WebResource method
+* requires a request body and a body is not already set.
+*
+* @param {Stream} inputStream the stream to pipe from
+* @param {Stream} outputStream the stream to pipe to
+*
+* @return destStream
+*/
+WebResource.prototype.pipeInput = function(inputStream, destStream) {
+ if (isMethodWithBody(this.method) && !this.hasOwnProperty('body')) {
+ inputStream.pipe(destStream);
+ }
+
+ return destStream;
+};
+
+module.exports = WebResource;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/md5-wrapper/md5.browser.js b/src/node_modules/azure-storage/lib/common/md5-wrapper/md5.browser.js
new file mode 100644
index 0000000..d0690f3
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/md5-wrapper/md5.browser.js
@@ -0,0 +1,26 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var MD5 = require('md5.js');
+
+var Md5Wrapper = function () {
+};
+
+Md5Wrapper.prototype.createMd5Hash = function() {
+ return new MD5();
+};
+
+module.exports = Md5Wrapper;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/md5-wrapper/md5.node.js b/src/node_modules/azure-storage/lib/common/md5-wrapper/md5.node.js
new file mode 100644
index 0000000..bf4e5f6
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/md5-wrapper/md5.node.js
@@ -0,0 +1,26 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var crypto = require('crypto');
+
+var Md5Wrapper = function () {
+};
+
+Md5Wrapper.prototype.createMd5Hash = function() {
+ return crypto.createHash('md5');
+};
+
+module.exports = Md5Wrapper;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/md5-wrapper/package.json b/src/node_modules/azure-storage/lib/common/md5-wrapper/package.json
new file mode 100644
index 0000000..17de3eb
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/md5-wrapper/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "azure-storage-md5-wrapper",
+ "author": "Microsoft Corporation",
+ "license": "Apache-2.0",
+ "main": "md5.node.js",
+ "browser": "md5.browser.js"
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/models/accountpropertiesresult.js b/src/node_modules/azure-storage/lib/common/models/accountpropertiesresult.js
new file mode 100644
index 0000000..2e95092
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/models/accountpropertiesresult.js
@@ -0,0 +1,33 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var Constants = require('../util/constants');
+var HeaderConstants = Constants.HeaderConstants;
+
+exports.parse = function (headers) {
+ var accountPropertiesResult = {};
+
+ if (headers[HeaderConstants.SKU_NAME]) {
+ accountPropertiesResult.SkuName = headers[HeaderConstants.SKU_NAME];
+ }
+
+ if (headers[HeaderConstants.ACCOUNT_KIND]) {
+ accountPropertiesResult.AccountKind = headers[HeaderConstants.ACCOUNT_KIND];
+ }
+
+ return accountPropertiesResult;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/models/aclresult.js b/src/node_modules/azure-storage/lib/common/models/aclresult.js
new file mode 100644
index 0000000..d6d2a67
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/models/aclresult.js
@@ -0,0 +1,121 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+var xmlbuilder = require('xmlbuilder');
+
+var azureutil = require('../util/util');
+var ISO8061Date = require('../util/iso8061date');
+var Constants = require('../util/constants');
+var AclConstants = Constants.AclConstants;
+
+exports = module.exports;
+
+/**
+* Builds an XML representation for container acl permissions.
+*
+* @param {Object.} entity The signed identifiers.
+* @return {string} The XML container acl permissions.
+*/
+exports.serialize = function (signedIdentifiersJs) {
+ var doc = xmlbuilder.create(AclConstants.SIGNED_IDENTIFIERS_ELEMENT, { version: '1.0', encoding: 'utf-8' });
+
+ var keys = Object.keys(signedIdentifiersJs);
+ if (keys.length > 0) {
+ keys.forEach(function (key) {
+ var accessPolicy = signedIdentifiersJs[key];
+ doc = doc
+ .ele(AclConstants.SIGNED_IDENTIFIER_ELEMENT)
+ .ele(AclConstants.ID)
+ .txt(key)
+ .up()
+ .ele(AclConstants.ACCESS_POLICY);
+
+ if (accessPolicy.Start) {
+ var startIsoString = accessPolicy.Start;
+ if (!_.isDate(startIsoString)) {
+ startIsoString = new Date(startIsoString);
+ }
+
+ // Convert to expected ISO 8061 date format
+ startIsoString = ISO8061Date.format(startIsoString);
+
+ doc = doc
+ .ele(AclConstants.START)
+ .txt(startIsoString)
+ .up();
+ }
+
+ if (accessPolicy.Expiry) {
+ var expiryIsoString = accessPolicy.Expiry;
+ if (!_.isDate(expiryIsoString)) {
+ expiryIsoString = new Date(expiryIsoString);
+ }
+
+ // Convert to expected ISO 8061 date format
+ expiryIsoString = ISO8061Date.format(expiryIsoString);
+
+ doc = doc
+ .ele(AclConstants.EXPIRY)
+ .txt(expiryIsoString)
+ .up();
+ }
+
+ if (accessPolicy.Permissions) {
+ doc = doc
+ .ele(AclConstants.PERMISSION)
+ .txt(accessPolicy.Permissions)
+ .up();
+ }
+
+ doc = doc.up().up();
+ });
+ }
+ return doc.doc().toString();
+};
+
+exports.parse = function (signedIdentifiersXml) {
+ var signedIdentifiers = {};
+
+ signedIdentifiersXml = azureutil.tryGetValueChain(signedIdentifiersXml, [ 'SignedIdentifiers', 'SignedIdentifier' ]);
+ if (signedIdentifiersXml) {
+ if (!_.isArray(signedIdentifiersXml)) {
+ signedIdentifiersXml = [ signedIdentifiersXml ];
+ }
+
+ signedIdentifiersXml.forEach(function (signedIdentifier) {
+ var accessPolicy = {};
+ if (signedIdentifier.AccessPolicy) {
+ if (signedIdentifier.AccessPolicy.Start) {
+ accessPolicy.Start = ISO8061Date.parse(signedIdentifier.AccessPolicy.Start);
+ }
+
+ if (signedIdentifier.AccessPolicy.Expiry) {
+ accessPolicy.Expiry = ISO8061Date.parse(signedIdentifier.AccessPolicy.Expiry);
+ }
+
+ if (signedIdentifier.AccessPolicy.Permission) {
+ accessPolicy.Permissions = signedIdentifier.AccessPolicy.Permission;
+ }
+ }
+
+ signedIdentifiers[signedIdentifier.Id] = accessPolicy;
+ });
+ }
+
+ return signedIdentifiers;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/models/servicepropertiesresult.js b/src/node_modules/azure-storage/lib/common/models/servicepropertiesresult.js
new file mode 100644
index 0000000..80629a5
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/models/servicepropertiesresult.js
@@ -0,0 +1,486 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+var xmlbuilder = require('xmlbuilder');
+
+var Constants = require('../util/constants');
+var ServicePropertiesConstants = Constants.ServicePropertiesConstants;
+
+exports = module.exports;
+
+function serializeRetentionPolicy(doc, policy) {
+ if (policy !== null) {
+ if (typeof policy === 'undefined') {
+ policy = {};
+ }
+
+ doc = doc.ele(ServicePropertiesConstants.RETENTION_POLICY_ELEMENT);
+ if (typeof policy.Enabled !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(policy.Enabled)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ if (typeof policy.Days !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.DAYS_ELEMENT)
+ .txt(policy.Days)
+ .up();
+ } else if (policy.Enabled === true) {
+ doc = doc.ele(ServicePropertiesConstants.DAYS_ELEMENT)
+ .txt(1)
+ .up();
+ }
+
+ doc = doc.up();
+ }
+}
+
+function serializeDeleteRetentionPolicy(doc, policy) {
+ if (policy !== null) {
+ if (typeof policy === 'undefined') {
+ policy = {};
+ }
+
+ if (typeof policy.Enabled !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(policy.Enabled)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ if (typeof policy.Days !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.DAYS_ELEMENT)
+ .txt(policy.Days)
+ .up();
+ } else if (policy.Enabled === true) {
+ doc = doc.ele(ServicePropertiesConstants.DAYS_ELEMENT)
+ .txt(1)
+ .up();
+ }
+
+ doc = doc.up();
+ }
+}
+
+function serializeStaticWebsite(doc, staticWebsite) {
+ if (staticWebsite !== null) {
+ if (typeof staticWebsite === 'undefined') {
+ staticWebsite = {};
+ }
+
+ if (typeof staticWebsite.Enabled !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(staticWebsite.Enabled)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ if (typeof staticWebsite.IndexDocument !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.DEFAULT_INDEX_DOCUMENT_ELEMENT)
+ .txt(staticWebsite.IndexDocument)
+ .up();
+ }
+
+ if (typeof staticWebsite.ErrorDocument404Path !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.DEFAULT_ERROR_DOCUMENT_404_PATH_ELEMENT)
+ .txt(staticWebsite.ErrorDocument404Path)
+ .up();
+ }
+
+ doc = doc.up();
+ }
+}
+
+function serializeLogging(doc, logging) {
+ if (typeof logging.Version !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.VERSION_ELEMENT)
+ .txt(logging.Version)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.VERSION_ELEMENT)
+ .txt(ServicePropertiesConstants.DEFAULT_ANALYTICS_VERSION)
+ .up();
+ }
+
+ if (typeof logging.Delete !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.DELETE_ELEMENT)
+ .txt(logging.Delete)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.DELETE_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ if (typeof logging.Read !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.READ_ELEMENT)
+ .txt(logging.Read)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.READ_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ if (typeof logging.Write !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.WRITE_ELEMENT)
+ .txt(logging.Write)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.WRITE_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ serializeRetentionPolicy(doc, logging.RetentionPolicy);
+
+ doc = doc.up();
+}
+
+function serializeMetrics(doc, metrics) {
+ if (typeof metrics.Version !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.VERSION_ELEMENT)
+ .txt(metrics.Version)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.VERSION_ELEMENT)
+ .txt(ServicePropertiesConstants.DEFAULT_ANALYTICS_VERSION)
+ .up();
+ }
+
+ if (typeof metrics.Enabled !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(metrics.Enabled)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.ENABLED_ELEMENT)
+ .txt(false)
+ .up();
+ }
+
+ if (metrics.Enabled) {
+ if (typeof metrics.IncludeAPIs !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.INCLUDE_APIS_ELEMENT)
+ .txt(metrics.IncludeAPIs)
+ .up();
+ } else if (metrics.Enabled === true) {
+ doc = doc.ele(ServicePropertiesConstants.INCLUDE_APIS_ELEMENT)
+ .txt(false)
+ .up();
+ }
+ }
+ serializeRetentionPolicy(doc, metrics.RetentionPolicy);
+}
+
+function serializeCorsRules(doc, rules) {
+ if (typeof rules !== 'undefined' && rules !== null && _.isArray(rules)) {
+ rules.forEach(function (rule) {
+ doc = doc.ele(ServicePropertiesConstants.CORS_RULE_ELEMENT);
+
+ if (typeof rule.AllowedMethods !== 'undefined' && _.isArray(rule.AllowedMethods)) {
+ doc = doc.ele(ServicePropertiesConstants.ALLOWED_METHODS_ELEMENT)
+ .txt(rule.AllowedMethods.join(','))
+ .up();
+ }
+
+ if (typeof rule.AllowedOrigins !== 'undefined' && _.isArray(rule.AllowedOrigins)) {
+ doc = doc.ele(ServicePropertiesConstants.ALLOWED_ORIGINS_ELEMENT)
+ .txt(rule.AllowedOrigins.join(','))
+ .up();
+ }
+
+ if (typeof rule.AllowedHeaders !== 'undefined' && _.isArray(rule.AllowedHeaders)) {
+ doc = doc.ele(ServicePropertiesConstants.ALLOWED_HEADERS_ELEMENT)
+ .txt(rule.AllowedHeaders.join(','))
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.ALLOWED_HEADERS_ELEMENT)
+ .txt('')
+ .up();
+ }
+
+ if (typeof rule.ExposedHeaders !== 'undefined' && _.isArray(rule.ExposedHeaders)) {
+ doc = doc.ele(ServicePropertiesConstants.EXPOSED_HEADERS_ELEMENT)
+ .txt(rule.ExposedHeaders.join(','))
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.EXPOSED_HEADERS_ELEMENT)
+ .txt('')
+ .up();
+ }
+
+ if (typeof rule.MaxAgeInSeconds !== 'undefined') {
+ doc = doc.ele(ServicePropertiesConstants.MAX_AGE_IN_SECONDS_ELEMENT)
+ .txt(rule.MaxAgeInSeconds)
+ .up();
+ } else {
+ doc = doc.ele(ServicePropertiesConstants.MAX_AGE_IN_SECONDS_ELEMENT)
+ .txt('0')
+ .up();
+ }
+
+ doc = doc.up();
+ });
+ }
+}
+
+exports.serialize = function (servicePropertiesJs) {
+ var doc = xmlbuilder.create(ServicePropertiesConstants.STORAGE_SERVICE_PROPERTIES_ELEMENT, { version: '1.0', encoding: 'utf-8' });
+
+ if (servicePropertiesJs.Logging) {
+ doc = doc.ele(ServicePropertiesConstants.LOGGING_ELEMENT);
+ serializeLogging(doc, servicePropertiesJs.Logging);
+ doc = doc.up();
+ }
+
+ if (servicePropertiesJs.HourMetrics) {
+ doc = doc.ele(ServicePropertiesConstants.HOUR_METRICS_ELEMENT);
+ serializeMetrics(doc, servicePropertiesJs.HourMetrics);
+ doc = doc.up();
+ }
+
+ if (servicePropertiesJs.MinuteMetrics) {
+ doc = doc.ele(ServicePropertiesConstants.MINUTE_METRICS_ELEMENT);
+ serializeMetrics(doc, servicePropertiesJs.MinuteMetrics);
+ doc = doc.up();
+ }
+
+ if (servicePropertiesJs.Cors) {
+ doc = doc.ele(ServicePropertiesConstants.CORS_ELEMENT);
+ serializeCorsRules(doc, servicePropertiesJs.Cors.CorsRule);
+ doc = doc.up();
+ }
+
+ if (servicePropertiesJs.DefaultServiceVersion) {
+ doc = doc.ele(ServicePropertiesConstants.DEFAULT_SERVICE_VERSION_ELEMENT)
+ .txt(servicePropertiesJs.DefaultServiceVersion)
+ .up();
+ }
+
+ if (servicePropertiesJs.DeleteRetentionPolicy) {
+ doc = doc.ele(ServicePropertiesConstants.DEFAULT_DELETE_RETENTION_POLICY_ELEMENT);
+ serializeDeleteRetentionPolicy(doc, servicePropertiesJs.DeleteRetentionPolicy);
+ doc = doc.up();
+ }
+
+ if (servicePropertiesJs.StaticWebsite) {
+ doc = doc.ele(ServicePropertiesConstants.DEFAULT_STATIC_WEBSITE_ELEMENT);
+ serializeStaticWebsite(doc, servicePropertiesJs.StaticWebsite);
+ doc = doc.up();
+ }
+
+ return doc.doc().toString();
+};
+
+function parseRetentionPolicy(policyXml) {
+ var policy = {};
+
+ if (typeof policyXml.Enabled !== 'undefined') {
+ policy.Enabled = policyXml.Enabled === 'true';
+ }
+
+ if (typeof policyXml.Days !== 'undefined') {
+ policy.Days = parseInt(policyXml.Days, 10);
+ }
+
+ return policy;
+}
+
+function parseLogging(loggingXml) {
+ var logging = {};
+
+ if (typeof loggingXml.Version !== 'undefined') {
+ logging.Version = loggingXml.Version;
+ }
+
+ if (typeof loggingXml.Delete !== 'undefined') {
+ logging.Delete = loggingXml.Delete === 'true';
+ }
+
+ if (typeof loggingXml.Read !== 'undefined') {
+ logging.Read = loggingXml.Read === 'true';
+ }
+
+ if (typeof loggingXml.Write !== 'undefined') {
+ logging.Write = loggingXml.Write === 'true';
+ }
+
+ if (typeof loggingXml.RetentionPolicy !== 'undefined') {
+ logging.RetentionPolicy = parseRetentionPolicy(loggingXml.RetentionPolicy);
+ }
+
+ return logging;
+}
+
+function parseMetrics(metricsXml) {
+ var metrics = {};
+
+ if (typeof metricsXml.Version !== 'undefined') {
+ metrics.Version = metricsXml.Version;
+ }
+
+ if (typeof metricsXml.Enabled !== 'undefined') {
+ metrics.Enabled = metricsXml.Enabled === 'true';
+ }
+
+ if (typeof metricsXml.IncludeAPIs !== 'undefined') {
+ metrics.IncludeAPIs = metricsXml.IncludeAPIs === 'true';
+ }
+
+ if (typeof metricsXml.RetentionPolicy !== 'undefined') {
+ metrics.RetentionPolicy = parseRetentionPolicy(metricsXml.RetentionPolicy);
+ }
+
+ return metrics;
+}
+
+function parseCors(corsXml) {
+ var cors = {};
+
+ if (typeof corsXml.CorsRule !== 'undefined') {
+ var rulesXml = corsXml.CorsRule;
+ if (!_.isArray(rulesXml)) {
+ rulesXml = [rulesXml];
+ }
+
+ cors.CorsRule = [];
+ rulesXml.forEach(function (ruleXml) {
+ var rule = {};
+
+ if (typeof ruleXml.AllowedMethods !== 'undefined') {
+ if (ruleXml.AllowedMethods !== '') {
+ rule.AllowedMethods = ruleXml.AllowedMethods.split(',');
+ }
+ else {
+ rule.AllowedMethods = [];
+ }
+ }
+
+ if (typeof ruleXml.AllowedOrigins !== 'undefined') {
+ if (ruleXml.AllowedOrigins !== '') {
+ rule.AllowedOrigins = ruleXml.AllowedOrigins.split(',');
+ }
+ else {
+ rule.AllowedOrigins = [];
+ }
+ }
+
+ if (typeof ruleXml.AllowedHeaders !== 'undefined') {
+ if (ruleXml.AllowedHeaders !== '') {
+ rule.AllowedHeaders = ruleXml.AllowedHeaders.split(',');
+ }
+ else {
+ rule.AllowedHeaders = [];
+ }
+ }
+
+ if (typeof ruleXml.ExposedHeaders !== 'undefined') {
+ if (ruleXml.ExposedHeaders !== '') {
+ rule.ExposedHeaders = ruleXml.ExposedHeaders.split(',');
+ }
+ else {
+ rule.ExposedHeaders = [];
+ }
+ }
+
+ if (typeof ruleXml.MaxAgeInSeconds !== 'undefined') {
+ rule.MaxAgeInSeconds = parseInt(ruleXml.MaxAgeInSeconds, 10);
+ }
+
+ cors.CorsRule.push(rule);
+ });
+ }
+
+ return cors;
+}
+
+function parseDeleteRetentionPolicy(deleteRetentionPolicyXml) {
+ var deleteRetentionPolicy = {};
+
+ if (typeof deleteRetentionPolicyXml.Enabled !== 'undefined') {
+ deleteRetentionPolicy.Enabled = deleteRetentionPolicyXml.Enabled === 'true';
+ }
+
+ if (typeof deleteRetentionPolicyXml.Days !== 'undefined') {
+ deleteRetentionPolicy.Days = parseInt(deleteRetentionPolicyXml.Days);
+ }
+
+ return deleteRetentionPolicy;
+}
+
+function parseStaticWebsite(staticWebsiteXml) {
+ var staticWebsite = {};
+
+ if (typeof staticWebsiteXml.Enabled !== 'undefined') {
+ staticWebsite.Enabled = staticWebsiteXml.Enabled === 'true';
+ }
+
+ if (typeof staticWebsiteXml.IndexDocument !== 'undefined') {
+ staticWebsite.IndexDocument = staticWebsiteXml.IndexDocument;
+ }
+
+ if (typeof staticWebsiteXml.ErrorDocument404Path !== 'undefined') {
+ staticWebsite.ErrorDocument404Path = staticWebsiteXml.ErrorDocument404Path;
+ }
+
+ return staticWebsite;
+}
+
+exports.parse = function (servicePropertiesXml) {
+ var serviceProperties = {};
+
+ if (typeof servicePropertiesXml.Logging !== 'undefined') {
+ serviceProperties.Logging = parseLogging(servicePropertiesXml.Logging);
+ }
+
+ if (typeof servicePropertiesXml.HourMetrics !== 'undefined') {
+ serviceProperties.HourMetrics = parseMetrics(servicePropertiesXml.HourMetrics);
+ }
+
+ if (typeof servicePropertiesXml.MinuteMetrics !== 'undefined') {
+ serviceProperties.MinuteMetrics = parseMetrics(servicePropertiesXml.MinuteMetrics);
+ }
+
+ if (typeof servicePropertiesXml.Cors !== 'undefined') {
+ serviceProperties.Cors = parseCors(servicePropertiesXml.Cors);
+ }
+
+ if (typeof servicePropertiesXml.DefaultServiceVersion !== 'undefined') {
+ serviceProperties.DefaultServiceVersion = servicePropertiesXml.DefaultServiceVersion;
+ }
+
+ if (typeof servicePropertiesXml.DeleteRetentionPolicy !== 'undefined') {
+ serviceProperties.DeleteRetentionPolicy = parseDeleteRetentionPolicy(servicePropertiesXml.DeleteRetentionPolicy);
+ }
+
+ if (typeof servicePropertiesXml.StaticWebsite !== 'undefined') {
+ serviceProperties.StaticWebsite = parseStaticWebsite(servicePropertiesXml.StaticWebsite);
+ }
+
+ return serviceProperties;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/models/servicestatsparser.js b/src/node_modules/azure-storage/lib/common/models/servicestatsparser.js
new file mode 100644
index 0000000..3ebf342
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/models/servicestatsparser.js
@@ -0,0 +1,34 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+exports = module.exports;
+
+exports.parse = function (serviceStatsXml) {
+ var serviceStats = {};
+
+ if (typeof serviceStatsXml.GeoReplication !== 'undefined') {
+ serviceStats.GeoReplication = {};
+
+ if (typeof serviceStatsXml.GeoReplication.Status !== 'undefined') {
+ serviceStats.GeoReplication.Status = serviceStatsXml.GeoReplication.Status;
+ }
+
+ if (typeof serviceStatsXml.GeoReplication.LastSyncTime !== 'undefined' && serviceStatsXml.GeoReplication.LastSyncTime !== '') {
+ serviceStats.GeoReplication.LastSyncTime = new Date(serviceStatsXml.GeoReplication.LastSyncTime);
+ }
+ }
+
+ return serviceStats;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/models/tokencredential.js b/src/node_modules/azure-storage/lib/common/models/tokencredential.js
new file mode 100644
index 0000000..6443798
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/models/tokencredential.js
@@ -0,0 +1,53 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* Creates a new TokenCredential object.
+* @class
+* The TokenCredential class is used to store the access token string.
+*
+* @constructor
+* @param {string} token The access token, such as an OAuth access token in string type.
+*
+* @example
+* var azure = require('azure-storage');
+* var tokenCredential = new azure.TokenCredential('myOAuthAccessToken');
+* var blobService = azure.createBlobServiceWithTokenCredential('https://account.blob.core.windows.net', tokenCredential);
+* tokenCredential.set('updatedOAuthAccessToken');
+*/
+function TokenCredential (token) {
+ this.token = token;
+}
+
+/**
+* Get current access token.
+*
+* @return {string} The current access token in string type.
+*/
+TokenCredential.prototype.get = function () {
+ return this.token;
+};
+
+/**
+* Renew the access token.
+*
+* @param {string} token The new access token in string.
+*/
+TokenCredential.prototype.set = function (token) {
+ this.token = token;
+};
+
+module.exports = TokenCredential;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/request-wrapper/package.json b/src/node_modules/azure-storage/lib/common/request-wrapper/package.json
new file mode 100644
index 0000000..00913d0
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/request-wrapper/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "azure-storage-request-wrapper",
+ "author": "Microsoft Corporation",
+ "license": "Apache-2.0",
+ "main": "request.node.js",
+ "browser": "request.browser.js"
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/request-wrapper/request.browser.js b/src/node_modules/azure-storage/lib/common/request-wrapper/request.browser.js
new file mode 100644
index 0000000..b71aa8f
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/request-wrapper/request.browser.js
@@ -0,0 +1,258 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var azureCommon = require('../common.browser');
+var Duplex = require('stream').Duplex;
+var extend = require('extend');
+var http = require('http');
+var https = require('https');
+var url = require('url');
+var util = require('util');
+
+/**
+* Creates a new Request object.
+*
+* @constructor
+* @param {object} options The options for a Request object.
+* @param {function} callback Callback
+*/
+function Request(options, callback) {
+ Duplex.call(this);
+
+ this._init(options, callback);
+ this._send();
+}
+
+util.inherits(Request, Duplex);
+
+Request.prototype._init = function (options, callback) {
+ this.callback = callback;
+
+ var nonReservedProperties = azureCommon.util.filterOutNonReservedProperties(this, options);
+ extend(this, nonReservedProperties);
+
+ this.agent = this.agent || false;
+ this.timeout = this.timeout || Math.pow(2, 32) * 1000;
+
+ this._initUri();
+ this._initHeaders();
+};
+
+Request.prototype._initUri = function () {
+ if (!this.uri) {
+ return this.emit('error', new Error('options.uri is a required argument'));
+ }
+
+ if (typeof this.uri === 'string') {
+ this.uri = url.parse(this.uri);
+ }
+
+ if (!this.uri.href) {
+ this.uri.href = url.format(this.uri);
+ }
+};
+
+Request.prototype._initHeaders = function () {
+ this.headers = this.headers || {};
+ this.headers['content-length'] = this.headers['content-length'] || 0;
+};
+
+Request.prototype._send = function () {
+ this._sent = true;
+
+ var protocol = this.uri.protocol || '';
+ var iface = (protocol === 'https:' ? https : http);
+
+ var options = {
+ scheme: protocol.replace(/:$/, ''),
+ method: this.method,
+ host: this.uri.hostname,
+ port: Number(this.uri.port) || (protocol === 'https:' ? 443 : 80),
+ path: this.uri.path,
+ agent: this.agent,
+ headers: this.headers,
+ withCredentials: this.withCredentials,
+ localAddress: this.localAddress,
+ mode: this.mode
+ };
+
+ if (protocol === 'https:') {
+ options.pfx = this.pfx;
+ options.key = this.key;
+ options.cert = this.cert;
+ options.ca = this.ca;
+ options.ciphers = this.ciphers;
+ options.rejectUnauthorized = this.rejectUnauthorized;
+ options.secureProtocol = this.secureProtocol;
+ }
+
+ var httpRequest = iface.request(options);
+ if (this.timeout && httpRequest.setTimeout) {
+ httpRequest.setTimeout(this.timeout);
+ }
+
+ this.httpRequest = httpRequest;
+ this.emit('request', httpRequest);
+
+ this._sendBody();
+ this._listenHttpResponse();
+ this._listenHttpError();
+
+ return httpRequest;
+};
+
+Request.prototype._sendBody = function () {
+ if (this.body) {
+ this.httpRequest.write(this.body);
+ this.httpRequest.end();
+ return;
+ }
+
+ if (this.headers['content-length'] == '0') {
+ this.httpRequest.end();
+ return;
+ }
+};
+
+Request.prototype._listenHttpError = function() {
+ var self = this;
+
+ self.httpRequest.on('error', function(error) {
+ self.emit('error', error);
+ });
+
+ self.on('error', function(error) {
+ if (self.callback) {
+ self.callback(error);
+ }
+ });
+};
+
+Request.prototype._listenHttpResponse = function () {
+ var self = this;
+
+ self.httpRequest.on('response', function (response) {
+ var buffers = [];
+ var bufferLength = 0;
+
+ self.response = response;
+
+ response.on('data', function (chunk) {
+ self.push(chunk);
+ buffers.push(chunk);
+ bufferLength += chunk.length;
+ });
+
+ response.on('error', function (error) {
+ self.emit('error', error);
+ });
+
+ response.on('end', function () {
+ self.push(null);
+
+ response.body = '';
+ if (bufferLength > 0) {
+ response.body = Buffer.concat(buffers, bufferLength);
+ }
+
+ if (self.encoding !== null) {
+ response.body = response.body.toString(self.encoding);
+ }
+
+ if (self.callback) {
+ self.callback(null, response);
+ }
+ });
+
+ self.emit('response', response);
+ });
+};
+
+/**
+* Set a Request header.
+*
+* @param {string} key The user provided header key.
+* @param {string} value The valid header value.
+*/
+Request.prototype.setHeader = function (key, value) {
+ if (this._sent) {
+ throw new Error('Request already sent');
+ }
+
+ this.headers[key] = value;
+ return this;
+};
+
+/**
+* Set a Request URI.
+*
+* @param {string} uri The user provided uri.
+*/
+Request.prototype.setLocation = function (uri) {
+ this.uri = uri;
+ return this;
+};
+
+Request.prototype.end = function (chunk) {
+ if (chunk) {
+ this.httpRequest.write(chunk);
+ }
+
+ this.httpRequest.end();
+};
+
+Request.prototype._write = function (chunk, encoding, callback) {
+ this.httpRequest.write(chunk);
+ callback();
+};
+
+Request.prototype._read = function () {
+};
+
+/**
+* Create a Request object
+* @ignore
+*
+* @param {object} options Options
+* @param {function} callback Callback
+* @return {Request} The created request object.
+*/
+function req(optionsOrCallback, callback) {
+ var reqDefaults = req.defaults();
+ return reqDefaults(optionsOrCallback, callback);
+}
+
+/**
+* Create a Request creator with default options
+* @ignore
+*
+* @param {object} defaultOptions Default options
+* @return {function}
+*/
+req.defaults = function (defaultOptions) {
+ return function (optionsOrCallback, callback) {
+ var options;
+ azureCommon.util.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ var nonReservedProperties = azureCommon.util.filterOutNonReservedProperties(options, defaultOptions);
+ extend(options, nonReservedProperties);
+
+ var request = new Request(options, callback);
+ return request;
+ };
+};
+
+module.exports = req;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/request-wrapper/request.node.js b/src/node_modules/azure-storage/lib/common/request-wrapper/request.node.js
new file mode 100644
index 0000000..63e8845
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/request-wrapper/request.node.js
@@ -0,0 +1,17 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+module.exports = require('request');
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/services/servicesettings.js b/src/node_modules/azure-storage/lib/common/services/servicesettings.js
new file mode 100644
index 0000000..5fca983
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/services/servicesettings.js
@@ -0,0 +1,262 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var util = require('util');
+
+var azureUtil = require('../util/util');
+var errors = require('../errors/errors');
+var SR = require('../util/sr');
+var Constants = require('../util/constants');
+
+exports = module.exports;
+
+/**
+* The default protocol.
+*/
+exports.DEFAULT_PROTOCOL = Constants.HTTPS;
+
+var NoMatchError = function (msg, constr) {
+ errors.captureStackTrace(this, constr || this);
+ this.message = msg || 'Error';
+};
+
+util.inherits(NoMatchError, Error);
+NoMatchError.prototype.name = 'NoMatchError';
+
+exports.NoMatchError = NoMatchError;
+
+/**
+* Throws an exception if the connection string format does not match any of the
+* available formats.
+*
+* @param {string} connectionString The invalid formatted connection string.
+* @return none
+*/
+exports.noMatchConnectionString = function (connectionString) {
+ throw new NoMatchError('The provided connection string "' + connectionString + '" does not have complete configuration settings.');
+};
+
+/**
+* Throws an exception if the settings dont match any of the
+* available formats.
+*
+* @param {object} settings The invalid settings.
+* @return none
+*/
+exports.noMatchSettings = function (settings) {
+ throw new NoMatchError('The provided settings ' + JSON.stringify(settings) + ' are not complete.');
+};
+
+/**
+* Parses the connection string and then validate that the parsed keys belong to
+* the validSettingKeys
+*
+* @param {string} connectionString The user provided connection string.
+* @param {array} validKeys The valid keys.
+* @return {array} The tokenized connection string keys.
+*/
+exports.parseAndValidateKeys = function (connectionString, validKeys) {
+ var parsedConnectionString = { };
+
+ // parse key/value pairs from connection string
+ var pairs = connectionString.split(';');
+ for (var m = 0; m < pairs.length; m++) {
+ if (pairs[m].length === 0) {
+ continue;
+ }
+
+ var equalDex = pairs[m].indexOf('=');
+ if (equalDex < 0) {
+ throw new SyntaxError(SR.INVALID_CONNECTION_STRING);
+ } else if (equalDex === 0) {
+ // empty key name.
+ throw new SyntaxError(SR.INVALID_CONNECTION_STRING_EMPTY_KEY);
+ }
+
+ var key = pairs[m].substring(0, equalDex);
+
+ // assure that all given keys are valid.
+ if (!azureUtil.inArrayInsensitive(key, validKeys)) {
+ throw new SyntaxError(util.format(SR.INVALID_CONNECTION_STRING_BAD_KEY, key));
+ }
+
+ var value = pairs[m].substring(equalDex + 1);
+
+ if(typeof parsedConnectionString[key] === 'undefined'){
+ parsedConnectionString[key] = value;
+ } else {
+ // duplicate key name
+ throw new SyntaxError(util.format(SR.INVALID_CONNECTION_STRING_DUPLICATE_KEY, key));
+ }
+ }
+
+ return parsedConnectionString;
+};
+
+/**
+* Creates an anonymous function that acts as predicate to perform a validation.
+*
+* @param array {requirements} The array of conditions to satisfy.
+* @param boolean {isRequired} Either these conditions are all required or all
+* optional.
+* @param boolean {atLeastOne} Indicates that at least one requirement must
+* succeed.
+* @return {function}
+*/
+exports.getValidator = function (requirements, isRequired, atLeastOne) {
+ return function (userSettings) {
+ var oneFound = false;
+ var result = { };
+
+ for (var key in userSettings) {
+ if (userSettings.hasOwnProperty(key)) {
+ result[key.toLowerCase()] = userSettings[key];
+ }
+ }
+
+ for (var requirement in requirements) {
+ if (requirements.hasOwnProperty(requirement)) {
+ var settingName = requirements[requirement].SettingName.toLowerCase();
+
+ // Check if the setting name exists in the provided user settings.
+ if (result[settingName]) {
+ // Check if the provided user setting value is valid.
+ var validationFunc = requirements[requirement].SettingConstraint;
+ var isValid = validationFunc(result[settingName]);
+
+ if (isValid) {
+ // Remove the setting as indicator for successful validation.
+ delete result[settingName];
+ oneFound = true;
+ }
+ } else if (isRequired) {
+ // If required then fail because the setting does not exist
+ return null;
+ }
+ }
+ }
+
+ if (atLeastOne) {
+ // At least one requirement must succeed, otherwise fail.
+ return oneFound ? result : null;
+ } else {
+ return result;
+ }
+ };
+};
+
+/**
+* Creates a setting value condition that validates it is one of the
+* passed valid values.
+*
+* @param {string} name The setting key name.
+* @return {array}
+*/
+exports.setting = function (name) {
+ var validValues = Array.prototype.slice.call(arguments, 1, arguments.length);
+
+ var predicate = function (settingValue) {
+ var validValuesString = JSON.stringify(validValues);
+ if (validValues.length === 0) {
+ // No restrictions, succeed.
+ return true;
+ }
+
+ // Check to find if the settingValue is valid or not.
+ for (var index = 0; index < validValues.length; index++) {
+ if (settingValue.toString() == validValues[index].toString()) {
+ // SettingValue is found in valid values set, succeed.
+ return true;
+ }
+ }
+
+ // settingValue is missing in valid values set, fail.
+ throw new RangeError('The provided config value ' + settingValue + ' does not belong to the valid values subset:\n' + validValuesString);
+ };
+
+ return exports.settingWithFunc(name, predicate);
+};
+
+/**
+* Creates an "at lease one" predicate for the provided list of requirements.
+*
+* @return callable
+*/
+exports.atLeastOne = function () {
+ var allSettings = arguments;
+ return exports.getValidator(allSettings, false, true);
+};
+
+/**
+* Creates an optional predicate for the provided list of requirements.
+*
+* @return {function}
+*/
+exports.optional = function () {
+ var optionalSettings = arguments;
+ return exports.getValidator(optionalSettings, false, false);
+};
+
+/**
+* Creates an required predicate for the provided list of requirements.
+*
+* @return {function}
+*/
+exports.allRequired = function () {
+ var requiredSettings = arguments;
+ return exports.getValidator(requiredSettings, true, false);
+};
+
+/**
+* Creates a setting value condition using the passed predicate.
+*
+* @param {string} name The setting key name.
+* @param {function} predicate The setting value predicate.
+* @return {array}
+*/
+exports.settingWithFunc = function (name, predicate) {
+ var requirement = {};
+ requirement.SettingName = name;
+ requirement.SettingConstraint = predicate;
+
+ return requirement;
+};
+
+
+/**
+* Tests to see if a given list of settings matches a set of filters exactly.
+*
+* @param array $settings The settings to check.
+* @return boolean If any filter returns null, false. If there are any settings
+* left over after all filters are processed, false. Otherwise true.
+*/
+exports.matchedSpecification = function (settings) {
+ var constraints = Array.prototype.slice.call(arguments, 1, arguments.length);
+
+ for (var constraint in constraints) {
+ if (constraints.hasOwnProperty(constraint)) {
+ var remainingSettings = constraints[constraint](settings);
+
+ if (!remainingSettings) {
+ return false;
+ } else {
+ settings = remainingSettings;
+ }
+ }
+ }
+
+ return azureUtil.objectKeysLength(settings) === 0;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/services/storageserviceclient.js b/src/node_modules/azure-storage/lib/common/services/storageserviceclient.js
new file mode 100644
index 0000000..3075c33
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/services/storageserviceclient.js
@@ -0,0 +1,1369 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var request = require('../request-wrapper');
+var url = require('url');
+var qs = require('querystring');
+var util = require('util');
+var xml2js = require('xml2js');
+var events = require('events');
+var _ = require('underscore');
+var guid = require('uuid');
+var os = require('os');
+var extend = require('extend');
+var Parser = require('json-edm-parser');
+
+var Md5Wrapper = require('../md5-wrapper');
+var azureutil = require('../util/util');
+var validate = require('../util/validate');
+var SR = require('../util/sr');
+var WebResource = require('../http/webresource');
+var BufferStream = require('../streams/bufferstream.js');
+
+var ServiceSettings = require('./servicesettings');
+var StorageServiceSettings = require('./storageservicesettings');
+var Constants = require('../util/constants');
+var StorageUtilities = require('../util/storageutilities');
+var ServicePropertiesResult = require('../models/servicepropertiesresult');
+var TableUtilities = require('../../services/table/tableutilities');
+
+var SharedKey = require('../signing/sharedkey');
+var SharedAccessSignature = require('../signing/sharedaccesssignature');
+var TokenSigner = require('../signing/tokensigner');
+
+var HeaderConstants = Constants.HeaderConstants;
+var QueryStringConstants = Constants.QueryStringConstants;
+var HttpResponseCodes = Constants.HttpConstants.HttpResponseCodes;
+var StorageServiceClientConstants = Constants.StorageServiceClientConstants;
+var defaultRequestLocationMode = Constants.RequestLocationMode.PRIMARY_ONLY;
+var RequestLocationMode = Constants.RequestLocationMode;
+
+var Logger = require('../diagnostics/logger');
+var errors = require('../errors/errors');
+var ArgumentError = errors.ArgumentError;
+var ArgumentNullError = errors.ArgumentNullError;
+var TimeoutError = errors.TimeoutError;
+var StorageError = errors.StorageError;
+
+/**
+* Creates a new StorageServiceClient object.
+*
+* @class
+* The StorageServiceClient class is the base class of all the service classes.
+* @constructor
+* @param {string} storageAccount The storage account.
+* @param {string} storageAccessKey The storage access key.
+* @param {object} host The host for the service.
+* @param {bool} usePathStyleUri Boolean value indicating wether to use path style uris.
+* @param {string} sas The Shared Access Signature string.
+* @param {TokenCredential} [token] The {@link TokenCredential} object, which can be created with an OAuth access token string.
+*/
+function StorageServiceClient(storageAccount, storageAccessKey, host, usePathStyleUri, sas, token) {
+ StorageServiceClient['super_'].call(this);
+
+ if(storageAccount && storageAccessKey) {
+ // account and key
+ this.storageAccount = storageAccount;
+ this.storageAccessKey = storageAccessKey;
+ this.storageCredentials = new SharedKey(this.storageAccount, this.storageAccessKey, usePathStyleUri);
+ } else if (sas) {
+ // sas
+ this.sasToken = sas;
+ this.storageCredentials = new SharedAccessSignature(sas);
+ } else if (token) {
+ // access token
+ this.token = token;
+ this.storageCredentials = new TokenSigner(token);
+ } else {
+ // anonymous
+ this.anonymous = true;
+ this.storageCredentials = {
+ signRequest: function(webResource, callback){
+ // no op, anonymous access
+ callback(null);
+ }
+ };
+ }
+
+ if(host){
+ this.setHost(host);
+ }
+
+ this.apiVersion = HeaderConstants.TARGET_STORAGE_VERSION;
+ this.usePathStyleUri = usePathStyleUri;
+
+ this._initDefaultFilter();
+
+ /**
+ * The logger of the service. To change the log level of the services, set the `[logger.level]{@link Logger#level}`.
+ * @name StorageServiceClient#logger
+ * @type Logger
+ * */
+ this.logger = new Logger(Logger.LogLevels.INFO);
+
+ this._setDefaultProxy();
+
+ this.xml2jsSettings = StorageServiceClient._getDefaultXml2jsSettings();
+ this.defaultLocationMode = StorageUtilities.LocationMode.PRIMARY_ONLY;
+}
+
+util.inherits(StorageServiceClient, events.EventEmitter);
+
+/**
+* Gets the default xml2js settings.
+* @ignore
+* @return {object} The default settings
+*/
+StorageServiceClient._getDefaultXml2jsSettings = function() {
+ var xml2jsSettings = _.clone(xml2js.defaults['0.2']);
+
+ // these determine what happens if the xml contains attributes
+ xml2jsSettings.attrkey = Constants.TableConstants.XML_METADATA_MARKER;
+ xml2jsSettings.charkey = Constants.TableConstants.XML_VALUE_MARKER;
+
+ // from xml2js guide: always put child nodes in an array if true; otherwise an array is created only if there is more than one.
+ xml2jsSettings.explicitArray = false;
+
+ return xml2jsSettings;
+};
+
+/**
+* Sets a host for the service.
+* @ignore
+* @param {string} host The host for the service.
+*/
+StorageServiceClient.prototype.setHost = function (host) {
+ var parseHost = function(hostUri){
+ var parsedHost;
+ if(!azureutil.objectIsNull(hostUri)) {
+ if(hostUri.indexOf('http') === -1 && hostUri.indexOf('//') !== 0){
+ hostUri = '//' + hostUri;
+ }
+ parsedHost = url.parse(hostUri, false, true);
+
+ if(!parsedHost.protocol){
+ parsedHost.protocol = ServiceSettings.DEFAULT_PROTOCOL;
+ }
+
+ if (!parsedHost.port) {
+ if (parsedHost.protocol === Constants.HTTPS) {
+ parsedHost.port = Constants.DEFAULT_HTTPS_PORT;
+ } else {
+ parsedHost.port = Constants.DEFAULT_HTTP_PORT;
+ }
+ }
+
+ parsedHost = url.format({
+ protocol: parsedHost.protocol,
+ port: parsedHost.port,
+ hostname: parsedHost.hostname,
+ pathname: parsedHost.pathname
+ });
+ }
+
+ return parsedHost;
+ };
+
+ validate.isValidHost(host);
+
+ this.host = {
+ primaryHost: parseHost(host.primaryHost),
+ secondaryHost: parseHost(host.secondaryHost)
+ };
+};
+
+/**
+* Performs a REST service request through HTTP expecting an input stream.
+* @ignore
+*
+* @param {WebResource} webResource The webresource on which to perform the request.
+* @param {string} outputData The outgoing request data as a raw string.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {function} callback The response callback function.
+*/
+StorageServiceClient.prototype.performRequest = function (webResource, outputData, options, callback) {
+ this._performRequest(webResource, { outputData: outputData }, options, callback);
+};
+
+/**
+* Performs a REST service request through HTTP expecting an input stream.
+* @ignore
+*
+* @param {WebResource} webResource The webresource on which to perform the request.
+* @param {Stream} outputStream The outgoing request data as a stream.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {function} callback The response callback function.
+*/
+StorageServiceClient.prototype.performRequestOutputStream = function (webResource, outputStream, options, callback) {
+ this._performRequest(webResource, { outputStream: outputStream }, options, callback);
+};
+
+/**
+* Performs a REST service request through HTTP expecting an input stream.
+* @ignore
+*
+* @param {WebResource} webResource The webresource on which to perform the request.
+* @param {string} outputData The outgoing request data as a raw string.
+* @param {Stream} inputStream The ingoing response data as a stream.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {function} callback The response callback function.
+*/
+StorageServiceClient.prototype.performRequestInputStream = function (webResource, outputData, inputStream, options, callback) {
+ this._performRequest(webResource, { outputData: outputData, inputStream: inputStream }, options, callback);
+};
+
+/**
+* Performs a REST service request through HTTP.
+* @ignore
+*
+* @param {WebResource} webResource The webresource on which to perform the request.
+* @param {object} body The request body.
+* @param {string} [body.outputData] The outgoing request data as a raw string.
+* @param {Stream} [body.outputStream] The outgoing request data as a stream.
+* @param {Stream} [body.inputStream] The ingoing response data as a stream.
+* @param {object} [options] The request options.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {function} callback The response callback function.
+*/
+StorageServiceClient.prototype._performRequest = function (webResource, body, options, callback) {
+ var self = this;
+
+ // Sets a requestId on the webResource
+ if(!options.clientRequestId) {
+ options.clientRequestId = guid.v1();
+ }
+
+ webResource.withHeader(HeaderConstants.CLIENT_REQUEST_ID, options.clientRequestId);
+
+ // Sets the user-agent string if the process is not started by the browser
+ if(!process.browser) {
+ var userAgentComment = util.format('(NODE-VERSION %s; %s %s)', process.version, os.type(), os.release());
+ webResource.withHeader(HeaderConstants.USER_AGENT, Constants.USER_AGENT_PRODUCT_NAME + '/' + Constants.USER_AGENT_PRODUCT_VERSION + ' ' + userAgentComment);
+ }
+
+ // Initialize the location that the request is going to be sent to.
+ if(azureutil.objectIsNull(options.locationMode)) {
+ options.locationMode = this.defaultLocationMode;
+ }
+
+ // Initialize the location that the request can be sent to.
+ if(azureutil.objectIsNull(options.requestLocationMode)) {
+ options.requestLocationMode = defaultRequestLocationMode;
+ }
+
+ // Initialize whether nagling is used or not.
+ if(azureutil.objectIsNull(options.useNagleAlgorithm)) {
+ options.useNagleAlgorithm = this.useNagleAlgorithm;
+ }
+
+ this._initializeLocation(options);
+
+ // Initialize the operationExpiryTime
+ this._setOperationExpiryTime(options);
+
+ // If the output stream already got sent to server and got error back,
+ // we should NOT retry within the SDK as the stream data is not valid anymore if we retry directly.
+ // And it's very hard for SDK to re-wind the stream.
+ //
+ // If users want to retry on this kind of error, they can implement their own logic to parse the response and
+ // determine if they need to re-prepare a stream and call our SDK API to retry.
+ //
+ // Currently for blobs/files with size greater than 32MB (DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES),
+ // we'll send the steam by chunk buffers which doesn't have this issue.
+ var outputStreamSent = false;
+
+ var operation = function (options, next) {
+ self._validateLocation(options);
+ var currentLocation = options.currentLocation;
+ self._buildRequestOptions(webResource, body, options, function (err, finalRequestOptions) {
+ if (err) {
+ callback({ error: err, response: null }, function (finalRequestOptions, finalCallback) {
+ finalCallback(finalRequestOptions);
+ });
+ } else {
+ self.logger.log(Logger.LogLevels.DEBUG, 'FINAL REQUEST OPTIONS:\n' + util.inspect(finalRequestOptions));
+
+ if(self._maximumExecutionTimeExceeded(Date.now(), options.operationExpiryTime)) {
+ callback({ error: new TimeoutError(SR.MAXIMUM_EXECUTION_TIMEOUT_EXCEPTION), response: null }, function (finalRequestOptions, finalCallback) {
+ finalCallback(finalRequestOptions);
+ });
+ } else {
+ var processResponseCallback = function (error, response) {
+ var responseObject;
+
+ if (error) {
+ responseObject = { error: error, response: null };
+ } else {
+ responseObject = self._processResponse(webResource, response, options);
+ responseObject.contentMD5 = response.contentMD5;
+ responseObject.length = response.length;
+ }
+
+ responseObject.operationEndTime = new Date();
+ // Required for listing operations to make sure successive operations go to the same location.
+ responseObject.targetLocation = currentLocation;
+ responseObject.outputStreamSent = outputStreamSent;
+
+ callback(responseObject, next);
+ };
+
+ var endResponse;
+ var buildRequest = function (headersOnly, inputStream) {
+ // Build request (if body was set before, request will process immediately, if not it'll wait for the piping to happen
+ var requestStream;
+
+ var requestWithDefaults;
+
+ if(self.proxy) {
+ if(requestWithDefaults === undefined) {
+ requestWithDefaults = request.defaults({'proxy':self.proxy});
+ }
+ } else {
+ requestWithDefaults = request;
+ }
+
+ if (headersOnly) {
+ requestStream = requestWithDefaults(finalRequestOptions);
+
+ requestStream.on('error', processResponseCallback);
+ requestStream.on('response', function (response) {
+ var isValid = WebResource.validResponse(response.statusCode);
+ if (!isValid) {
+ // When getting invalid response, try to get the error message for future steps to extract the detailed error information
+ var contentLength = parseInt(response.headers['content-length']);
+ var errorMessageBuffer;
+ var index = 0;
+ if (contentLength !== undefined) {
+ errorMessageBuffer = Buffer.alloc(contentLength);
+ }
+
+ requestStream.on('data', function (data) {
+ if (contentLength !== undefined) {
+ data.copy(errorMessageBuffer, index);
+ index += data.length;
+ } else {
+ if (!errorMessageBuffer) {
+ errorMessageBuffer = data;
+ } else {
+ errorMessageBuffer = Buffer.concat([errorMessageBuffer, data]);
+ }
+ }
+ });
+ requestStream.on('end', function () {
+ if (errorMessageBuffer) {
+ // Strip the UTF8 BOM following the same ways as 'request' module
+ if (errorMessageBuffer.length > 3 &&
+ errorMessageBuffer[0] === 239 &&
+ errorMessageBuffer[1] === 187 &&
+ errorMessageBuffer[2] === 191) {
+ response.body = errorMessageBuffer.toString('utf8', 3);
+ } else {
+ response.body = errorMessageBuffer.toString('utf8');
+ }
+ }
+ processResponseCallback(null, response);
+ });
+ } else {
+ // Only pipe to the destination stream when we get a valid response from service
+ // Error message should NOT be piped to the destination stream
+ if (inputStream) {
+ requestStream.pipe(inputStream);
+ }
+
+ var responseLength = 0;
+ var internalHash = new Md5Wrapper().createMd5Hash();
+ response.on('data', function(data) {
+ responseLength += data.length;
+ internalHash.update(data);
+ });
+
+ response.on('end', function () {
+ // Calculate and set MD5 here
+ if(azureutil.objectIsNull(options.disableContentMD5Validation) || options.disableContentMD5Validation === false) {
+ response.contentMD5 = internalHash.digest('base64');
+ }
+
+ response.length = responseLength;
+ endResponse = response;
+ });
+ }
+ });
+ } else {
+ requestStream = requestWithDefaults(finalRequestOptions, processResponseCallback);
+ }
+
+ //If useNagleAlgorithm is not set or the value is set and is false, setNoDelay is set to true.
+ if (azureutil.objectIsNull(options.useNagleAlgorithm) || options.useNagleAlgorithm === false) {
+ requestStream.on('request', function(httpRequest) {
+ httpRequest.setNoDelay(true);
+ });
+ }
+
+ // Workaround to avoid request from potentially setting unwanted (rejected) headers by the service
+ var oldEnd = requestStream.end;
+ requestStream.end = function () {
+ if (finalRequestOptions.headers['content-length']) {
+ requestStream.headers['content-length'] = finalRequestOptions.headers['content-length'];
+ } else if (requestStream.headers['content-length']) {
+ delete requestStream.headers['content-length'];
+ }
+
+ oldEnd.call(requestStream);
+ };
+
+ // Bubble events up -- This is when the request is going to be made.
+ requestStream.on('response', function (response) {
+ self.emit('receivedResponseEvent', response);
+ });
+
+ return requestStream;
+ };
+
+ if (body && body.outputData) {
+ if (!azureutil.isBrowser() && Buffer.isBuffer(body.outputData)) {
+ // Request module will take 200MB additional memory when we pass a 100MB buffer as body
+ // Transfer buffer to stream will highly reduce the memory used by request module
+ finalRequestOptions.body = new BufferStream(body.outputData);
+ } else {
+ finalRequestOptions.body = body.outputData;
+ }
+ }
+
+ // Pipe any input / output streams
+ if (body && body.inputStream) {
+ body.inputStream.on('close', function () {
+ if (endResponse) {
+ processResponseCallback(null, endResponse);
+ endResponse = null;
+ }
+ });
+ body.inputStream.on('end', function () {
+ if (endResponse) {
+ processResponseCallback(null, endResponse);
+ endResponse = null;
+ }
+ });
+ body.inputStream.on('finish', function () {
+ if (endResponse) {
+ processResponseCallback(null, endResponse);
+ endResponse = null;
+ }
+ });
+ buildRequest(true, body.inputStream);
+ } else if (body && body.outputStream) {
+ var sendUnchunked = function () {
+ var size = finalRequestOptions.headers['content-length'] ?
+ finalRequestOptions.headers['content-length'] :
+ Constants.BlobConstants.MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES;
+
+ var concatBuf = Buffer.alloc(parseInt(size));
+ var index = 0;
+
+ body.outputStream.on('data', function (d) {
+ outputStreamSent = true;
+ if(self._maximumExecutionTimeExceeded(Date.now(), options.operationExpiryTime)) {
+ processResponseCallback(new TimeoutError(SR.MAXIMUM_EXECUTION_TIMEOUT_EXCEPTION));
+ } else {
+ d.copy(concatBuf, index);
+ index += d.length;
+ }
+ }).on('end', function () {
+ var requestStream = buildRequest();
+ requestStream.write(concatBuf);
+ requestStream.end();
+ });
+ if (azureutil.isStreamPaused(body.outputStream)) {
+ body.outputStream.resume();
+ }
+ };
+
+ var sendStream = function () {
+ // NOTE: workaround for an unexpected EPIPE exception when piping streams larger than 29 MB
+ if (!azureutil.objectIsNull(finalRequestOptions.headers['content-length']) && finalRequestOptions.headers['content-length'] < 29 * 1024 * 1024) {
+ body.outputStream.pipe(buildRequest());
+ outputStreamSent = true;
+
+ if (azureutil.isStreamPaused(body.outputStream)) {
+ body.outputStream.resume();
+ }
+ } else {
+ sendUnchunked();
+ }
+ };
+
+ if (!body.outputStream.readable) {
+ // if the content length is zero, build the request and don't send a body
+ if (finalRequestOptions.headers['content-length'] === 0) {
+ buildRequest();
+ } else {
+ // otherwise, wait until we know the readable stream is actually valid before piping
+ body.outputStream.on('open', function () {
+ sendStream();
+ });
+ }
+ } else {
+ sendStream();
+ }
+
+ // This catches any errors that happen while creating the readable stream (usually invalid names)
+ body.outputStream.on('error', function (error) {
+ processResponseCallback(error);
+ });
+ } else {
+ buildRequest();
+ }
+ }
+ }
+ });
+ };
+
+ // The filter will do what it needs to the requestOptions and will provide a
+ // function to be handled after the reply
+ self.filter(options, function (postFiltersRequestOptions, nextPostCallback) {
+ if(self._maximumExecutionTimeExceeded(Date.now() + postFiltersRequestOptions.retryInterval, postFiltersRequestOptions.operationExpiryTime)) {
+ callback({ error: new TimeoutError(SR.MAXIMUM_EXECUTION_TIMEOUT_EXCEPTION), response: null}, function (postFiltersRequestOptions, finalCallback) {
+ finalCallback(postFiltersRequestOptions);
+ });
+ } else {
+ // If there is a filter, flow is:
+ // filter -> operation -> process response
+ if(postFiltersRequestOptions.retryContext) {
+ var func = function() {
+ operation(postFiltersRequestOptions, nextPostCallback);
+ };
+
+ // Sleep for retryInterval before making the request
+ setTimeout(func, postFiltersRequestOptions.retryInterval);
+ } else {
+ // No retry policy filter specified
+ operation(postFiltersRequestOptions, nextPostCallback);
+ }
+ }
+ });
+};
+
+
+/**
+* Builds the request options to be passed to the http.request method.
+* @ignore
+* @param {WebResource} webResource The webresource where to build the options from.
+* @param {object} options The request options.
+* @param {function(error, requestOptions)} callback The callback function.
+*/
+StorageServiceClient.prototype._buildRequestOptions = function (webResource, body, options, callback) {
+ webResource.withHeader(HeaderConstants.STORAGE_VERSION, this.apiVersion);
+ webResource.withHeader(HeaderConstants.MS_DATE, new Date().toUTCString());
+ if (!webResource.headers[HeaderConstants.ACCEPT]) {
+ webResource.withHeader(HeaderConstants.ACCEPT, 'application/atom+xml,application/xml');
+ }
+ webResource.withHeader(HeaderConstants.ACCEPT_CHARSET, 'UTF-8');
+
+ // Browsers cache GET/HEAD requests by adding conditional headers such as 'IF_MODIFIED_SINCE' after Azure Storage 'Authorization header' calculation,
+ // which may result in a 403 authorization error. So add timestamp to GET/HEAD request URLs thus avoid the browser cache.
+ if (azureutil.isBrowser() && (
+ webResource.method === Constants.HttpConstants.HttpVerbs.GET ||
+ webResource.method === Constants.HttpConstants.HttpVerbs.HEAD)) {
+ webResource.withQueryOption(HeaderConstants.FORCE_NO_CACHE_IN_BROWSER, new Date().getTime());
+ }
+
+ if(azureutil.objectIsNull(options.timeoutIntervalInMs)) {
+ options.timeoutIntervalInMs = this.defaultTimeoutIntervalInMs;
+ }
+
+ if(azureutil.objectIsNull(options.clientRequestTimeoutInMs)) {
+ options.clientRequestTimeoutInMs = this.defaultClientRequestTimeoutInMs;
+ }
+
+ if(!azureutil.objectIsNull(options.timeoutIntervalInMs) && options.timeoutIntervalInMs > 0) {
+ webResource.withQueryOption(QueryStringConstants.TIMEOUT, Math.ceil(options.timeoutIntervalInMs / 1000));
+ }
+
+ if(options.accessConditions) {
+ webResource.withHeader(HeaderConstants.IF_MATCH, options.accessConditions.EtagMatch);
+ webResource.withHeader(HeaderConstants.IF_MODIFIED_SINCE, options.accessConditions.DateModifedSince);
+ webResource.withHeader(HeaderConstants.IF_NONE_MATCH, options.accessConditions.EtagNonMatch);
+ webResource.withHeader(HeaderConstants.IF_UNMODIFIED_SINCE, options.accessConditions.DateUnModifiedSince);
+ webResource.withHeader(HeaderConstants.SEQUENCE_NUMBER_EQUAL, options.accessConditions.SequenceNumberEqual);
+ webResource.withHeader(HeaderConstants.SEQUENCE_NUMBER_LESS_THAN, options.accessConditions.SequenceNumberLessThan);
+ webResource.withHeader(HeaderConstants.SEQUENCE_NUMBER_LESS_THAN_OR_EQUAL, options.accessConditions.SequenceNumberLessThanOrEqual);
+ webResource.withHeader(HeaderConstants.BLOB_CONDITION_MAX_SIZE, options.accessConditions.MaxBlobSize);
+ webResource.withHeader(HeaderConstants.BLOB_CONDITION_APPEND_POSITION, options.accessConditions.MaxAppendPosition);
+ }
+
+ if(options.sourceAccessConditions) {
+ webResource.withHeader(HeaderConstants.SOURCE_IF_MATCH, options.sourceAccessConditions.EtagMatch);
+ webResource.withHeader(HeaderConstants.SOURCE_IF_MODIFIED_SINCE, options.sourceAccessConditions.DateModifedSince);
+ webResource.withHeader(HeaderConstants.SOURCE_IF_NONE_MATCH, options.sourceAccessConditions.EtagNonMatch);
+ webResource.withHeader(HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE, options.sourceAccessConditions.DateUnModifiedSince);
+ }
+
+ if (!webResource.headers || webResource.headers[HeaderConstants.CONTENT_TYPE] === undefined) {
+ // work around to add an empty content type header to prevent the request module from magically adding a content type.
+ webResource.headers[HeaderConstants.CONTENT_TYPE] = '';
+ } else if (webResource.headers && webResource.headers[HeaderConstants.CONTENT_TYPE] === null) {
+ delete webResource.headers[HeaderConstants.CONTENT_TYPE];
+ }
+
+ if (!webResource.headers || webResource.headers[HeaderConstants.CONTENT_LENGTH] === undefined) {
+ if (body && body.outputData) {
+ webResource.withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(body.outputData, 'UTF8'));
+ } else if (webResource.headers[HeaderConstants.CONTENT_LENGTH] === undefined) {
+ webResource.withHeader(HeaderConstants.CONTENT_LENGTH, 0);
+ }
+ } else if (webResource.headers && webResource.headers[HeaderConstants.CONTENT_LENGTH] === null) {
+ delete webResource.headers[HeaderConstants.CONTENT_LENGTH];
+ }
+
+ var enableGlobalHttpAgent = this.enableGlobalHttpAgent;
+
+ // Sets the request url in the web resource.
+ this._setRequestUrl(webResource, options);
+
+ this.emit('sendingRequestEvent', webResource);
+
+ // Now that the web request is finalized, sign it
+ this.storageCredentials.signRequest(webResource, function (error) {
+ var requestOptions = null;
+
+ if (!error) {
+ var targetUrl = webResource.uri;
+
+ requestOptions = {
+ uri: url.format(targetUrl),
+ method: webResource.method,
+ headers: webResource.headers,
+ mode: 'disable-fetch'
+ };
+
+ if (options) {
+ //set encoding of response data. If set to null, the body is returned as a Buffer
+ requestOptions.encoding = options.responseEncoding;
+ }
+
+ if (options && options.clientRequestTimeoutInMs) {
+ requestOptions.timeout = options.clientRequestTimeoutInMs;
+ } else {
+ requestOptions.timeout = Constants.DEFAULT_CLIENT_REQUEST_TIMEOUT_IN_MS; // 2 minutes
+ }
+
+ // If global HTTP agent is not enabled, use forever agent.
+ if (enableGlobalHttpAgent !== true) {
+ requestOptions.forever = true;
+ }
+ }
+
+ callback(error, requestOptions);
+ });
+};
+
+/**
+* Process the response.
+* @ignore
+*
+* @param {WebResource} webResource The web resource that made the request.
+* @param {Response} response The response object.
+* @param {Options} options The response parsing options.
+* @param {String} options.payloadFormat The payload format.
+* @return The normalized responseObject.
+*/
+StorageServiceClient.prototype._processResponse = function (webResource, response, options) {
+ var self = this;
+
+ function convertRawHeadersToHeaders(rawHeaders) {
+ var headers = {};
+ if(!rawHeaders) {
+ return undefined;
+ }
+
+ for(var i = 0; i < rawHeaders.length; i++) {
+ var headerName;
+ if (rawHeaders[i].indexOf(HeaderConstants.PREFIX_FOR_STORAGE_METADATA) === 0) {
+ headerName = rawHeaders[i];
+ } else {
+ headerName = rawHeaders[i].toLowerCase();
+ }
+ headers[headerName] = rawHeaders[++i];
+ }
+
+ return headers;
+ }
+
+ var validResponse = WebResource.validResponse(response.statusCode);
+ var rsp = StorageServiceClient._buildResponse(validResponse, response.body, convertRawHeadersToHeaders(response.rawHeaders) || response.headers, response.statusCode, response.md5);
+ var responseObject;
+
+ if (validResponse && webResource.rawResponse) {
+ responseObject = { error: null, response: rsp };
+ } else {
+ // attempt to parse the response body, errors will be returned in rsp.error without modifying the body
+ rsp = StorageServiceClient._parseResponse(rsp, self.xml2jsSettings, options);
+
+ if (validResponse && !rsp.error) {
+ responseObject = { error: null, response: rsp };
+ } else {
+ rsp.isSuccessful = false;
+
+ if (response.statusCode < 400 || response.statusCode >= 500) {
+ this.logger.log(Logger.LogLevels.DEBUG,
+ 'ERROR code = ' + response.statusCode + ' :\n' + util.inspect(rsp.body));
+ }
+
+ // responseObject.error should contain normalized parser errors if they occured in _parseResponse
+ // responseObject.response.body should contain the raw response body in that case
+ var errorBody = rsp.body;
+ if(rsp.error) {
+ errorBody = rsp.error;
+ delete rsp.error;
+ }
+
+ if (!errorBody) {
+ var code = Object.keys(HttpResponseCodes).filter(function (name) {
+ if (HttpResponseCodes[name] === rsp.statusCode) {
+ return name;
+ }
+ });
+
+ errorBody = { error: { code: code[0] } };
+ }
+
+ var normalizedError = StorageServiceClient._normalizeError(errorBody, response);
+ responseObject = { error: normalizedError, response: rsp };
+ }
+ }
+
+ this.logger.log(Logger.LogLevels.DEBUG, 'RESPONSE:\n' + util.inspect(responseObject));
+
+ return responseObject;
+};
+
+/**
+* Associate a filtering operation with this StorageServiceClient. Filtering operations
+* can include logging, automatically retrying, etc. Filter operations are objects
+* that implement a method with the signature:
+*
+* "function handle (requestOptions, next)".
+*
+* After doing its preprocessing on the request options, the method needs to call
+* "next" passing a callback with the following signature:
+* signature:
+*
+* "function (returnObject, finalCallback, next)"
+*
+* In this callback, and after processing the returnObject (the response from the
+* request to the server), the callback needs to either invoke next if it exists to
+* continue processing other filters or simply invoke finalCallback otherwise to end
+* up the service invocation.
+*
+* @param {Object} filter The new filter object.
+* @return {StorageServiceClient} A new service client with the filter applied.
+*/
+StorageServiceClient.prototype.withFilter = function (newFilter) {
+ // Create a new object with the same members as the current service
+ var derived = _.clone(this);
+
+ // If the current service has a filter, merge it with the new filter
+ // (allowing us to effectively pipeline a series of filters)
+ var parentFilter = this.filter;
+ var mergedFilter = newFilter;
+ if (parentFilter !== undefined) {
+ // The parentFilterNext is either the operation or the nextPipe function generated on a previous merge
+ // Ordering is [f3 pre] -> [f2 pre] -> [f1 pre] -> operation -> [f1 post] -> [f2 post] -> [f3 post]
+ mergedFilter = function (originalRequestOptions, parentFilterNext) {
+ newFilter.handle(originalRequestOptions, function (postRequestOptions, newFilterCallback) {
+ // handle parent filter pre and get Parent filter post
+ var next = function (postPostRequestOptions, parentFilterCallback) {
+ // The parentFilterNext is the filter next to the merged filter.
+ // For 2 filters, that'd be the actual operation.
+ parentFilterNext(postPostRequestOptions, function (responseObject, responseCallback, finalCallback) {
+ parentFilterCallback(responseObject, finalCallback, function (postResponseObject) {
+ newFilterCallback(postResponseObject, responseCallback, finalCallback);
+ });
+ });
+ };
+
+ parentFilter(postRequestOptions, next);
+ });
+ };
+ }
+
+ // Store the filter so it can be applied in performRequest
+ derived.filter = mergedFilter;
+ return derived;
+ };
+
+/*
+* Builds a response object with normalized key names.
+* @ignore
+*
+* @param {Bool} isSuccessful Boolean value indicating if the request was successful
+* @param {Object} body The response body.
+* @param {Object} headers The response headers.
+* @param {int} statusCode The response status code.
+* @param {string} md5 The response's content md5 hash.
+* @return {Object} A response object.
+*/
+StorageServiceClient._buildResponse = function (isSuccessful, body, headers, statusCode, md5) {
+ var response = {
+ isSuccessful: isSuccessful,
+ statusCode: statusCode,
+ body: body,
+ headers: headers,
+ md5: md5
+ };
+
+ if (!azureutil.objectIsNull(headers)) {
+ if (headers[HeaderConstants.REQUEST_SERVER_ENCRYPTED] !== undefined) {
+ response.requestServerEncrypted = (headers[HeaderConstants.REQUEST_SERVER_ENCRYPTED] === 'true');
+ }
+ }
+
+ return response;
+};
+
+/**
+* Parses a server response body from XML or JSON into a JS object.
+* This is done using the xml2js library.
+* @ignore
+*
+* @param {object} response The response object with a property "body" with a XML or JSON string content.
+* @param {object} xml2jsSettings The XML to json settings.
+* @param {Options} options The response parsing options.
+* @param {String} options.payloadFormat The payload format.
+* @return {object} The same response object with the body part as a JS object instead of a XML or JSON string.
+*/
+StorageServiceClient._parseResponse = function (response, xml2jsSettings, options) {
+ function parseXml(body) {
+ var parsed;
+ var parser = new xml2js.Parser(xml2jsSettings);
+ parser.parseString(azureutil.removeBOM(body.toString()), function (err, parsedBody) {
+ if (err) {
+ var xmlError = new SyntaxError('EXMLFORMAT');
+ xmlError.innerError = err;
+ throw xmlError;
+ } else { parsed = parsedBody; }
+ });
+
+ return parsed;
+ }
+
+ if (response.body && Buffer.byteLength(response.body.toString()) > 0) {
+ var contentType = '';
+ if (response.headers && response.headers['content-type']) {
+ contentType = response.headers['content-type'].toLowerCase();
+ }
+
+ try {
+ if (contentType.indexOf('application/json') !== -1) {
+ if (options && options.payloadFormat && options.payloadFormat !== TableUtilities.PayloadFormat.NO_METADATA) {
+ var parser = new Parser();
+ parser.onValue = function (value) {
+ response.body = value;
+ };
+ parser.write(response.body);
+ } else {
+ response.body = JSON.parse(response.body);
+ }
+ } else if (contentType.indexOf('application/xml') !== -1 || contentType.indexOf('application/atom+xml') !== -1) {
+ response.body = parseXml(response.body);
+ } else if (contentType.indexOf('text/html') !== -1) {
+ response.body = response.body;
+ } else {
+ response.body = parseXml(response.body);
+ // throw new SyntaxError(SR.CONTENT_TYPE_MISSING, null);
+ }
+ } catch (e) {
+ response.error = e;
+ }
+ }
+
+ return response;
+};
+
+/**
+* Gets the storage settings.
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [sas] The Shared Access Signature string.
+* @param {TokenCredential} [token] The {@link TokenCredential} object.
+*
+* @return {StorageServiceSettings}
+*/
+StorageServiceClient.getStorageSettings = function (storageAccountOrConnectionString, storageAccessKey, host, sas, endpointSuffix, token) {
+ var storageServiceSettings;
+ if (storageAccountOrConnectionString && !storageAccessKey && !sas) {
+ // If storageAccountOrConnectionString was passed and no accessKey was passed, assume connection string
+ storageServiceSettings = StorageServiceSettings.createFromConnectionString(storageAccountOrConnectionString);
+ } else if ((storageAccountOrConnectionString && storageAccessKey) || sas || token || host) {
+ // Account and key or credentials or anonymous
+ storageServiceSettings = StorageServiceSettings.createExplicitly(storageAccountOrConnectionString, storageAccessKey, host, sas, endpointSuffix, token);
+ } else {
+ // Use environment variables
+ storageServiceSettings = StorageServiceSettings.createFromEnvironment();
+ }
+
+ return storageServiceSettings;
+};
+
+/**
+* Sets the webResource's requestUrl based on the service client settings.
+* @ignore
+*
+* @param {WebResource} webResource The web resource where to set the request url.
+*/
+StorageServiceClient.prototype._setRequestUrl = function (webResource, options) {
+ // Normalize the path
+ // Backup the original path of the webResource to make sure it works fine even this function get executed multiple times - like RetryFilter
+ webResource.originalPath = webResource.originalPath || webResource.path;
+ webResource.path = this._getPath(webResource.originalPath);
+
+ if(!this.host){
+ throw new ArgumentNullError('this.host', SR.STORAGE_HOST_LOCATION_REQUIRED);
+ }
+
+ var host = this.host.primaryHost;
+
+ if(!azureutil.objectIsNull(options) && options.currentLocation === Constants.StorageLocation.SECONDARY) {
+ host = this.host.secondaryHost;
+ }
+
+ if(host && host.lastIndexOf('/') !== (host.length - 1)){
+ host = host + '/';
+ }
+
+ var fullPath = url.format({pathname: webResource.path, query: webResource.queryString});
+ webResource.uri = url.resolve(host, fullPath);
+ webResource.path = url.parse(webResource.uri).pathname;
+};
+
+/**
+* Retrieves the normalized path to be used in a request.
+* It also removes any leading "/" of the path in case
+* it's there before.
+* @ignore
+* @param {string} path The path to be normalized.
+* @return {string} The normalized path.
+*/
+StorageServiceClient.prototype._getPath = function (path) {
+ if (path === null || path === undefined) {
+ path = '';
+ } else if (path.indexOf('/') === 0) {
+ path = path.substring(1);
+ }
+
+ return path;
+};
+
+/**
+ * Get the url of a given path
+ */
+StorageServiceClient.prototype._getUrl = function (path, sasToken, primary) {
+ var host;
+ if (!azureutil.objectIsNull(primary) && primary === false) {
+ host = this.host.secondaryHost;
+ } else {
+ host = this.host.primaryHost;
+ }
+
+ host = azureutil.trimPortFromUri(host);
+ if(host && host.lastIndexOf('/') !== (host.length - 1)){
+ host = host + '/';
+ }
+
+ var query = qs.parse(sasToken);
+ var fullPath = url.format({ pathname: this._getPath(path), query: query });
+ return url.resolve(host, fullPath);
+};
+
+/**
+* Initializes the default filter.
+* This filter is responsible for chaining the pre filters request into the operation and, after processing the response,
+* pass it to the post processing filters. This method should only be invoked by the StorageServiceClient constructor.
+* @ignore
+*
+*/
+StorageServiceClient.prototype._initDefaultFilter = function () {
+ this.filter = function (requestOptions, nextPreCallback) {
+ if (nextPreCallback) {
+ // Handle the next pre callback and pass the function to be handled as post call back.
+ nextPreCallback(requestOptions, function (returnObject, finalCallback, nextPostCallback) {
+ if (nextPostCallback) {
+ nextPostCallback(returnObject);
+ } else if (finalCallback) {
+ finalCallback(returnObject);
+ }
+ });
+ }
+ };
+};
+
+/**
+* Retrieves the metadata headers from the response headers.
+* @ignore
+*
+* @param {object} headers The metadata headers.
+* @return {object} An object with the metadata headers (without the "x-ms-" prefix).
+*/
+StorageServiceClient.prototype.parseMetadataHeaders = function (headers) {
+ var metadata = {};
+
+ if (!headers) {
+ return metadata;
+ }
+
+ for (var header in headers) {
+ if (header.indexOf(HeaderConstants.PREFIX_FOR_STORAGE_METADATA) === 0) {
+ var key = header.substr(HeaderConstants.PREFIX_FOR_STORAGE_METADATA.length, header.length - HeaderConstants.PREFIX_FOR_STORAGE_METADATA.length);
+ metadata[key] = headers[header];
+ }
+ }
+
+ return metadata;
+};
+
+/**
+* Gets the properties of a storage account’s service, including Azure Storage Analytics.
+* @ignore
+*
+* @this {StorageServiceClient}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `result` will contain the properties
+* and `response` will contain information related to this operation.
+*/
+StorageServiceClient.prototype.getAccountServiceProperties = function (optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getServiceProperties', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var webResource = WebResource.get()
+ .withQueryOption(QueryStringConstants.COMP, 'properties')
+ .withQueryOption(QueryStringConstants.RESTYPE, 'service');
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.servicePropertiesResult = null;
+ if (!responseObject.error) {
+ responseObject.servicePropertiesResult = ServicePropertiesResult.parse(responseObject.response.body.StorageServiceProperties);
+ }
+
+ // function to be called after all filters
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.servicePropertiesResult, returnObject.response);
+ };
+
+ // call the first filter
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets the properties of a storage account’s service, including Azure Storage Analytics.
+* You can also use this operation to set the default request version for all incoming requests that do not have a version specified.
+*
+* @this {StorageServiceClient}
+* @param {object} serviceProperties The service properties.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise, `response`
+* will contain information related to this operation.
+*/
+StorageServiceClient.prototype.setAccountServiceProperties = function (serviceProperties, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setServiceProperties', function (v) {
+ v.object(serviceProperties, 'serviceProperties');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var servicePropertiesXml = ServicePropertiesResult.serialize(serviceProperties);
+
+ var webResource = WebResource.put()
+ .withQueryOption(QueryStringConstants.COMP, 'properties')
+ .withQueryOption(QueryStringConstants.RESTYPE, 'service')
+ .withHeader(HeaderConstants.CONTENT_TYPE, 'application/xml;charset="utf-8"')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(servicePropertiesXml))
+ .withBody(servicePropertiesXml);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+// Other functions
+
+/**
+* Processes the error body into a normalized error object with all the properties lowercased.
+*
+* Error information may be returned by a service call with additional debugging information:
+* http://msdn.microsoft.com/en-us/library/windowsazure/dd179382.aspx
+*
+* Table services returns these properties lowercased, example, "code" instead of "Code". So that the user
+* can always expect the same format, this method lower cases everything.
+*
+* @ignore
+*
+* @param {Object} error The error object as returned by the service and parsed to JSON by the xml2json.
+* @return {Object} The normalized error object with all properties lower cased.
+*/
+StorageServiceClient._normalizeError = function (error, response) {
+ if (azureutil.objectIsString(error)) {
+ return new StorageError(error, null);
+ } else if (error) {
+ var normalizedError = {};
+
+ // blob/queue errors should have error.Error, table errors should have error['odata.error']
+ var errorProperties = error.Error || error.error || error['odata.error'] || error['m:error'] || error;
+ normalizedError.code = errorProperties.message; // The message exists when there is error.Error.
+
+ for (var property in errorProperties) {
+ if (errorProperties.hasOwnProperty(property)) {
+ var key = property.toLowerCase();
+ if(key.indexOf('m:') === 0) {
+ key = key.substring(2);
+ }
+
+ normalizedError[key] = errorProperties[property];
+
+ // if this is a table error, message is an object - flatten it to normalize with blob/queue errors
+ // ex: "message":{"lang":"en-US","value":"The specified resource does not exist."} becomes message: "The specified resource does not exist."
+ if (key === 'message' && _.isObject(errorProperties[property])) {
+ if (errorProperties[property]['value']) {
+ normalizedError[key] = errorProperties[property]['value'];
+ }
+ }
+ }
+ }
+
+ // add status code and server request id if available
+ if (response) {
+ if (response.statusCode) {
+ normalizedError.statusCode = response.statusCode;
+ }
+
+ if (response.headers && response.headers['x-ms-request-id']) {
+ normalizedError.requestId = response.headers['x-ms-request-id'];
+ }
+ }
+
+ var errorObject = new StorageError(normalizedError.code, normalizedError);
+ return errorObject;
+ }
+
+ return null;
+};
+
+/**
+* Sets proxy object specified by caller.
+*
+* @param {object} proxy proxy to use for tunneling
+* {
+* host: hostname
+* port: port number
+* proxyAuth: 'user:password' for basic auth
+* headers: {...} headers for proxy server
+* key: key for proxy server
+* ca: ca for proxy server
+* cert: cert for proxy server
+* }
+* if null or undefined, clears proxy
+*/
+StorageServiceClient.prototype.setProxy = function (proxy) {
+ if (proxy) {
+ this.proxy = proxy;
+ } else {
+ this.proxy = null;
+ }
+};
+
+/**
+* Sets the service host default proxy from the environment.
+* Can be overridden by calling _setProxyUrl or _setProxy
+*
+*/
+StorageServiceClient.prototype._setDefaultProxy = function () {
+ var proxyUrl = StorageServiceClient._loadEnvironmentProxyValue();
+ if (proxyUrl) {
+ var parsedUrl = url.parse(proxyUrl);
+ if (!parsedUrl.port) {
+ parsedUrl.port = 80;
+ }
+ this.setProxy(parsedUrl);
+ } else {
+ this.setProxy(null);
+ }
+};
+
+/*
+* Loads the fields "useProxy" and respective protocol, port and url
+* from the environment values HTTPS_PROXY and HTTP_PROXY
+* in case those are set.
+* @ignore
+*
+* @return {string} or null
+*/
+StorageServiceClient._loadEnvironmentProxyValue = function () {
+ var proxyUrl = null;
+ if (process.env[StorageServiceClientConstants.EnvironmentVariables.HTTPS_PROXY]) {
+ proxyUrl = process.env[StorageServiceClientConstants.EnvironmentVariables.HTTPS_PROXY];
+ } else if (process.env[StorageServiceClientConstants.EnvironmentVariables.HTTPS_PROXY.toLowerCase()]) {
+ proxyUrl = process.env[StorageServiceClientConstants.EnvironmentVariables.HTTPS_PROXY.toLowerCase()];
+ } else if (process.env[StorageServiceClientConstants.EnvironmentVariables.HTTP_PROXY]) {
+ proxyUrl = process.env[StorageServiceClientConstants.EnvironmentVariables.HTTP_PROXY];
+ } else if (process.env[StorageServiceClientConstants.EnvironmentVariables.HTTP_PROXY.toLowerCase()]) {
+ proxyUrl = process.env[StorageServiceClientConstants.EnvironmentVariables.HTTP_PROXY.toLowerCase()];
+ }
+
+ return proxyUrl;
+};
+
+/**
+* Initializes the location to which the operation is being sent to.
+*/
+StorageServiceClient.prototype._initializeLocation = function (options) {
+ if(!azureutil.objectIsNull(options.locationMode)) {
+ switch(options.locationMode) {
+ case StorageUtilities.LocationMode.PRIMARY_ONLY:
+ case StorageUtilities.LocationMode.PRIMARY_THEN_SECONDARY:
+ options.currentLocation = Constants.StorageLocation.PRIMARY;
+ break;
+ case StorageUtilities.LocationMode.SECONDARY_ONLY:
+ case StorageUtilities.LocationMode.SECONDARY_THEN_PRIMARY:
+ options.currentLocation = Constants.StorageLocation.SECONDARY;
+ break;
+ default:
+ throw new RangeError(util.format(SR.ARGUMENT_OUT_OF_RANGE_ERROR, 'locationMode', options.locationMode));
+ }
+ } else {
+ options.locationMode = StorageUtilities.LocationMode.PRIMARY_ONLY;
+ options.currentLocation = Constants.StorageLocation.PRIMARY;
+ }
+};
+
+/**
+* Validates the location to which the operation is being sent to.
+*/
+StorageServiceClient.prototype._validateLocation = function (options) {
+ if(this._invalidLocationMode(options.locationMode)) {
+ throw new ArgumentNullError('host', SR.STORAGE_HOST_MISSING_LOCATION);
+ }
+
+ switch(options.requestLocationMode) {
+ case Constants.RequestLocationMode.PRIMARY_ONLY:
+ if(options.locationMode === StorageUtilities.LocationMode.SECONDARY_ONLY) {
+ throw new ArgumentError('host.primaryHost', SR.PRIMARY_ONLY_COMMAND);
+ }
+
+ options.currentLocation = Constants.StorageLocation.PRIMARY;
+ options.locationMode = StorageUtilities.LocationMode.PRIMARY_ONLY;
+ break;
+
+ case Constants.RequestLocationMode.SECONDARY_ONLY:
+ if(options.locationMode === StorageUtilities.LocationMode.PRIMARY_ONLY) {
+ throw new ArgumentError('host.secondaryHost', SR.SECONDARY_ONLY_COMMAND);
+ }
+
+ options.currentLocation = Constants.StorageLocation.SECONDARY;
+ options.locationMode = StorageUtilities.LocationMode.SECONDARY_ONLY;
+ break;
+
+ default:
+ // no op
+ }
+};
+
+/**
+* Checks whether we have the relevant host information based on the locationMode.
+*/
+StorageServiceClient.prototype._invalidLocationMode = function (locationMode) {
+ switch(locationMode) {
+ case StorageUtilities.LocationMode.PRIMARY_ONLY:
+ return azureutil.objectIsNull(this.host.primaryHost);
+ case StorageUtilities.LocationMode.SECONDARY_ONLY:
+ return azureutil.objectIsNull(this.host.secondaryHost);
+ default:
+ return (azureutil.objectIsNull(this.host.primaryHost) || azureutil.objectIsNull(this.host.secondaryHost));
+ }
+};
+
+/**
+* Checks to see if the maximum execution timeout provided has been exceeded.
+*/
+StorageServiceClient.prototype._maximumExecutionTimeExceeded = function (currentTime, expiryTime) {
+ if(!azureutil.objectIsNull(expiryTime) && currentTime > expiryTime) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+/**
+* Sets the operation expiry time.
+*/
+StorageServiceClient.prototype._setOperationExpiryTime = function (options) {
+ if(azureutil.objectIsNull(options.operationExpiryTime)) {
+ if(!azureutil.objectIsNull(options.maximumExecutionTimeInMs)) {
+ options.operationExpiryTime = Date.now() + options.maximumExecutionTimeInMs;
+ } else if(this.defaultMaximumExecutionTimeInMs) {
+ options.operationExpiryTime = Date.now() + this.defaultMaximumExecutionTimeInMs;
+ }
+ }
+};
+
+module.exports = StorageServiceClient;
diff --git a/src/node_modules/azure-storage/lib/common/services/storageservicesettings.js b/src/node_modules/azure-storage/lib/common/services/storageservicesettings.js
new file mode 100644
index 0000000..44b1c6a
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/services/storageservicesettings.js
@@ -0,0 +1,450 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+'use strict';
+
+var _ = require('underscore');
+var url = require('url');
+
+var util = require('../util/util');
+var ServiceSettings = require('./servicesettings');
+var Constants = require('../util/constants');
+var StorageServiceClientConstants = Constants.StorageServiceClientConstants;
+var ConnectionStringKeys = Constants.ConnectionStringKeys;
+var Validate = require('../util/validate');
+var SR = require('../util/sr');
+var TokenCredential = require('../models/tokencredential');
+
+var useDevelopmentStorageSetting = ServiceSettings.setting(ConnectionStringKeys.USE_DEVELOPMENT_STORAGE_NAME, true);
+var developmentStorageProxyUriSetting = ServiceSettings.settingWithFunc(ConnectionStringKeys.DEVELOPMENT_STORAGE_PROXY_URI_NAME, Validate.isValidUri);
+var defaultEndpointsProtocolSetting = ServiceSettings.setting(ConnectionStringKeys.DEFAULT_ENDPOINTS_PROTOCOL_NAME, 'http', 'https');
+var accountNameSetting = ServiceSettings.setting(ConnectionStringKeys.ACCOUNT_NAME_NAME);
+var accountKeySetting = ServiceSettings.settingWithFunc(ConnectionStringKeys.ACCOUNT_KEY_NAME, Validate.isBase64Encoded);
+var sasSetting = ServiceSettings.settingWithFunc(ConnectionStringKeys.SHARED_ACCESS_SIGNATURE_NAME, _.isString);
+var tokenSetting = ServiceSettings.settingWithFunc('token', function (object) {return object instanceof TokenCredential;});
+
+var blobEndpointSetting = ServiceSettings.settingWithFunc(
+ ConnectionStringKeys.BLOB_ENDPOINT_NAME,
+ Validate.isValidHost
+);
+
+var queueEndpointSetting = ServiceSettings.settingWithFunc(
+ ConnectionStringKeys.QUEUE_ENDPOINT_NAME,
+ Validate.isValidHost
+);
+
+var tableEndpointSetting = ServiceSettings.settingWithFunc(
+ ConnectionStringKeys.TABLE_ENDPOINT_NAME,
+ Validate.isValidHost
+);
+
+var fileEndpointSetting = ServiceSettings.settingWithFunc(
+ ConnectionStringKeys.FILE_ENDPOINT_NAME,
+ Validate.isValidHost
+);
+
+var endpointSuffixSetting = ServiceSettings.settingWithFunc(
+ ConnectionStringKeys.ENDPOINT_SUFFIX_NAME,
+ Validate.isValidHost
+);
+
+var validKeys = [
+ ConnectionStringKeys.USE_DEVELOPMENT_STORAGE_NAME,
+ ConnectionStringKeys.DEVELOPMENT_STORAGE_PROXY_URI_NAME,
+ ConnectionStringKeys.DEFAULT_ENDPOINTS_PROTOCOL_NAME,
+ ConnectionStringKeys.ACCOUNT_NAME_NAME,
+ ConnectionStringKeys.ACCOUNT_KEY_NAME,
+ ConnectionStringKeys.SHARED_ACCESS_SIGNATURE_NAME,
+ ConnectionStringKeys.BLOB_ENDPOINT_NAME,
+ ConnectionStringKeys.QUEUE_ENDPOINT_NAME,
+ ConnectionStringKeys.TABLE_ENDPOINT_NAME,
+ ConnectionStringKeys.FILE_ENDPOINT_NAME,
+ ConnectionStringKeys.ENDPOINT_SUFFIX_NAME
+];
+
+/**
+* Creates new storage service settings instance.
+*
+* @param {string} name The storage service name.
+* @param {string} key The storage service key.
+* @param {string} sasToken The storage service shared access signature token.
+* @param {string} blobEndpoint The storage service blob endpoint.
+* @param {string} queueEndpoint The storage service queue endpoint.
+* @param {string} tableEndpoint The storage service table endpoint.
+* @param {string} fileEndpoint The storage service file endpoint.
+* @param {bool} usePathStyleUri Boolean value indicating wether to use path style uri or not.
+* @param {TokenCredential} [token] The {@link TokenCredential} object.
+*/
+function StorageServiceSettings(name, key, sasToken, blobEndpoint, queueEndpoint, tableEndpoint, fileEndpoint, usePathStyleUri, token) {
+ this._name = name;
+ this._key = key;
+
+ if (sasToken && sasToken[0] === '?') {
+ this._sasToken = sasToken.slice(1);
+ } else {
+ this._sasToken = sasToken;
+ }
+
+ this._blobEndpoint = blobEndpoint;
+ this._queueEndpoint = queueEndpoint;
+ this._tableEndpoint = tableEndpoint;
+ this._fileEndpoint = fileEndpoint;
+
+ if (usePathStyleUri) {
+ this._usePathStyleUri = usePathStyleUri;
+ } else {
+ this._usePathStyleUri = false;
+ }
+
+ this._token = token;
+}
+
+/**
+* Creates a StorageServiceSettings object from the given connection string.
+*
+* @param {string} connectionString The storage settings connection string.
+* @return {StorageServiceSettings}
+*/
+StorageServiceSettings.createFromConnectionString = function (connectionString) {
+ var tokenizedSettings = ServiceSettings.parseAndValidateKeys(connectionString, validKeys);
+
+ try {
+ return StorageServiceSettings.createFromSettings(tokenizedSettings);
+ } catch (e) {
+ if (e instanceof ServiceSettings.NoMatchError) {
+ // Replace no match settings exception by no match connection string one.
+ ServiceSettings.noMatchConnectionString(connectionString);
+ } else {
+ throw e;
+ }
+ }
+};
+
+StorageServiceSettings.createExplicitly = function (storageAccount, storageAccessKey, host, sasToken, endpointSuffix, token) {
+ var settings = {};
+ function addIfNotNullOrEmpty(key, value){
+ if(typeof value === 'string' && !util.stringIsEmpty(value)){
+ settings[key] = value;
+ } else if (typeof value == 'object' && !util.objectIsNull(value)) {
+ settings[key] = value;
+ }
+ }
+
+ // Endpoints
+ if (host) {
+ addIfNotNullOrEmpty('blobendpoint', host);
+ addIfNotNullOrEmpty('tableendpoint', host);
+ addIfNotNullOrEmpty('queueendpoint', host);
+ addIfNotNullOrEmpty('fileendpoint', host);
+ } else {
+ addIfNotNullOrEmpty('defaultendpointsprotocol', ServiceSettings.DEFAULT_PROTOCOL.split(':', 1)[0]);
+ }
+
+ addIfNotNullOrEmpty('accountname', storageAccount);
+ addIfNotNullOrEmpty('accountkey', storageAccessKey);
+ addIfNotNullOrEmpty('sharedaccesssignature', sasToken);
+ addIfNotNullOrEmpty('endpointsuffix', endpointSuffix);
+ addIfNotNullOrEmpty('token', token);
+
+ return StorageServiceSettings.createFromSettings(settings);
+};
+
+StorageServiceSettings.createFromEnvironment = function () {
+ var emulated = process.env[StorageServiceClientConstants.EnvironmentVariables.EMULATED];
+ if (emulated) {
+ return StorageServiceSettings.getDevelopmentStorageAccountSettings();
+ }
+
+ var connectionString = process.env[StorageServiceClientConstants.EnvironmentVariables.AZURE_STORAGE_CONNECTION_STRING];
+ if (connectionString) {
+ return StorageServiceSettings.createFromConnectionString(connectionString);
+ }
+
+ var storageAccount = process.env[StorageServiceClientConstants.EnvironmentVariables.AZURE_STORAGE_ACCOUNT];
+ var storageAccessKey = process.env[StorageServiceClientConstants.EnvironmentVariables.AZURE_STORAGE_ACCESS_KEY];
+ if(storageAccount && storageAccessKey){
+ return StorageServiceSettings.createExplicitly(storageAccount, storageAccessKey, null, null, null);
+ }
+
+ throw new Error(SR.NO_CREDENTIALS_PROVIDED);
+};
+
+/**
+* Creates a StorageServiceSettings object from a set of settings.
+*
+* @param {object} settings The settings object.
+* @return {StorageServiceSettings}
+*/
+StorageServiceSettings.createFromSettings = function (settings) {
+ // Devstore case
+ var matchedSpecs = ServiceSettings.matchedSpecification(
+ settings,
+ ServiceSettings.allRequired(useDevelopmentStorageSetting),
+ ServiceSettings.optional(developmentStorageProxyUriSetting)
+ );
+
+ if (matchedSpecs) {
+ var proxyUri = util.tryGetValueInsensitive(
+ ConnectionStringKeys.DEVELOPMENT_STORAGE_PROXY_URI_NAME,
+ settings
+ );
+
+ return this.getDevelopmentStorageAccountSettings(proxyUri);
+ }
+
+ // Account/Key automatic case
+ matchedSpecs = ServiceSettings.matchedSpecification(
+ settings,
+ ServiceSettings.allRequired(
+ defaultEndpointsProtocolSetting,
+ accountNameSetting,
+ accountKeySetting
+ ),
+ ServiceSettings.optional(
+ blobEndpointSetting,
+ queueEndpointSetting,
+ tableEndpointSetting,
+ fileEndpointSetting,
+ endpointSuffixSetting
+ )
+ );
+
+ if (matchedSpecs) {
+ return this._createStorageServiceSettings(settings);
+ }
+
+ // Account/Key explicit case
+ matchedSpecs = ServiceSettings.matchedSpecification(
+ settings,
+ ServiceSettings.allRequired(
+ accountNameSetting,
+ accountKeySetting
+ ),
+ ServiceSettings.atLeastOne(
+ blobEndpointSetting,
+ queueEndpointSetting,
+ tableEndpointSetting,
+ fileEndpointSetting,
+ endpointSuffixSetting
+ )
+ );
+
+ if (matchedSpecs) {
+ return this._createStorageServiceSettings(settings);
+ }
+
+ // SAS case
+ matchedSpecs = ServiceSettings.matchedSpecification(
+ settings,
+ ServiceSettings.allRequired(
+ sasSetting
+ ),
+ ServiceSettings.atLeastOne(
+ blobEndpointSetting,
+ queueEndpointSetting,
+ tableEndpointSetting,
+ fileEndpointSetting,
+ endpointSuffixSetting
+ )
+ );
+
+ if(matchedSpecs) {
+ return this._createStorageServiceSettings(settings);
+ }
+
+ // anonymous explicit case
+ // Only blob anonymous access is valid.
+ matchedSpecs = ServiceSettings.matchedSpecification(
+ settings,
+ ServiceSettings.allRequired(
+ blobEndpointSetting
+ ),
+ ServiceSettings.optional(
+ fileEndpointSetting,
+ queueEndpointSetting,
+ tableEndpointSetting,
+ endpointSuffixSetting
+ )
+ );
+
+ if(matchedSpecs) {
+ return this._createStorageServiceSettings(settings);
+ }
+
+ // Token case
+ matchedSpecs = ServiceSettings.matchedSpecification(
+ settings,
+ ServiceSettings.allRequired(
+ tokenSetting
+ ),
+ ServiceSettings.atLeastOne(
+ blobEndpointSetting,
+ queueEndpointSetting,
+ tableEndpointSetting,
+ fileEndpointSetting
+ )
+ );
+
+ if(matchedSpecs) {
+ return this._createStorageServiceSettings(settings);
+ }
+
+ ServiceSettings.noMatchSettings(settings);
+};
+
+/**
+* Returns a StorageServiceSettings with development storage credentials using
+* the specified proxy Uri.
+*
+* @param {string} proxyUri The proxy endpoint to use.
+* @return {StorageServiceSettings}
+*/
+StorageServiceSettings.getDevelopmentStorageAccountSettings = function (proxyUri) {
+ if (!proxyUri) {
+ proxyUri = StorageServiceClientConstants.DEV_STORE_URI;
+ }
+
+ var parsedUri = url.parse(proxyUri);
+ var scheme = parsedUri.protocol;
+ var host = parsedUri.host;
+ var prefix = scheme + '//' + host;
+
+ var blobEndpoint = {
+ primaryHost: prefix + ':10000' + '/' + StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT,
+ secondaryHost: prefix + ':10000' + '/' + StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT + '-secondary'
+ };
+
+ var queueEndpoint = {
+ primaryHost: prefix + ':10001' + '/' + StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT,
+ secondaryHost: prefix + ':10001' + '/' + StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT + '-secondary'
+ };
+
+ var tableEndpoint = {
+ primaryHost: prefix + ':10002' + '/' + StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT,
+ secondaryHost: prefix + ':10002' + '/' + StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT + '-secondary'
+ };
+
+ return new StorageServiceSettings(
+ StorageServiceClientConstants.DEVSTORE_STORAGE_ACCOUNT,
+ StorageServiceClientConstants.DEVSTORE_STORAGE_ACCESS_KEY,
+ null,
+ blobEndpoint,
+ queueEndpoint,
+ tableEndpoint,
+ null,
+ true
+ );
+};
+
+/**
+* Creates StorageServiceSettings object given endpoints uri.
+*
+* @ignore
+* @param {array} settings The service settings.
+* @param {string} blobEndpointUri The blob endpoint uri.
+* @param {string} queueEndpointUri The queue endpoint uri.
+* @param {string} tableEndpointUri The table endpoint uri.
+* @param {string} fileEndpointUri The file endpoint uri.
+* @return {StorageServiceSettings}
+*/
+StorageServiceSettings._createStorageServiceSettings = function (settings) {
+ var standardizeHost = function (host, accountName, scheme, dns){
+ var storageHost;
+ if (host) {
+ storageHost = {};
+ storageHost.primaryHost = _.isString(host) ? host : host.primaryHost;
+ storageHost.secondaryHost = _.isString(host) ? undefined : host.secondaryHost;
+ }
+
+ if (scheme && accountName && dns) {
+ storageHost = storageHost ? storageHost : {};
+ storageHost.primaryHost = storageHost.primaryHost ? storageHost.primaryHost : url.format({ protocol: scheme, hostname: accountName + '.' + dns});
+ storageHost.secondaryHost = storageHost.secondaryHost ? storageHost.secondaryHost : url.format({ protocol: scheme, hostname: accountName + '-secondary.' + dns});
+ }
+
+ return storageHost;
+ };
+
+ var scheme = util.tryGetValueInsensitive(
+ ConnectionStringKeys.DEFAULT_ENDPOINTS_PROTOCOL_NAME,
+ settings
+ );
+
+ var accountName = util.tryGetValueInsensitive(
+ ConnectionStringKeys.ACCOUNT_NAME_NAME,
+ settings
+ );
+
+ var accountKey = util.tryGetValueInsensitive(
+ ConnectionStringKeys.ACCOUNT_KEY_NAME,
+ settings
+ );
+
+ var sasToken = util.tryGetValueInsensitive(
+ ConnectionStringKeys.SHARED_ACCESS_SIGNATURE_NAME,
+ settings
+ );
+
+ var endpointSuffix = util.tryGetValueInsensitive(
+ ConnectionStringKeys.ENDPOINT_SUFFIX_NAME,
+ settings
+ );
+
+ var token = util.tryGetValueInsensitive(
+ 'token',
+ settings
+ );
+
+ var blobEndpoint = standardizeHost(
+ util.tryGetValueInsensitive(ConnectionStringKeys.BLOB_ENDPOINT_NAME, settings),
+ accountName,
+ scheme,
+ endpointSuffix ? 'blob.' + endpointSuffix : StorageServiceClientConstants.CLOUD_BLOB_HOST);
+
+ var queueEndpoint = standardizeHost(
+ util.tryGetValueInsensitive(ConnectionStringKeys.QUEUE_ENDPOINT_NAME, settings),
+ accountName,
+ scheme,
+ endpointSuffix ? 'queue.' + endpointSuffix : StorageServiceClientConstants.CLOUD_QUEUE_HOST);
+
+ var tableEndpoint = standardizeHost(
+ util.tryGetValueInsensitive(ConnectionStringKeys.TABLE_ENDPOINT_NAME, settings),
+ accountName,
+ scheme,
+ endpointSuffix ? 'table.' + endpointSuffix : StorageServiceClientConstants.CLOUD_TABLE_HOST);
+
+ var fileEndpoint = standardizeHost(
+ util.tryGetValueInsensitive(ConnectionStringKeys.FILE_ENDPOINT_NAME, settings),
+ accountName,
+ scheme,
+ endpointSuffix ? 'file.' + endpointSuffix : StorageServiceClientConstants.CLOUD_FILE_HOST);
+
+
+ return new StorageServiceSettings(
+ accountName,
+ accountKey,
+ sasToken,
+ blobEndpoint,
+ queueEndpoint,
+ tableEndpoint,
+ fileEndpoint,
+ token
+ );
+};
+
+StorageServiceSettings.validKeys = validKeys;
+
+exports = module.exports = StorageServiceSettings;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/signing/hmacsha256sign.js b/src/node_modules/azure-storage/lib/common/signing/hmacsha256sign.js
new file mode 100644
index 0000000..c7a0edc
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/signing/hmacsha256sign.js
@@ -0,0 +1,43 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var crypto = require('crypto');
+
+/**
+* Creates a new HmacSHA256Sign object.
+*
+* @constructor
+*/
+function HmacSha256Sign(accessKey) {
+ this._accessKey = accessKey;
+ this._decodedAccessKey = Buffer.from(this._accessKey, 'base64');
+}
+
+/**
+* Computes a signature for the specified string using the HMAC-SHA256 algorithm.
+*
+* @param {string} stringToSign The UTF-8-encoded string to sign.
+* @return A String that contains the HMAC-SHA256-encoded signature.
+*/
+HmacSha256Sign.prototype.sign = function (stringToSign) {
+ // Encoding the Signature
+ // Signature=Base64(HMAC-SHA256(UTF8(StringToSign)))
+
+ return crypto.createHmac('sha256', this._decodedAccessKey).update(stringToSign, 'utf-8').digest('base64');
+};
+
+module.exports = HmacSha256Sign;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/signing/sharedaccesssignature.js b/src/node_modules/azure-storage/lib/common/signing/sharedaccesssignature.js
new file mode 100644
index 0000000..1a95891
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/signing/sharedaccesssignature.js
@@ -0,0 +1,56 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+var HmacSha256Sign = require('./hmacsha256sign');
+var Constants = require('./../util/constants');
+var SR = require('./../util/sr');
+
+/**
+* Creates a new SharedAccessSignature object.
+*
+* @constructor
+* @param {string} sasToken The sasToken.
+*/
+function SharedAccessSignature(sasToken) {
+ this.sasToken = sasToken;
+ this.signer = new HmacSha256Sign(sasToken);
+}
+
+/**
+* Signs a request with the signature header.
+*
+* @this {SharedAccessSignature}
+* @param {WebResource} The webresource to be signed.
+* @param {function(error)} callback The callback function.
+*/
+SharedAccessSignature.prototype.signRequest = function (webResource, callback) {
+ if (webResource.uri.indexOf('?') === -1) {
+ webResource.uri += '?';
+ } else {
+ webResource.uri += '&';
+ }
+
+ webResource.uri += this.sasToken;
+
+ // Add the api-version
+ if (this.sasToken.indexOf('api-version') == -1) {
+ webResource.uri += '&' + Constants.QueryStringConstants.API_VERSION + '=' + Constants.HeaderConstants.TARGET_STORAGE_VERSION;
+ } else {
+ throw new SyntaxError(SR.INVALID_SAS_TOKEN);
+ }
+ callback(null);
+};
+
+module.exports = SharedAccessSignature;
diff --git a/src/node_modules/azure-storage/lib/common/signing/sharedkey.js b/src/node_modules/azure-storage/lib/common/signing/sharedkey.js
new file mode 100644
index 0000000..5e18808
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/signing/sharedkey.js
@@ -0,0 +1,500 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+var qs = require('querystring');
+
+var azureutil = require('../util/util');
+var HmacSha256Sign = require('./hmacsha256sign');
+var SR = require('../util/sr');
+var errors = require('../errors/errors');
+var ArgumentError = errors.ArgumentError;
+
+var Constants = require('../util/constants');
+var HeaderConstants = Constants.HeaderConstants;
+var QueryStringConstants = Constants.QueryStringConstants;
+var HeaderConstants = Constants.HeaderConstants;
+var CompatibleVersionConstants = Constants.CompatibleVersionConstants;
+
+/**
+* Creates a new SharedKey object.
+*
+* @constructor
+* @param {string} storageAccount The storage account.
+* @param {string} storageAccessKey The storage account's access key.
+* @param {bool} usePathStyleUri Boolean value indicating if the path, or the hostname, should include the storage account.
+*/
+function SharedKey(storageAccount, storageAccessKey, usePathStyleUri) {
+ this.storageAccount = storageAccount;
+ this.storageAccessKey = storageAccessKey;
+ this.usePathStyleUri = usePathStyleUri;
+ this.signer = new HmacSha256Sign(storageAccessKey);
+}
+
+/**
+* Generates the shared access signature for a account.
+* For more detailed information, refer to https://msdn.microsoft.com/en-us/library/azure/mt584140.aspx
+*
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {SharedAccessServices} sharedAccessPolicy.AccessPolicy.Services The services (blob, file, queue, table) for a shared access signature associated with this shared access policy.
+* Refer to `Constants.AccountSasConstants.Services`.
+* @param {SharedAccessResourceTypes} sharedAccessPolicy.AccessPolicy.ResourceTypes The resource type for a shared access signature associated with this shared access policy.
+* Refer to `Constants.AccountSasConstants.Resources`.
+* @param {SharedAccessPermissions} sharedAccessPolicy.AccessPolicy.Permissions The permissions for a shared access signature.
+* Refer to `Constants.AccountSasConstants.Permissions`.
+* @param {date} sharedAccessPolicy.AccessPolicy.Start The time at which the Shared Access Signature becomes valid.
+* @param {date} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired.
+* @param {string} sharedAccessPolicy.AccessPolicy.IPAddressOrRange An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} sharedAccessPolicy.AccessPolicy.Protocols The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* Refer to `Constants.AccountSasConstants.Protocols`.
+* @return {string} The shared access signature.
+*/
+SharedKey.prototype.generateAccountSignedQueryString = function (sharedAccessPolicy) {
+ var addIfNotNull = function (queryString, name, value) {
+ if (!azureutil.objectIsNull(name) && !azureutil.objectIsNull(value)) {
+ queryString[name] = value;
+ }
+ };
+
+ var formatAccessPolicyDates = function (accessPolicy) {
+ if (!azureutil.objectIsNull(accessPolicy.Start)) {
+ if (!_.isDate(accessPolicy.Start)) {
+ accessPolicy.Start = new Date(accessPolicy.Start);
+ }
+
+ accessPolicy.Start = azureutil.truncatedISO8061Date(accessPolicy.Start);
+ }
+
+ if (!azureutil.objectIsNull(accessPolicy.Expiry)) {
+ if (!_.isDate(accessPolicy.Expiry)) {
+ accessPolicy.Expiry = new Date(accessPolicy.Expiry);
+ }
+
+ accessPolicy.Expiry = azureutil.truncatedISO8061Date(accessPolicy.Expiry);
+ }
+ };
+
+ var queryString = {};
+
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_VERSION, HeaderConstants.TARGET_STORAGE_VERSION);
+
+ // add shared access policy params
+ if (sharedAccessPolicy.AccessPolicy) {
+ formatAccessPolicyDates(sharedAccessPolicy.AccessPolicy);
+
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_SERVICES, sharedAccessPolicy.AccessPolicy.Services);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_RESOURCE_TYPES, sharedAccessPolicy.AccessPolicy.ResourceTypes);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_PERMISSIONS, sharedAccessPolicy.AccessPolicy.Permissions);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_START, sharedAccessPolicy.AccessPolicy.Start);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_EXPIRY, sharedAccessPolicy.AccessPolicy.Expiry);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_IP, sharedAccessPolicy.AccessPolicy.IPAddressOrRange);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_PROTOCOL, sharedAccessPolicy.AccessPolicy.Protocols);
+ }
+
+ // add signature
+ addIfNotNull(queryString, QueryStringConstants.SIGNATURE, this._generateAccountSharedAccessSignature(sharedAccessPolicy));
+
+ return qs.stringify(queryString);
+};
+
+
+/**
+* Generates the signature part of the shared access signature for a account.
+* For more detailed information, refer to https://msdn.microsoft.com/en-us/library/azure/mt584140.aspx
+*
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {SharedAccessServices} sharedAccessPolicy.AccessPolicy.Services The services (blob, file, queue, table) for a shared access signature associated with this shared access policy.
+* Refer to `Constants.AccountSasConstants.Services`.
+* @param {SharedAccessResourceTypes} sharedAccessPolicy.AccessPolicy.ResourceTypes The resource type for a shared access signature associated with this shared access policy.
+* Refer to `Constants.AccountSasConstants.ResourceTypes`.
+* @param {SharedAccessPermissions} sharedAccessPolicy.AccessPolicy.Permissions The permissions for a shared access signature.
+* Refer to `Constants.AccountSasConstants.Permissions`.
+* @param {date} sharedAccessPolicy.AccessPolicy.Start The time at which the Shared Access Signature becomes valid.
+* @param {date} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired.
+* @param {string} sharedAccessPolicy.AccessPolicy.IPAddressOrRange An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} sharedAccessPolicy.AccessPolicy.Protocols The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* Refer to `Constants.AccountSasConstants.Protocols`.
+* @return {string} The signature part of the shared access signature.
+*/
+SharedKey.prototype._generateAccountSharedAccessSignature = function(sharedAccessPolicy){
+ var getvalueToAppend = function (value, noNewLine) {
+ var returnValue = '';
+ if (!azureutil.objectIsNull(value)) {
+ returnValue = value;
+ }
+
+ if (noNewLine !== true) {
+ returnValue += '\n';
+ }
+
+ return returnValue;
+ };
+
+ var stringToSign = getvalueToAppend(this.storageAccount) +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Permissions : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Services : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.ResourceTypes : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Start : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Expiry : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.IPAddressOrRange : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Protocols : '') +
+ getvalueToAppend(HeaderConstants.TARGET_STORAGE_VERSION);
+
+ return this.signer.sign(stringToSign);
+};
+
+/**
+* Signs a request with the Authentication header.
+*
+* @param {WebResource} webResource The webresource to be signed.
+* @param {function(error)} callback The callback function.
+*/
+SharedKey.prototype.signRequest = function (webResource, callback) {
+ var getvalueToAppend = function (value, headerName) {
+ // Do not sign content-length 0 in 2014-08-16 and later
+ if (headerName === HeaderConstants.CONTENT_LENGTH && (azureutil.objectIsNull(value[headerName]) || value[headerName].toString() === '0')) {
+ return '\n';
+ } else if (azureutil.objectIsNull(value) || azureutil.objectIsNull(value[headerName])) {
+ return '\n';
+ } else {
+ return value[headerName] + '\n';
+ }
+ };
+
+ var stringToSign =
+ webResource.method + '\n' +
+ getvalueToAppend(webResource.headers, HeaderConstants.CONTENT_ENCODING) +
+ getvalueToAppend(webResource.headers, HeaderConstants.CONTENT_LANGUAGE) +
+ getvalueToAppend(webResource.headers, HeaderConstants.CONTENT_LENGTH) +
+ getvalueToAppend(webResource.headers, HeaderConstants.CONTENT_MD5) +
+ getvalueToAppend(webResource.headers, HeaderConstants.CONTENT_TYPE) +
+ getvalueToAppend(webResource.headers, HeaderConstants.DATE) +
+ getvalueToAppend(webResource.headers, HeaderConstants.IF_MODIFIED_SINCE) +
+ getvalueToAppend(webResource.headers, HeaderConstants.IF_MATCH) +
+ getvalueToAppend(webResource.headers, HeaderConstants.IF_NONE_MATCH) +
+ getvalueToAppend(webResource.headers, HeaderConstants.IF_UNMODIFIED_SINCE) +
+ getvalueToAppend(webResource.headers, HeaderConstants.RANGE) +
+ this._getCanonicalizedHeaders(webResource) +
+ this._getCanonicalizedResource(webResource);
+
+ var signature = this.signer.sign(stringToSign);
+
+ webResource.withHeader(HeaderConstants.AUTHORIZATION, 'SharedKey ' + this.storageAccount + ':' + signature);
+ callback(null);
+};
+
+/*
+* Retrieves the webresource's canonicalized resource string.
+* @param {WebResource} webResource The webresource to get the canonicalized resource string from.
+* @return {string} The canonicalized resource string.
+*/
+SharedKey.prototype._getCanonicalizedResource = function (webResource) {
+ var path = '/';
+ if (webResource.path) {
+ path = webResource.path;
+ }
+
+ var canonicalizedResource = '/' + this.storageAccount + path;
+
+ // Get the raw query string values for signing
+ var queryStringValues = webResource.queryString;
+
+ // Build the canonicalized resource by sorting the values by name.
+ if (queryStringValues) {
+ var paramNames = [];
+ Object.keys(queryStringValues).forEach(function (n) {
+ paramNames.push(n);
+ });
+
+ paramNames = paramNames.sort();
+ Object.keys(paramNames).forEach(function (name) {
+ canonicalizedResource += '\n' + paramNames[name] + ':' + queryStringValues[paramNames[name]];
+ });
+ }
+
+ return canonicalizedResource;
+};
+
+/*
+* Constructs the Canonicalized Headers string.
+*
+* 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. Unfold the string by replacing any breaking white space with a
+* single space. 5. Trim any white space 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.
+*
+* @param {object} The webresource object.
+* @return {string} The canonicalized headers.
+*/
+SharedKey.prototype._getCanonicalizedHeaders = function (webResource) {
+ // Build canonicalized headers
+ var canonicalizedHeaders = '';
+ if (webResource.headers) {
+ var canonicalizedHeadersArray = [];
+ for (var header in webResource.headers) {
+ if (header.indexOf(HeaderConstants.PREFIX_FOR_STORAGE) === 0) {
+ var headerItem = { canonicalized: header.toLowerCase(), original: header };
+ canonicalizedHeadersArray.push(headerItem);
+ }
+ }
+
+ canonicalizedHeadersArray.sort(function(a, b) { return a.canonicalized.localeCompare(b.canonicalized); });
+
+ _.each(canonicalizedHeadersArray, function (currentHeaderItem) {
+ var value = webResource.headers[currentHeaderItem.original];
+ if (!azureutil.IsNullOrEmptyOrUndefinedOrWhiteSpace(value)) {
+ canonicalizedHeaders += currentHeaderItem.canonicalized + ':' + value + '\n';
+ } else {
+ canonicalizedHeaders += currentHeaderItem.canonicalized + ':\n';
+ }
+ });
+ }
+
+ return canonicalizedHeaders;
+};
+
+/**
+* Generates the query string for a shared access signature signing.
+*
+* @this {SharedAccessSignature}
+* @param {string} serviceType The service type.
+* @param {string} path The path to the resource.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {string} [sharedAccessPolicy.Id] The signed identifier.
+* @param {SharedAccessPermissions} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+* @param {date} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid.
+* @param {date} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired.
+* @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} [sharedAccessPolicy.AccessPolicy.Protocols] The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* @param {string} sasVersion A string indicating the desired SAS Version to use, in storage service version format. Value must be 2012-02-12 or later.
+* @parma {ResourceTypes} [args.resourceType] The resource type, if the resource is a blob or container. Null if the resource is a queue or table.
+* @parma {ResourceTypes} [args.tableName] The table name, if the resource is a table. Null if the resource is a blob orqueue.
+* @parma {ResourceTypes} [args.queryString] The query string, if additional parameters are desired.
+* @param {object} [args.headers] The optional header values to set for a blob returned wth this SAS.
+* @param {string} [args.headers.CacheControl] The value of the Cache-Control response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentType] The value of the Content-Type response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentEncoding] The value of the Content-Encoding response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentLanguage] The value of the Content-Language response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentDisposition] The value of the Content-Disposition response header to be returned when this SAS is used.
+* @return {object} The shared access signature query string.
+*/
+SharedKey.prototype.generateSignedQueryString = function (serviceType, path, sharedAccessPolicy, sasVersion, args) {
+ var addIfNotNull = function (queryString, name, value) {
+ if (!azureutil.objectIsNull(name) && !azureutil.objectIsNull(value)) {
+ queryString[name] = value;
+ }
+ };
+
+ var validateVersion = function (sasVersion) {
+ // validate and add version
+ if (azureutil.objectIsNull(sasVersion)) {
+ return HeaderConstants.TARGET_STORAGE_VERSION;
+ } else {
+ var values = _.values(CompatibleVersionConstants);
+ if (values.some(function(version) {
+ return version.toLowerCase() === sasVersion.toLowerCase();
+ })) {
+ return sasVersion;
+ } else {
+ throw new ArgumentError('sasVersion', azureutil.stringFormat(SR.INVALID_SAS_VERSION, sasVersion, values));
+ }
+ }
+ };
+
+ var formatAccessPolicyDates = function (accessPolicy) {
+ if (!azureutil.objectIsNull(accessPolicy.Start)) {
+ if (!_.isDate(accessPolicy.Start)) {
+ accessPolicy.Start = new Date(accessPolicy.Start);
+ }
+
+ accessPolicy.Start = azureutil.truncatedISO8061Date(accessPolicy.Start);
+ }
+
+ if (!azureutil.objectIsNull(accessPolicy.Expiry)) {
+ if (!_.isDate(accessPolicy.Expiry)) {
+ accessPolicy.Expiry = new Date(accessPolicy.Expiry);
+ }
+
+ accessPolicy.Expiry = azureutil.truncatedISO8061Date(accessPolicy.Expiry);
+ }
+ };
+
+ // set up optional args
+ var queryString;
+ var resourceType;
+ var headers;
+ var tableName;
+
+ if(args) {
+ queryString = args.queryString;
+ resourceType = args.resourceType;
+ tableName = args.tableName;
+ headers = args.headers;
+ }
+
+ if(!queryString) {
+ queryString = {};
+ }
+
+ // add shared access policy params
+ if (sharedAccessPolicy.AccessPolicy) {
+ formatAccessPolicyDates(sharedAccessPolicy.AccessPolicy);
+
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_START, sharedAccessPolicy.AccessPolicy.Start);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_EXPIRY, sharedAccessPolicy.AccessPolicy.Expiry);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_PERMISSIONS, sharedAccessPolicy.AccessPolicy.Permissions);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_IP, sharedAccessPolicy.AccessPolicy.IPAddressOrRange);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_PROTOCOL, sharedAccessPolicy.AccessPolicy.Protocols);
+
+ // tables only
+ addIfNotNull(queryString, QueryStringConstants.STARTPK, sharedAccessPolicy.AccessPolicy.StartPk);
+ addIfNotNull(queryString, QueryStringConstants.ENDPK, sharedAccessPolicy.AccessPolicy.EndPk);
+ addIfNotNull(queryString, QueryStringConstants.STARTRK, sharedAccessPolicy.AccessPolicy.StartRk);
+ addIfNotNull(queryString, QueryStringConstants.ENDRK, sharedAccessPolicy.AccessPolicy.EndRk);
+ }
+
+ // validate and add version
+ var validatedSASVersionString = validateVersion(sasVersion);
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_VERSION, validatedSASVersionString);
+
+ // add signed identifier
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_IDENTIFIER, sharedAccessPolicy.Id);
+
+ // blobs only
+ addIfNotNull(queryString, QueryStringConstants.SIGNED_RESOURCE, resourceType);
+ if (headers) {
+ addIfNotNull(queryString, QueryStringConstants.CACHE_CONTROL, headers.cacheControl);
+ addIfNotNull(queryString, QueryStringConstants.CONTENT_TYPE, headers.contentType);
+ addIfNotNull(queryString, QueryStringConstants.CONTENT_ENCODING, headers.contentEncoding);
+ addIfNotNull(queryString, QueryStringConstants.CONTENT_LANGUAGE, headers.contentLanguage);
+ addIfNotNull(queryString, QueryStringConstants.CONTENT_DISPOSITION, headers.contentDisposition);
+ }
+
+ // tables only
+ addIfNotNull(queryString, QueryStringConstants.TABLENAME, tableName);
+
+ // add signature
+ addIfNotNull(queryString, QueryStringConstants.SIGNATURE, this._generateSignature(serviceType, path, sharedAccessPolicy, validatedSASVersionString, {resourceType: resourceType, headers: headers, tableName: tableName}));
+
+ return qs.stringify(queryString);
+};
+
+/**
+* Generates the shared access signature for a resource.
+*
+* @this {SharedAccessSignature}
+* @param {string} serviceType The service type.
+* @param {string} path The path to the resource.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {string} [sharedAccessPolicy.Id] The signed identifier.
+* @param {SharedAccessPermissions} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+* @param {date} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid.
+* @param {date} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired.
+* @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} [sharedAccessPolicy.AccessPolicy.Protocols] The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* @param {string} sasVersion A string indicating the desired SAS Version to use, in storage service version format. Value must be 2012-02-12 or later.
+* @parma {ResourceTypes} [args.resourceType] The resource type, if the resource is a blob or container. Null if the resource is a queue or table.
+* @parma {ResourceTypes} [args.tableName] The table name, if the resource is a table. Null if the resource is a blob or queue.
+* @param {object} [args.headers] The optional header values to set for a blob returned wth this SAS.
+* @param {string} [args.headers.CacheControl] The value of the Cache-Control response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentType] The value of the Content-Type response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentEncoding] The value of the Content-Encoding response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentLanguage] The value of the Content-Language response header to be returned when this SAS is used.
+* @param {string} [args.headers.ContentDisposition] The value of the Content-Disposition response header to be returned when this SAS is used.
+* @return {string} The shared access signature.
+*/
+SharedKey.prototype._generateSignature = function (serviceType, path, sharedAccessPolicy, sasVersion, args) {
+ var getvalueToAppend = function (value, noNewLine) {
+ var returnValue = '';
+ if (!azureutil.objectIsNull(value)) {
+ returnValue = value;
+ }
+
+ if (noNewLine !== true) {
+ returnValue += '\n';
+ }
+
+ return returnValue;
+ };
+
+ // set up optional args
+ var resourceType;
+ var tableName;
+ var headers;
+ if(args) {
+ resourceType = args.resourceType;
+ tableName = args.tableName;
+ headers = args.headers;
+ }
+
+ // Add leading slash to path
+ if (path.substr(0, 1) !== '/') {
+ path = '/' + path;
+ }
+
+ var canonicalizedResource;
+ if (sasVersion === CompatibleVersionConstants.FEBRUARY_2012 || sasVersion === CompatibleVersionConstants.AUGUST_2013) {
+ // Do not prepend service name for older versions
+ canonicalizedResource = '/' + this.storageAccount + path;
+ } else {
+ canonicalizedResource = '/' + serviceType + '/' + this.storageAccount + path;
+ }
+
+ var stringToSign = getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Permissions : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Start : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Expiry : '') +
+ getvalueToAppend(canonicalizedResource) +
+ getvalueToAppend(sharedAccessPolicy.Id) +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.IPAddressOrRange : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Protocols : '') +
+ sasVersion;
+
+ if(sasVersion == CompatibleVersionConstants.FEBRUARY_2012) {
+ if(headers) {
+ throw new ArgumentError('args.headers', SR.INVALID_HEADERS);
+ }
+ } else if (resourceType) {
+ stringToSign += '\n' +
+ getvalueToAppend(headers ? headers.cacheControl : '') +
+ getvalueToAppend(headers ? headers.contentDisposition : '') +
+ getvalueToAppend(headers ? headers.contentEncoding : '') +
+ getvalueToAppend(headers ? headers.contentLanguage : '') +
+ getvalueToAppend(headers ? headers.contentType : '', true);
+ }
+
+ if(tableName) {
+ stringToSign += '\n' +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.StartPk : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.StartRk : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.EndPk : '') +
+ getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.EndRk : '', true);
+ }
+
+ return this.signer.sign(stringToSign);
+};
+
+module.exports = SharedKey;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/signing/tokensigner.js b/src/node_modules/azure-storage/lib/common/signing/tokensigner.js
new file mode 100644
index 0000000..ce71e69
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/signing/tokensigner.js
@@ -0,0 +1,41 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var Constants = require('../util/constants');
+var HeaderConstants = Constants.HeaderConstants;
+
+/**
+* Creates a new TokenSigner object.
+*
+* @constructor
+* @param {TokenCredential} tokenCredential The token credential, such as containing an OAuth access token.
+*/
+function TokenSigner (tokenCredential) {
+ this.tokenCredential = tokenCredential;
+}
+
+/**
+* Signs a request with the Authentication header.
+*
+* @param {WebResource} webResource The webresource to be signed.
+* @param {function(error)} callback The callback function.
+*/
+TokenSigner.prototype.signRequest = function (webResource, callback) {
+ webResource.withHeader(HeaderConstants.AUTHORIZATION, 'Bearer ' + this.tokenCredential.get());
+ callback(null);
+};
+
+module.exports = TokenSigner;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/streams/batchoperation.js b/src/node_modules/azure-storage/lib/common/streams/batchoperation.js
new file mode 100644
index 0000000..1366b56
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/batchoperation.js
@@ -0,0 +1,425 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var util = require('util');
+var http = require('http');
+var https = require('https');
+var EventEmitter = require('events').EventEmitter;
+var os = require('os');
+
+var azureutil = require('../util/util');
+var Logger = require('../diagnostics/logger');
+var Constants = require('../util/constants');
+var errors = require('../errors/errors');
+var ArgumentError = errors.ArgumentError;
+
+var DEFAULT_OPERATION_MEMORY_USAGE = Constants.BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+var DEFAULT_CRITICAL_MEMORY_LIMITATION_32_IN_BYTES = Constants.BlobConstants.DEFAULT_CRITICAL_MEMORY_LIMITATION_32_IN_BYTES;
+var DEFAULT_CRITICAL_MEMORY_LIMITATION_BROWSER_IN_BYTES = Constants.BlobConstants.DEFAULT_CRITICAL_MEMORY_LIMITATION_BROWSER_IN_BYTES;
+var DEFAULT_MINIMUM_MEMORY_USAGE_BROWSER_IN_BYTES = Constants.BlobConstants.DEFAULT_MINIMUM_MEMORY_USAGE_BROWSER_IN_BYTES;
+var DEFAULT_GLOBAL_CONCURRENCY = 5; //Default http connection limitation for nodejs
+
+var SystemTotalMemory = os.totalmem();
+var CriticalFreeMemory = 0.1 * SystemTotalMemory;
+var nodeVersion = azureutil.getNodeVersion();
+
+/**
+* Concurrently execute batch operations and call operation callback randomly or in sequence.
+* Random mode is for uploading.
+* 1. Fire user callback when the operation is done.
+* Sequence mode is for downloading.
+* 1. Fire user callback when the operation is done and all previous operations and callback has finished.
+* 2. BatchOperation guarantees the user callback is fired one by one.
+* 3. The next user callback can't be fired until the current one is completed.
+*/
+function BatchOperation(name, options) {
+ if (!options) {
+ options = {};
+ }
+
+ this.name = name;
+ this.logger = options.logger || new Logger(Logger.LogLevels.INFO);
+ this.operationMemoryUsage = options.operationMemoryUsage || DEFAULT_OPERATION_MEMORY_USAGE;
+ this.callbackInOrder = options.callbackInOrder === true;
+ this.callInOrder = options.callInOrder === true;
+ this._currentOperationId = this.callbackInOrder ? 1 : -1;
+ this.concurrency = DEFAULT_GLOBAL_CONCURRENCY;
+ this.enableReuseSocket = (nodeVersion.major > 0 || nodeVersion.minor >= 10) && options.enableReuseSocket;
+
+ this._emitter = new EventEmitter();
+ this._enableComplete = false;
+ this._ended = false;
+ this._error = null;
+ this._paused = false;
+
+ //Total operations count(queued and active and connected)
+ this._totalOperation = 0;
+
+ //Action operations count(The operations which are connecting to remote or executing callback or queued for executing)
+ this._activeOperation = 0;
+
+ //Queued operations count(The operations which are connecting to remote or queued for executing)
+ this._queuedOperation = 0;
+
+ //finished operation should be removed from this array
+ this._operations = [];
+}
+
+/**
+* Operation state
+*/
+var OperationState = {
+ INITED : 'inited',
+ QUEUED : 'queued',
+ RUNNING : 'running',
+ COMPLETE : 'complete',
+ CALLBACK : 'callback',
+ ERROR : 'error'
+};
+
+BatchOperation.OperationState = OperationState;
+
+/**
+* Set batch operation concurrency
+*/
+BatchOperation.prototype.setConcurrency = function(concurrency) {
+ if (concurrency) {
+ this.concurrency = concurrency;
+ http.Agent.maxSockets = this.concurrency;
+ https.Agent.maxSockets = this.concurrency;
+ }
+};
+
+/**
+* Is the workload heavy and It can be used to determine whether we could queue operations
+*/
+BatchOperation.prototype.IsWorkloadHeavy = function() {
+ //Only support one batch operation for now.
+ //In order to work with the multiple batch operation, we can use global operation track objects
+ //BatchOperation acquire a bunch of operation ids from global and allocated ids to RestOperation
+ //RestOperation start to run in order of id
+ var sharedRequest = 1;
+ if(this.enableReuseSocket && !this.callInOrder) {
+ sharedRequest = 2;
+ }
+ return this._activeOperation >= sharedRequest * this.concurrency || this._isLowMemory();
+};
+
+/**
+* Get the approximate memory usage for batch operation.
+*/
+BatchOperation.prototype._getApproximateMemoryUsage = function() {
+ var currentUsage = azureutil.isBrowser() ? DEFAULT_MINIMUM_MEMORY_USAGE_BROWSER_IN_BYTES : process.memoryUsage().rss; // Currently, we cannot get memory usage in browsers
+ var futureUsage = this._queuedOperation * this.operationMemoryUsage;
+ return currentUsage + futureUsage;
+};
+
+/**
+* Return whether in a low memory situation.
+*/
+BatchOperation.prototype._isLowMemory = function() {
+ var approximateMemoryUsage = this._getApproximateMemoryUsage();
+ return os.freemem() < CriticalFreeMemory ||
+ (this._activeOperation >= this.concurrency && approximateMemoryUsage > 0.5 * SystemTotalMemory) ||
+ (azureutil.is32() && approximateMemoryUsage > DEFAULT_CRITICAL_MEMORY_LIMITATION_32_IN_BYTES) ||
+ (azureutil.isBrowser() && approximateMemoryUsage > DEFAULT_CRITICAL_MEMORY_LIMITATION_BROWSER_IN_BYTES);
+};
+
+/**
+* Add a operation into batch operation
+*/
+BatchOperation.prototype.addOperation = function(operation) {
+ this._operations.push(operation);
+ operation.status = OperationState.QUEUED;
+ operation.operationId = ++this._totalOperation;
+ this._queuedOperation++;
+ this.logger.debug(util.format('Add operation %d into batch operation %s. Active: %s; Queued: %s', operation.operationId, this.name, this._activeOperation, this._queuedOperation));
+ //Immediately start the idle operation if workload isn't heavy
+ this._runOperation(operation);
+ return this.IsWorkloadHeavy();
+};
+
+/**
+* Enable batch operation complete when there is no operation to run.
+*/
+BatchOperation.prototype.enableComplete = function() {
+ this._enableComplete = true;
+ this.logger.debug(util.format('Enable batch operation %s complete', this.name));
+ this._tryEmitEndEvent();
+};
+
+/**
+* Stop firing user call back
+*/
+BatchOperation.prototype.pause = function () {
+ this._paused = true;
+};
+
+/**
+* Start firing user call back
+*/
+BatchOperation.prototype.resume = function () {
+ if (this._paused) {
+ this._paused = false;
+ this._fireOperationUserCallback();
+ }
+};
+
+/**
+* Add event listener
+*/
+BatchOperation.prototype.on = function(event, listener) {
+ // only emit end if the batch has completed all operations
+ if(this._ended && event === 'end') {
+ listener();
+ } else {
+ this._emitter.on(event, listener);
+ }
+};
+
+/**
+* Run operation
+*/
+BatchOperation.prototype._runOperation = function (operation) {
+ this.logger.debug(util.format('Operation %d start to run', operation.operationId));
+ var cb = this.getBatchOperationCallback(operation);
+
+ if(this._error) {
+ cb(this._error);//Directly call the callback with previous error.
+ } else {
+ operation.run(cb);
+ }
+
+ this._activeOperation++;
+};
+
+/**
+* Return an general operation call back.
+* This callback is used to update the internal status and fire user's callback when operation is complete.
+*/
+BatchOperation.prototype.getBatchOperationCallback = function (operation) {
+ var self = this;
+ return function (error) {
+ self._queuedOperation--;
+ if (error) {
+ operation.status = OperationState.ERROR;
+ self.logger.debug(util.format('Operation %d failed. Error %s', operation.operationId, error));
+ self._error = error;
+ } else {
+ operation.status = OperationState.CALLBACK;
+ self.logger.debug(util.format('Operation %d succeed', operation.operationId));
+ }
+
+ operation._callbackArguments = arguments;
+ if (self._paused) {
+ operation.status = OperationState.CALLBACK;
+ self.logger.debug(util.format('Batch operation paused and Operation %d wait for firing callback', operation.operationId));
+ } else if (self.callbackInOrder) {
+ operation.status = OperationState.CALLBACK;
+ if (self._currentOperationId === operation.operationId) {
+ self._fireOperationUserCallback(operation);
+ } else if (self._currentOperationId > operation.operationId) {
+ throw new Error('Debug error: current callback operation id cannot be larger than operation id');
+ } else {
+ self.logger.debug(util.format('Operation %d is waiting for firing callback %s', operation.operationId, self._currentOperationId));
+ }
+ } else {
+ self._fireOperationUserCallback(operation);
+ }
+
+ self._tryEmitDrainEvent();
+ operation = null;
+ self = null;
+ };
+};
+
+/**
+* Fire user's call back
+*/
+BatchOperation.prototype._fireOperationUserCallback = function (operation) {
+ var index = this._getCallbackOperationIndex();
+ if (!operation && index != -1) {
+ operation = this._operations[index];
+ }
+
+ if (operation && !this._paused) {
+ // fire the callback, if exists
+ if (operation._userCallback) {
+ this.logger.debug(util.format('Fire user call back for operation %d', operation.operationId));
+ // make sure UserCallback is a sync operation in sequence mode.
+ // both async and sync operations are available for random mode.
+ operation._fireUserCallback();
+ }
+
+ // remove the operation from the array and decrement the counter
+ this._operations.splice(index, 1);
+ this._activeOperation--;
+ operation.status = OperationState.COMPLETE;
+ index = operation = null;
+
+ if (this.callbackInOrder) {
+ this._currentOperationId++;
+ }
+
+ this._fireOperationUserCallback();
+ } else if (this._paused) {
+ this._tryEmitDrainEvent();
+ } else {
+ // check if batch has ended and if so emit end event
+ this._tryEmitEndEvent();
+ }
+};
+
+/**
+* Try to emit the BatchOperation end event
+* End event means all the operation and callback already finished.
+*/
+BatchOperation.prototype._tryEmitEndEvent = function () {
+ if(this._enableComplete && this._activeOperation === 0 && this._operations.length === 0) {
+ this._ended = true;
+ this.logger.debug(util.format('Batch operation %s emits the end event', this.name));
+ this._emitter.emit('end', this._error, null);
+ return true;
+ }
+
+ // Workaround to recover from the 'hang' edge case. _tryEmitEndEvent function is not supposed to be called if the bacth is not really completed.
+ this._tryEmitDrainEvent();
+ return false;
+};
+
+/**
+* Try to emit the drain event
+*/
+BatchOperation.prototype._tryEmitDrainEvent = function () {
+ if (!this._emitter) return false;
+ if(!this.IsWorkloadHeavy() || this._activeOperation < this.concurrency) {
+ this._emitter.emit('drain');
+ return true;
+ }
+ return false;
+};
+
+/**
+* Get the current active operation index.
+* Only the active operation could call user's callback in sequence model.
+* The other finished but not active operations should wait for wake up.
+*/
+BatchOperation.prototype._getCallbackOperationIndex = function () {
+ var operation = null;
+ for (var i = 0; i < this._operations.length; i++) {
+ operation = this._operations[i];
+ if (this.callbackInOrder) {
+ //Sequence mode
+ if (operation.operationId == this._currentOperationId) {
+ if (operation.status === OperationState.CALLBACK) {
+ return i;
+ } else {
+ return -1;
+ }
+ }
+ } else {
+ //Random mode
+ if (operation.status === OperationState.CALLBACK) {
+ return i;
+ }
+ }
+ }
+ return -1;
+};
+
+/**
+* Do nothing and directly call the callback.
+* In random mode, the user callback will be called immediately
+* In sequence mode, the user callback will be called after the previous callback has been called
+*/
+BatchOperation.noOperation = function (cb) {
+ cb();
+};
+
+/**
+* Rest operation in sdk
+*/
+function RestOperation(serviceClient, operation) {
+ this.status = OperationState.Inited;
+ this.operationId = -1;
+ this._callbackArguments = null;
+
+ // setup callback and args
+ this._userCallback = arguments[arguments.length - 1];
+ var sliceEnd = arguments.length;
+ if(azureutil.objectIsFunction(this._userCallback)) {
+ sliceEnd--;
+ } else {
+ this._userCallback = null;
+ }
+ var operationArguments = Array.prototype.slice.call(arguments).slice(2, sliceEnd);
+
+ this.run = function(cb) {
+ var func = serviceClient[operation];
+ if(!func) {
+ throw new ArgumentError('operation', util.format('Unknown operation %s in serviceclient', operation));
+ } else {
+ if(!cb) cb = this._userCallback;
+ operationArguments.push(cb);
+ this.status = OperationState.RUNNING;
+ func.apply(serviceClient, operationArguments);
+ operationArguments = operation = null;
+ }
+ };
+
+ this._fireUserCallback = function () {
+ if(this._userCallback) {
+ this._userCallback.apply(null, this._callbackArguments);
+ }
+ };
+}
+
+BatchOperation.RestOperation = RestOperation;
+
+/**
+* Common operation wrapper
+*/
+function CommonOperation(operationFunc, callback) {
+ this.status = OperationState.Inited;
+ this.operationId = -1;
+ this._callbackArguments = null;
+ var sliceStart = 2;
+ if (azureutil.objectIsFunction(callback)) {
+ this._userCallback = callback;
+ } else {
+ this._userCallback = null;
+ sliceStart = 1;
+ }
+ var operationArguments = Array.prototype.slice.call(arguments).slice(sliceStart);
+ this.run = function (cb) {
+ if (!cb) cb = this._userCallback;
+ operationArguments.push(cb);
+ this.status = OperationState.RUNNING;
+ operationFunc.apply(null, operationArguments);
+ operationArguments = operationFunc = null;
+ };
+
+ this._fireUserCallback = function () {
+ if (this._userCallback) {
+ this._userCallback.apply(null, this._callbackArguments);
+ }
+ this._userCallback = this._callbackArguments = null;
+ };
+}
+
+BatchOperation.CommonOperation = CommonOperation;
+
+module.exports = BatchOperation;
diff --git a/src/node_modules/azure-storage/lib/common/streams/browserfilereadstream.js b/src/node_modules/azure-storage/lib/common/streams/browserfilereadstream.js
new file mode 100644
index 0000000..0178820
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/browserfilereadstream.js
@@ -0,0 +1,61 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var buffer = require('buffer').Buffer;
+var stream = require('stream');
+var util = require('util');
+
+var Constants = require('../util/constants');
+var bufferSize = Constants.BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+
+function BrowserFileReadStream(file, options) {
+ stream.Readable.call(this, options);
+
+ if (!options) {
+ options = {};
+ }
+
+ this._fileReader = new FileReader(file); // HTML FileReader
+ this._file = file;
+ this._size = file.size;
+ this._highWaterMark = options.highWaterMark || bufferSize;
+ this._offset = 0;
+ var self = this;
+
+ this._fileReader.onloadend = function (event) {
+ var data = event.target.result;
+ var buf = buffer.from(data);
+ self.push(buf);
+ };
+
+ this._fileReader.onerror = function (error) {
+ self.emit('error', error);
+ };
+}
+util.inherits(BrowserFileReadStream, stream.Readable);
+
+BrowserFileReadStream.prototype._read = function() {
+ if (this._offset >= this._size) {
+ this.push(null);
+ } else {
+ var end = this._offset + this._highWaterMark;
+ var slice = this._file.slice(this._offset, end);
+ this._fileReader.readAsArrayBuffer(slice);
+ this._offset = end;
+ }
+};
+
+module.exports = BrowserFileReadStream;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/streams/bufferstream.js b/src/node_modules/azure-storage/lib/common/streams/bufferstream.js
new file mode 100644
index 0000000..6bac838
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/bufferstream.js
@@ -0,0 +1,50 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var stream = require('stream');
+var util = require('util');
+
+function BufferStream(buffer, options) {
+ stream.Readable.call(this, options);
+
+ this._buffer = buffer;
+ this._offset = 0;
+ this._chunkSize = 4 * 1024 * 1024;
+ this._bufferSize = buffer.length;
+}
+
+util.inherits(BufferStream, stream.Readable);
+
+BufferStream.prototype._read = function () {
+ while (this.push(this._readNextChunk())) {
+ continue;
+ }
+};
+
+BufferStream.prototype._readNextChunk = function () {
+ var data = null;
+
+ if (this._offset < this._bufferSize) {
+ var end = this._offset + this._chunkSize;
+ end = end > this._bufferSize ? this._bufferSize : end;
+ data = this._buffer.slice(this._offset, end);
+ this._offset = end;
+ }
+
+ return data;
+};
+
+module.exports = BufferStream;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/streams/chunkallocator.js b/src/node_modules/azure-storage/lib/common/streams/chunkallocator.js
new file mode 100644
index 0000000..2ecc2e1
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/chunkallocator.js
@@ -0,0 +1,128 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+/**
+* Chunked memory pool allocator.
+* It could dramatically reduce the memory usage.
+* However, it can't dramatically reduce the CPU time since GC in v8 is very efficient.
+*/
+function ChunkAllocator(chunkSize, maxCount) {
+ // Track the unused buffers and number of used buffers
+ this._pool = [];
+ this._inuse = 0;
+
+ // Buffer size
+ this._chunkSize = chunkSize;
+
+ // If total memory is larger than this._chunkSize * this._maxCount, the buffer pool is not used.
+ this._maxCount = maxCount || 10;
+
+ // Immediately add a buffer to the pool.
+ this._extendMemoryPool();
+}
+
+/**
+* Synchronously require a buffer
+* Caller should be aware of that the content of buffer is random since the Buffer.fill is Time-consumed opreation.
+*/
+ChunkAllocator.prototype.getBuffer = function(size) {
+ var buffer = this._getBufferFromPool(size);
+ if (buffer === null) {
+ // Either the total memory is larger than this._chunkSize * this._maxCount
+ // Or, the size does not match the chunk size of the pool
+ buffer = Buffer.alloc(size);
+ }
+
+ this._inuse++;
+ return buffer;
+};
+
+/**
+* Get buffer from the current memory pool.
+*/
+ChunkAllocator.prototype._getBufferFromPool = function(size) {
+ // Return null if the given size does not match the chunk size of the buffer pool.
+ if(size !== this._chunkSize) {
+ return null;
+ }
+
+ // Extend the memory pool if it is empty.
+ if(this._pool.length === 0) {
+ this._extendMemoryPool();
+ }
+
+ // If the pool is not empty, return a buffer.
+ if(this._pool.length !== 0) {
+ return this._pool.pop();
+ } else {
+ return null;
+ }
+};
+
+/**
+* Extend the memory pool if the maximum size has not been reached.
+*/
+ChunkAllocator.prototype._extendMemoryPool = function() {
+ var total = this._pool.length + this._inuse;
+
+ // If the total is larger than the max, do not allocate more memory.
+ if(total >= this._maxCount) return;
+
+ // Calculate the new number of buffers, equal to the total*2 bounded by 1 and the maxCount
+ var nextSize = Math.min(total * 2, this._maxCount) || 1;
+
+ // Add more buffers.
+ var increment = nextSize - total;
+ for(var i = 0; i < increment; i++) {
+ var buffer = Buffer.alloc(this._chunkSize);
+ this._pool.push(buffer);
+ }
+};
+
+/**
+* Release the buffer.
+*/
+ChunkAllocator.prototype.releaseBuffer = function(buffer) {
+ if(buffer.length !== this._chunkSize) {
+ // Directly delete the buffer if bufferSize is invalid and wait for GC.
+ buffer = null;
+ return;
+ }
+
+ // Add the buffer to the pool if it is not full, otherwise delete it
+ if (this._pool.length < this._maxCount) {
+ this._pool.push(buffer);
+ } else {
+ buffer = null;
+ }
+
+ // Decrement _inuse
+ this._inuse--;
+
+ // _inuse could be below zero if a buffer is released which was not returned by getBuffer
+ if(this._inuse < 0) {
+ this._inuse = 0;
+ }
+};
+
+/**
+* Destroy ChunkAllocator.
+*/
+ChunkAllocator.prototype.destroy = function() {
+ this._pool = [];
+ this._inuse = 0;
+};
+
+module.exports = ChunkAllocator;
diff --git a/src/node_modules/azure-storage/lib/common/streams/chunkstream.js b/src/node_modules/azure-storage/lib/common/streams/chunkstream.js
new file mode 100644
index 0000000..d92b7f4
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/chunkstream.js
@@ -0,0 +1,321 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var stream = require('stream');
+var util = require('util');
+
+var azureutil = require('../util/util');
+var Md5Wrapper = require('../md5-wrapper');
+var Constants = require('../util/constants');
+var bufferSize = Constants.BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+
+/**
+* Chunk stream
+* 1. Calculate md5
+* 2. Track reading offset
+* 3. Work with customize memory allocator
+* 4. Buffer data from stream.
+* @param {object} options stream.Readable options
+*/
+function ChunkStream(options) {
+ stream.Stream.call(this);
+ this.writable = this.readable = true;
+
+ if (!options) {
+ options = {};
+ }
+
+ this._highWaterMark = options.highWaterMark || bufferSize;
+
+ this._paused = undefined; //True/false is the external status from users.
+
+ this._isStreamOpened = false;
+ this._offset = 0;
+ this._allocator = options.allocator;
+ this._streamEnded = false;
+ this._md5hash = null;
+ this._buffer = null;
+ this._internalBufferSize = 0;
+ this._outputLengthLimit = 0;
+ this._md5sum = undefined;
+
+ if (options.calcContentMd5) {
+ this._md5hash = new Md5Wrapper().createMd5Hash();
+ }
+}
+
+util.inherits(ChunkStream, stream.Stream);
+
+/**
+* Set the memory allocator.
+*/
+ChunkStream.prototype.setMemoryAllocator = function(allocator) {
+ this._allocator = allocator;
+};
+
+/**
+* Set the output length.
+*/
+ChunkStream.prototype.setOutputLength = function(length) {
+ if (length) {
+ this._outputLengthLimit = length;
+ }
+};
+
+/**
+* Internal stream ended
+*/
+ChunkStream.prototype.end = function (chunk, encoding, cb) {
+ if (typeof chunk === 'function') {
+ cb = chunk;
+ chunk = null;
+ encoding = null;
+ } else if (typeof encoding === 'function') {
+ cb = encoding;
+ encoding = null;
+ }
+
+ if (chunk) {
+ this.write(chunk, encoding);
+ }
+
+ this._streamEnded = true;
+ this._flushInternalBuffer();
+
+ if (cb) {
+ this.once('end', cb);
+ }
+
+ this.emit('end');
+};
+
+ChunkStream.prototype.finish = function () {
+ this.emit('finish');
+
+ this.destroy();
+};
+
+ChunkStream.prototype.error = function () {
+ this.emit('error');
+
+ this.destroy();
+};
+
+ChunkStream.prototype.destroy = function () {
+ this.writable = this.readable = false;
+
+ if (this._allocator && azureutil.objectIsFunction(this._allocator.destroy)) {
+ this._allocator.destroy();
+ }
+
+ this.emit('close');
+};
+
+ChunkStream.prototype.stop = function () {
+ this.destroy();
+ this._streamEnded = true;
+ this.emit('end');
+};
+
+/**
+* Add event listener
+*/
+ChunkStream.prototype.write = function (chunk, encoding) {
+ if (!this._isStreamOpened) {
+ this._isStreamOpened = true;
+ }
+
+ this._buildChunk(chunk, encoding);
+
+ return !this._paused;
+};
+
+/**
+* Buffer the data into a chunk and emit it
+*/
+ChunkStream.prototype._buildChunk = function (data) {
+ if (typeof data == 'string') {
+ data = Buffer.from(data);
+ }
+ var dataSize = data.length;
+ var dataOffset = 0;
+ do {
+ var buffer = null;
+ var targetSize = this._internalBufferSize + dataSize;
+
+ if (targetSize < this._highWaterMark) {
+ // add the data to the internal buffer and return as it is not yet full
+ this._copyToInternalBuffer(data, dataOffset, data.length);
+ return;
+ } else if (targetSize == this._highWaterMark){
+ var canReleaseInnerStreamBuffer = this._stream && this._stream._allocator && this._stream._allocator.releaseBuffer;
+ if(this._internalBufferSize === 0 && data.length === this._highWaterMark && !canReleaseInnerStreamBuffer) {
+ // set the buffer to the data passed in to avoid creating a new buffer
+ buffer = data;
+ } else {
+ // add the data to the internal buffer and pop that buffer
+ this._copyToInternalBuffer(data, dataOffset, data.length);
+ buffer = this._popInternalBuffer();
+ }
+ dataSize = 0;
+ } else {
+ // add data to the internal buffer until its full, then return it
+ // set the dataSize parameter so that additional data is not lost
+ var copySize = this._highWaterMark - this._internalBufferSize;
+ this._copyToInternalBuffer(data, dataOffset, dataOffset + copySize);
+ dataSize -= copySize;
+ dataOffset += copySize;
+ buffer = this._popInternalBuffer();
+ }
+ this._emitBufferData(buffer);
+ } while(dataSize > 0);
+};
+
+/**
+* Emit the buffer
+*/
+ChunkStream.prototype._emitBufferData = function(buffer) {
+ var newOffset = this._offset + buffer.length;
+ var range = {
+ start : this._offset,
+ end : newOffset - 1,
+ size : buffer.length
+ };
+
+ this._offset = newOffset;
+
+ if (this._outputLengthLimit > 0) {
+ // When the start postion is larger than the limit, no data will be consumed though there is an event to be emitted.
+ // So the buffer should not be calculated.
+ if (range.start <= this._outputLengthLimit) {
+ if (this._offset > this._outputLengthLimit) {
+ // Don't use negative end parameter which means the index starting from the end of the buffer
+ // to be compatible with node 0.8.
+ buffer = buffer.slice(0, buffer.length - (this._offset - this._outputLengthLimit));
+ }
+ if (this._md5hash) {
+ this._md5hash.update(buffer);
+ }
+ }
+ } else if (this._md5hash) {
+ this._md5hash.update(buffer);
+ }
+
+ this.emit('data', buffer, range);
+};
+
+/**
+* Copy data into internal buffer
+*/
+ChunkStream.prototype._copyToInternalBuffer = function(data, start, end) {
+ if(start === undefined) start = 0;
+ if(end === undefined) end = data.length;
+ if (!this._buffer) {
+ this._buffer = this._allocateNewBuffer();
+ this._internalBufferSize = 0;
+ }
+ var copied = data.copy(this._buffer, this._internalBufferSize, start, end);
+ this._internalBufferSize += copied;
+
+ if (this._stream && this._stream._allocator && this._stream._allocator.releaseBuffer) {
+ this._stream._allocator.releaseBuffer(data);
+ }
+
+ if(copied != (end - start)) {
+ throw new Error('Can not copy entire data to buffer');
+ }
+};
+
+/**
+* Flush internal buffer
+*/
+ChunkStream.prototype._flushInternalBuffer = function() {
+ var buffer = this._popInternalBuffer();
+ if (buffer) {
+ this._emitBufferData(buffer);
+ }
+};
+
+/**
+* Pop internal buffer
+*/
+ChunkStream.prototype._popInternalBuffer = function () {
+ var buf = null;
+ if (!this._buffer || this._internalBufferSize === 0) {
+ buf = null;
+ } else if(this._internalBufferSize == this._highWaterMark) {
+ buf = this._buffer;
+ } else {
+ buf = this._buffer.slice(0, this._internalBufferSize);
+ }
+
+ this._buffer = null;
+ this._internalBufferSize = 0;
+
+ return buf;
+};
+
+/**
+* Allocate a buffer
+*/
+ChunkStream.prototype._allocateNewBuffer = function() {
+ var size = this._highWaterMark;
+ if(this._allocator && azureutil.objectIsFunction(this._allocator.getBuffer)) {
+ return this._allocator.getBuffer(size);
+ } else {
+ var buffer = Buffer.alloc(size);
+ return buffer;
+ }
+};
+
+/**
+* Get file content md5 when read completely.
+*/
+ChunkStream.prototype.getContentMd5 = function(encoding) {
+ if (!encoding) encoding = 'base64';
+ if(!this._md5hash) {
+ throw new Error('Can\'t get content md5, please set the calcContentMd5 option for FileReadStream.');
+ } else {
+ if (this._streamEnded) {
+ if (!this._md5sum) {
+ this._md5sum = this._md5hash.digest(encoding);
+ }
+ return this._md5sum;
+ } else {
+ throw new Error('Stream has not ended.');
+ }
+ }
+};
+
+/**
+* Pause chunk stream
+*/
+ChunkStream.prototype.pause = function() {
+ this._paused = true;
+};
+
+/**
+* Resume read stream
+*/
+ChunkStream.prototype.resume = function() {
+ if (this._paused) {
+ this._paused = false;
+
+ this.emit('drain');
+ }
+};
+
+module.exports = ChunkStream;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/streams/chunkstreamwithstream.js b/src/node_modules/azure-storage/lib/common/streams/chunkstreamwithstream.js
new file mode 100644
index 0000000..4c3d6b2
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/chunkstreamwithstream.js
@@ -0,0 +1,103 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var ChunkStream = require('./chunkstream');
+var EventEmitter = require('events').EventEmitter;
+var util = require('util');
+var azureutil = require('./../util/util');
+
+/**
+* Chunk stream
+* 1. Calculate md5
+* 2. Track reading offset
+* 3. Work with customize memory allocator
+* 4. Buffer data from stream.
+* @param {object} options stream.Readable options
+*/
+function ChunkStreamWithStream(stream, options) {
+ ChunkStream.call(this, options);
+
+ stream.pause(); // Pause stream and wait for data listener. It's useful for node v0.8
+ this._stream = stream;
+ this._stream.on('end', this.end.bind(this)); // Should catch the end event for node v0.8
+}
+
+util.inherits(ChunkStreamWithStream, ChunkStream);
+
+/**
+* Add event listener
+*/
+ChunkStreamWithStream.prototype.on = function(event, listener) {
+ if(event === 'end' && this._streamEnded) {
+ listener(); //Directly call the end event when stream already ended
+ } else {
+ EventEmitter.prototype.on.call(this, event, listener);
+ }
+
+ if (event === 'data') {
+ if (!this._isStreamOpened) {
+ this._isStreamOpened = true;
+ this._stream.on('data', this._buildChunk.bind(this));
+ }
+ if (this._paused === undefined) {
+ this._stream.resume();
+ }
+ }
+
+ return this;
+};
+
+/**
+* Stop stream from external
+*/
+ChunkStreamWithStream.prototype.stop = function (chunk, encoding, cb) {
+ if (azureutil.objectIsFunction(this._stream.destroy)) {
+ this._stream.destroy();
+ } else {
+ this.pause();
+ }
+ ChunkStream.prototype.end.call(this, chunk, encoding, cb);
+};
+
+/**
+* Pause chunk stream
+*/
+ChunkStreamWithStream.prototype.pause = function () {
+ ChunkStream.prototype.pause.call(this);
+
+ this._stream.pause();
+};
+
+/**
+* Resume read stream
+*/
+ChunkStreamWithStream.prototype.resume = function() {
+ ChunkStream.prototype.resume.call(this);
+
+ this._stream.resume();
+};
+
+ChunkStreamWithStream.prototype.finish = function () {
+ ChunkStream.prototype.finish.call(this);
+ this._stream.emit.call(this._stream, 'finish');
+};
+
+ChunkStreamWithStream.prototype.destroy = function () {
+ ChunkStream.prototype.destroy.call(this);
+ this._stream.emit.call(this._stream, 'close');
+};
+
+module.exports = ChunkStreamWithStream;
diff --git a/src/node_modules/azure-storage/lib/common/streams/filereadstream.js b/src/node_modules/azure-storage/lib/common/streams/filereadstream.js
new file mode 100644
index 0000000..368824f
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/filereadstream.js
@@ -0,0 +1,261 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var stream = require('stream');
+var util = require('util');
+var fs = require('fs');
+var validator = require('validator');
+
+var Md5Wrapper = require('../md5-wrapper');
+var Constants = require('../util/constants');
+var bufferSize = Constants.BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+
+var EventEmitter = require('events').EventEmitter;
+
+/**
+* File read stream
+* 1. Calculate md5
+* 2. Track reading offset
+* 3. Work with customize memory allocator
+* 4. Buffer data from stream.
+* @param {object} options stream.Readable options
+*/
+function FileReadStream(path, options) {
+ stream.Stream.call(this);
+ this.readable = true;
+
+ if(!options) {
+ options = {};
+ }
+
+ this._destroyed = false;
+ this._streamEnded = false;
+ this._fd = null;
+ this._fileName = undefined;
+ this._highWaterMark = options.highWaterMark || bufferSize;
+ this._offset = 0;
+ this._paused = undefined;
+ this._allocator = options.allocator;
+ this._fileName = path;
+
+ this._md5hash = null;
+ this._md5sum = undefined;
+
+ if (options.calcContentMd5) {
+ this._md5hash = new Md5Wrapper().createMd5Hash();
+ }
+
+ this._open();
+}
+
+util.inherits(FileReadStream, stream.Stream);
+
+/**
+* Open file
+*/
+FileReadStream.prototype._open = function () {
+ var flags = 'r';
+ var self = this;
+ fs.open(this._fileName, flags, function(error, fd) {
+ if (error) {
+ self.emit('error', error);
+ } else {
+ self._fd = fd;
+ self.emit('open', fd);
+ }
+ });
+};
+
+/**
+* Add event listener
+*/
+FileReadStream.prototype.on = function(event, listener) {
+ if (event === 'data' && this._paused === undefined) {
+ this._paused = false;
+ this._emitData();
+ }
+
+ return EventEmitter.prototype.on.call(this, event, listener);
+};
+
+/**
+* Set memory allocator
+*/
+FileReadStream.prototype.setMemoryAllocator = function(allocator) {
+ this._allocator = allocator;
+};
+
+/**
+* Get buffer
+*/
+FileReadStream.prototype._getBuffer = function(size) {
+ if(this._allocator && this._allocator.getBuffer) {
+ return this._allocator.getBuffer(size);
+ } else {
+ var buffer = Buffer.alloc(size);
+ return buffer;
+ }
+};
+
+/**
+* Release buffer
+*/
+FileReadStream.prototype._releaseBuffer = function(buffer) {
+ if(this._allocator && this._allocator.releaseBuffer) {
+ this._allocator.releaseBuffer(buffer);
+ }
+};
+
+/**
+* Emit the data from file
+*/
+FileReadStream.prototype._emitData = function() {
+ var self = this;
+ if(!this._fd) {
+ this.once('open', function() {
+ self._emitData();
+ });
+ return;
+ }
+
+ if (this._paused || this._streamEnded) {
+ return;
+ }
+ var buffer = this._getBuffer(this._highWaterMark);
+ fs.read(this._fd, buffer, 0, this._highWaterMark, this._offset, function(error, bytesRead, readBuffer) {
+ if (error) {
+ self.emit('error', error);
+ return;
+ }
+
+ if(bytesRead === 0) {
+ if(!self._streamEnded) {
+ self._streamEnded = true;
+ self.emit('end');
+ }
+ return;
+ }
+
+ var range = {
+ start : self._offset,
+ end : self._offset + bytesRead - 1,
+ size : bytesRead
+ };
+
+ var data;
+ if(bytesRead == self._highWaterMark) {
+ data = readBuffer;
+ } else {
+ data = readBuffer.slice(0, bytesRead);
+ //Release the current buffer since we created a new one
+ self._releaseBuffer(readBuffer);
+ }
+
+ if(self._md5hash) {
+ self._md5hash.update(data);
+ }
+
+ self.emit('data', data, range);
+
+ // cleanup
+ self._offset += bytesRead;
+ buffer = readBuffer = data = null;
+ self._emitData();
+ });
+};
+
+/**
+* Get file content md5 when read completely.
+*/
+FileReadStream.prototype.getContentMd5 = function(encoding) {
+ if (!encoding) encoding = 'base64';
+ if(!this._md5hash) {
+ throw new Error('Can\'t get content md5, please set the calcContentMd5 option for FileReadStream.');
+ } else {
+ if (this._streamEnded) {
+ if (!this._md5sum) {
+ this._md5sum = this._md5hash.digest(encoding);
+ }
+ return this._md5sum;
+ } else {
+ throw new Error('FileReadStream has not ended.');
+ }
+ }
+};
+
+/**
+* Pause chunk stream
+*/
+FileReadStream.prototype.pause = function() {
+ this._paused = true;
+};
+
+/**
+* Resume read stream
+*/
+FileReadStream.prototype.resume = function() {
+ var previousState = this._paused;
+ if (this._paused) {
+ this._paused = false;
+
+ if(previousState === true) {
+ //Only start to emit data when it's in pause state
+ this._emitData();
+ }
+ }
+};
+
+FileReadStream.prototype.finish = function () {
+ this.destroy();
+};
+
+FileReadStream.prototype.destroy = function () {
+ if (this._destroyed) {
+ return;
+ }
+
+ var self = this;
+ this.readable = false;
+
+ function close(fd) {
+ fs.close(fd || self._fd, function(err) {
+ if (err) {
+ self.emit('error', err);
+ }
+ else {
+ self.emit('close');
+ }
+ });
+ self._fd = null;
+ self._destroyed = true;
+ }
+
+ // when the stream is closed immediately after creating it
+ if (!validator.isInt('' + this._fd)) {
+ this.once('open', close);
+ return;
+ }
+
+ close();
+};
+
+FileReadStream.prototype.stop = function () {
+ this.destroy();
+ this._streamEnded = true;
+ this.emit('end');
+};
+
+module.exports = FileReadStream;
diff --git a/src/node_modules/azure-storage/lib/common/streams/rangestream.js b/src/node_modules/azure-storage/lib/common/streams/rangestream.js
new file mode 100644
index 0000000..9043191
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/rangestream.js
@@ -0,0 +1,293 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var azureCommon = require('./../common.core');
+var azureutil = azureCommon.util;
+var Constants = require('./../util/constants');
+var EventEmitter = require('events').EventEmitter;
+
+/**
+* Range stream
+*/
+function RangeStream(serviceClient, container, blob, options) {
+ this.serviceClient = serviceClient;
+ this._emitter = new EventEmitter();
+ this._paused = false;
+ this._emittedAll = false;
+ this._emittedRangeIndex = 0;
+ this._rangelist = [];
+ this._resourcePath = [];
+ this._isEmitting = false;
+ this._rangeStreamEnded = false;
+ this._lengthHeader = Constants.HeaderConstants.CONTENT_LENGTH;
+ this._minRangeSize = Constants.BlobConstants.MIN_WRITE_PAGE_SIZE_IN_BYTES;
+ this._maxRangeSize = Constants.BlobConstants.DEFAULT_WRITE_PAGE_SIZE_IN_BYTES;
+ if (options.rangeStart) {
+ this._startOffset = options.rangeStart;
+ } else {
+ this._startOffset = 0;
+ }
+ this._dataOffset = this._startOffset;
+ if (options.rangeEnd) {
+ this._endOffset = options.rangeEnd;
+ } else {
+ this._endOffset = Number.MAX_VALUE;
+ }
+ if (container) {
+ this._resourcePath.push(container);
+ }
+ if (blob) {
+ this._resourcePath.push(blob);
+ }
+}
+
+/**
+* Get range list
+*/
+RangeStream.prototype.list = function (options, callback) {
+ var start = this._startOffset;
+ var end;
+ var singleRangeSize = Constants.BlobConstants.MAX_SINGLE_GET_PAGE_RANGE_SIZE;
+
+ if (this._listFunc === undefined) {
+ // the default function puts the whole blob into a single list item
+ this._listFunc = this._defaultListFunc;
+ end = this._endOffset;
+ } else {
+ end = Math.min(this._startOffset + singleRangeSize - 1, this._endOffset);
+ }
+ options.rangeStart = start;
+ if (end != Number.MAX_VALUE) {
+ options.rangeEnd = end;
+ }
+
+ var self = this;
+ var onList = function (error, ranges, response) {
+ if (error) {
+ callback(error);
+ } else {
+ if (self._rangeStreamEnded) {
+ return;
+ }
+
+ var totalSize = parseInt(response.headers[self._lengthHeader], 10);
+ var endOffset = Math.min(totalSize - 1, self._endOffset);
+ var rangeEnd = Math.min(end, endOffset);
+
+ if (!ranges.length) {
+ // convert single object to range
+ // start >= end means there is no valid regions
+ ranges.push({ start : start, end : rangeEnd, dataSize: 0 });
+ } else if (ranges[ranges.length - 1].end !== rangeEnd) {
+ // don't forget the zero chunk at the end of range
+ ranges.push({ start : ranges[ranges.length - 1].end + 1, end : rangeEnd, dataSize: 0 });
+ }
+
+ if (end >= endOffset) {
+ self._rangeStreamEnded = true;
+ }
+ self.resizeAndSaveRanges(ranges);
+ self._startOffset += singleRangeSize;
+ self._emitRange();
+
+ // This is only valid when listing pages because when listing with the default function, the "endOffset" will always equal to or greater than the "end".
+ if (end < endOffset && !self._rangeStreamEnded) {
+ process.nextTick(function () {
+ ranges = null;
+ self.list(options, callback);
+ self = null;
+ });
+ }
+ }
+ };
+
+ var callArguments = Array.prototype.slice.call(this._resourcePath);
+ callArguments.push(options);
+ callArguments.push(onList);
+ this._listFunc.apply(this.serviceClient, callArguments);
+};
+
+/**
+* Resize regions:
+* 1. Merge small pieces into a range no less than this._minRangeSize
+* 2. Split large pieces into ranges no more than this._maxRangeSize
+*/
+RangeStream.prototype.resizeAndSaveRanges = function (ranges) {
+ var rangeList = this._rangelist;
+ var holdingRange = { type : 'range', size : 0, dataSize : 0, start : this._startOffset, end : -1 };
+ var readingRange = null;
+ var rangeSize = 0;
+
+ for (var index = 0; index < ranges.length; index++) {
+ readingRange = ranges[index];
+ rangeSize = readingRange.end - holdingRange.start + 1;
+
+ if (rangeSize < this._minRangeSize) {
+ // merge fragment ranges
+ this.mergeRanges(holdingRange, readingRange);
+ } else {
+ if (holdingRange.end != -1) {
+ // save the holding range list and hold the reading range
+ this.splitAndSaveRanges(holdingRange, rangeList);
+ holdingRange = readingRange;
+ }
+
+ if (this._dataOffset != readingRange.start) {
+ // padding zero for empty range and hold the reading range
+ this.putZeroRange(this._dataOffset, readingRange.start - 1, rangeList);
+ holdingRange = readingRange;
+ } else if (holdingRange.end == -1) {
+ // if holdingRange is never set, it means readingRange exceeds MIN_WRITE_FILE_SIZE_IN_BYTES
+ this.splitAndSaveRanges(readingRange, rangeList);
+ // reading range has been saved, offset the holding start position for calculating the range size in next loop
+ holdingRange.start = readingRange.end + 1;
+ }
+ }
+
+ // If it is the last range, put the holding range into list anyway
+ if (index == ranges.length - 1 && holdingRange.end > holdingRange.start) {
+ this.splitAndSaveRanges(holdingRange, rangeList);
+ }
+
+ this._dataOffset = readingRange.end + 1;
+ }
+};
+
+/**
+* Put a zero range into range list
+*/
+RangeStream.prototype.putZeroRange = function (startOffset, endOffset, rangeList) {
+ var zeroDataRange = { type : 'range', size : -1, dataSize : 0, start : startOffset, end : endOffset };
+ this.splitAndSaveRanges(zeroDataRange, rangeList);
+};
+
+/**
+* Merge small ranges
+*/
+RangeStream.prototype.mergeRanges = function (holdingRange, readingRange) {
+ holdingRange.size = readingRange.end - holdingRange.start + 1;
+ holdingRange.dataSize += readingRange.dataSize;
+ holdingRange.end = readingRange.end;
+ return holdingRange;
+};
+
+/**
+* Split range into small pieces with maximum _maxRangeSize and minimum _minRangeSize size.
+* For example, [0, 10G - 1] => [0, 4MB - 1], [4MB, 8MB - 1] ... [10GB - 4MB, 10GB - 1]
+*/
+RangeStream.prototype.splitAndSaveRanges = function (range, rangeList) {
+ var rangeSize = range.end - range.start + 1;
+ var offset = range.start;
+ var limitedSize = 0;
+
+ while (rangeSize > 0) {
+ var newRange = { type : 'range', size : 0, dataSize : 0, start : -1, end : -1 };
+ limitedSize = Math.min(rangeSize, this._maxRangeSize);
+ newRange.start = offset;
+ newRange.size = limitedSize;
+ if (range.dataSize === 0) {
+ newRange.dataSize = 0;
+ } else {
+ newRange.dataSize = limitedSize;
+ }
+ offset += limitedSize;
+ newRange.end = offset - 1;
+ rangeList.push(newRange);
+ rangeSize -= limitedSize;
+ }
+};
+
+/**
+* Emit a range
+*/
+RangeStream.prototype._emitRange = function () {
+ if (this._paused || this._emittedAll || this._isEmitting) return;
+ this._isEmitting = true;
+ try {
+ for (; this._emittedRangeIndex < this._rangelist.length; this._emittedRangeIndex++) {
+ if (this._paused) {
+ return;
+ }
+ var range = this._rangelist[this._emittedRangeIndex];
+ this._emitter.emit('range', range);
+ this._rangelist[this._emittedRangeIndex] = null;
+ }
+
+ if (this._rangeStreamEnded) {
+ this._rangelist = null;
+ this._emittedAll = true;
+ this._emitter.emit('end');
+ }
+ } finally {
+ this._isEmitting = false;
+ }
+};
+
+/**
+* The Default list function which puts the whole blob into one range.
+*/
+RangeStream.prototype._defaultListFunc = function (container, blob, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ this.getBlobProperties(container, blob, options, function (error, result, response) {
+ if (error) {
+ callback(error);
+ } else {
+ var range = [{}];
+ range[0].start = options.rangeStart ? Math.max(options.rangeStart, 0) : 0;
+ range[0].end = options.rangeEnd ? Math.min(options.rangeEnd, result.contentLength - 1) : result.contentLength - 1;
+ range[0].size = range[0].end - range[0].start + 1;
+ range[0].dataSize = range[0].size;
+ callback(error, range, response);
+ }
+ });
+};
+
+/**
+* Add event listener
+*/
+RangeStream.prototype.on = function (event, listener) {
+ this._emitter.on(event, listener);
+};
+
+/**
+* Pause the stream
+*/
+RangeStream.prototype.pause = function () {
+ this._paused = true;
+};
+
+/**
+* Resume the stream
+*/
+RangeStream.prototype.resume = function () {
+ this._paused = false;
+ if (!this._isEmitting) {
+ this._emitRange();
+ }
+};
+
+/**
+* Stop the stream
+*/
+RangeStream.prototype.stop = function () {
+ this.pause();
+ this._emittedAll = true;
+ this._emitter.emit('end');
+};
+
+module.exports = RangeStream;
diff --git a/src/node_modules/azure-storage/lib/common/streams/readablefs.js b/src/node_modules/azure-storage/lib/common/streams/readablefs.js
new file mode 100644
index 0000000..9601935
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/readablefs.js
@@ -0,0 +1,32 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var rs = require('readable-stream').Readable;
+var fs = require('fs');
+
+/*
+* As far as streams support goes, we can get the node 0.10 stream API in node 0.8.
+* Use the readable-stream module (https://www.npmjs.org/package/readable-stream) which is
+* essentially a copy of the stream modules from core node 0.10 and it just works on both 0.8 and 0.10.
+*/
+
+exports.createReadStream = function(path, options) {
+ var stream = fs.createReadStream(path, options);
+ if (/^v0\.8\./.test(process.version)) {
+ stream = rs().wrap(stream);
+ }
+ return stream;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/streams/speedsummary.js b/src/node_modules/azure-storage/lib/common/streams/speedsummary.js
new file mode 100644
index 0000000..79185cd
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/streams/speedsummary.js
@@ -0,0 +1,215 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var EventEmitter = require('events');
+var util = require('util');
+var azureutil = require('../util/util');
+
+/**
+* Blob upload/download speed summary.
+* Trigger 'progress' event every progress updates.
+*/
+function SpeedSummary (name) {
+ this.name = name;
+ this._startTime = Date.now();
+ this._timeWindowInSeconds = 10;
+ this._timeWindow = this._timeWindowInSeconds * 1000;
+ this._totalWindowSize = 0;
+ this._speedTracks = new Array(this._timeWindowInSeconds);
+ this._speedTrackPtr = 0;
+ this.totalSize = undefined;
+ this.completeSize = 0;
+}
+
+util.inherits(SpeedSummary, EventEmitter);
+
+/**
+* Convert the size to human readable size
+*/
+function toHumanReadableSize(size, len) {
+ if(!size) return '0B';
+ if (!len || len <= 0) {
+ len = 2;
+ }
+ var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+ var i = Math.floor( Math.log(size) / Math.log(1024));
+ return (size/Math.pow(1024, i)).toFixed(len) + units[i];
+}
+
+/**
+* Get running seconds
+*/
+SpeedSummary.prototype.getElapsedSeconds = function(humanReadable) {
+ var now = Date.now();
+ var seconds = parseInt((now - this._startTime) / 1000, 10);
+ if (humanReadable !== false) {
+ var s = parseInt(seconds % 60, 10);
+ seconds /= 60;
+ var m = Math.floor(seconds % 60);
+ seconds /= 60;
+ var h = Math.floor(seconds);
+ seconds = util.format('%s:%s:%s', azureutil.zeroPaddingString(h, 2), azureutil.zeroPaddingString(m, 2), azureutil.zeroPaddingString(s, 2));
+ }
+ return seconds;
+};
+
+/**
+* Get complete percentage
+* @param {int} len The number of digits after the decimal point.
+*/
+SpeedSummary.prototype.getCompletePercent = function(len) {
+ if (this.totalSize) {
+ if(!len || len <= 0) {
+ len = 1;
+ }
+ return (this.completeSize * 100 / this.totalSize).toFixed(len);
+ } else {
+ if(this.totalSize === 0) {
+ return 100;
+ } else {
+ return 0;
+ }
+ }
+};
+
+/**
+* Get average upload/download speed
+*/
+SpeedSummary.prototype.getAverageSpeed = function(humanReadable) {
+ var elapsedTime = this.getElapsedSeconds(false);
+ return this._getInternalSpeed(this.completeSize, elapsedTime, humanReadable);
+};
+
+/**
+* Get instant speed
+*/
+SpeedSummary.prototype.getSpeed = function(humanReadable) {
+ this._refreshSpeedTracks();
+ var elapsedTime = this.getElapsedSeconds(false);
+ elapsedTime = Math.min(elapsedTime, this._timeWindowInSeconds);
+ return this._getInternalSpeed(this._totalWindowSize, elapsedTime, humanReadable);
+};
+
+/**
+* Get internal speed
+*/
+SpeedSummary.prototype._getInternalSpeed = function(totalSize, elapsedTime, humanReadable) {
+ if (elapsedTime <= 0) {
+ elapsedTime = 1;
+ }
+ var speed = totalSize / elapsedTime;
+ if(humanReadable !== false) {
+ speed = toHumanReadableSize(speed) + '/s';
+ }
+ return speed;
+};
+
+/**
+* Refresh speed tracks
+*/
+SpeedSummary.prototype._refreshSpeedTracks = function() {
+ var now = Date.now();
+ var totalSize = 0;
+ for(var i = 0; i < this._speedTracks.length; i++) {
+ if(!this._speedTracks[i]) continue;
+ if(now - this._speedTracks[i].timeStamp <= this._timeWindow) {
+ totalSize += this._speedTracks[i].size;
+ } else {
+ this._speedTracks[i] = null;
+ }
+ }
+ this._totalWindowSize = totalSize;
+};
+
+/**
+* Increment the complete data size
+*/
+SpeedSummary.prototype.increment = function(len) {
+ this.completeSize += len;
+ this._recordSpeed(len);
+
+ var that = this;
+ process.nextTick(function () {
+ that.emit('progress');
+ });
+
+ return this.completeSize;
+};
+
+/**
+* record complete size into speed tracks
+*/
+SpeedSummary.prototype._recordSpeed = function(completeSize) {
+ var now = Date.now();
+ var track = this._speedTracks[this._speedTrackPtr];
+ if(track) {
+ var timeDiff = now - track.timeStamp;
+ if(timeDiff > this._timeWindow) {
+ track.timeStamp = now;
+ track.size = completeSize;
+ } else if(timeDiff <= 1000) { //1 seconds
+ track.size += completeSize;
+ } else {
+ this._speedTrackPtr = (this._speedTrackPtr + 1) % this._timeWindowInSeconds;
+ this._recordSpeed(completeSize);
+ }
+ } else {
+ track = {timeStamp : now, size: completeSize};
+ this._speedTracks[this._speedTrackPtr] = track;
+ }
+};
+
+/**
+* Get auto increment function
+*/
+SpeedSummary.prototype.getAutoIncrementFunction = function(size) {
+ var self = this;
+ return function(error, retValue) {
+ if(!error) {
+ var doneSize = 0;
+ if((!retValue && retValue !== 0) || isNaN(retValue)) {
+ doneSize = size;
+ } else {
+ doneSize = retValue;
+ }
+ self.increment(doneSize);
+ }
+ };
+};
+
+/**
+* Get total size
+*/
+SpeedSummary.prototype.getTotalSize = function(humanReadable) {
+ if (humanReadable !== false) {
+ return toHumanReadableSize(this.totalSize);
+ } else {
+ return this.totalSize;
+ }
+};
+
+/**
+* Get completed data size
+*/
+SpeedSummary.prototype.getCompleteSize = function(humanReadable) {
+ if (humanReadable !== false) {
+ return toHumanReadableSize(this.completeSize);
+ } else {
+ return this.completeSize;
+ }
+};
+
+module.exports = SpeedSummary;
diff --git a/src/node_modules/azure-storage/lib/common/util/accesscondition.js b/src/node_modules/azure-storage/lib/common/util/accesscondition.js
new file mode 100644
index 0000000..f89c8ef
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/accesscondition.js
@@ -0,0 +1,166 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'AccessCondition'.
+
+/**
+* Defines constants, enums, and utility functions for use with storage access condition.
+* @namespace
+*/
+
+'use strict';
+
+exports = module.exports;
+
+/**
+* Constructs an empty access condition.
+*
+* @return {object} An empty AccessCondition object
+*/
+exports.generateEmptyCondition = function () {
+ return {};
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource does not exist on the service
+*
+* Setting this access condition modifies the request to include the HTTP If-None-Match conditional header
+
+* @return {AccessConditions} An AccessCondition object that represents a condition that checks for nonexistence
+*/
+exports.generateIfNotExistsCondition = function () {
+ var accessCondition = {};
+ accessCondition.EtagNonMatch = '*';
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource exists on the service
+*
+* Setting this access condition modifies the request to include the HTTP If-Match conditional header
+
+* @return {AccessConditions} An AccessCondition object that represents a condition that checks for existence
+*/
+exports.generateIfExistsCondition = function () {
+ var accessCondition = {};
+ accessCondition.EtagMatch = '*';
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource's ETag value
+* does not match the specified ETag value
+*
+* Setting this access condition modifies the request to include the HTTP If-None-Match conditional header
+*
+* @param {string} etag The ETag value to check against the resource's ETag
+* @return {AccessConditions} An AccessCondition object that represents the If-None-Match condition
+*/
+exports.generateIfNoneMatchCondition = function (etag) {
+ var accessCondition = {};
+ accessCondition.EtagNonMatch = etag;
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource's ETag value
+* matches the specified ETag value
+*
+* Setting this access condition modifies the request to include the HTTP If-Match conditional header
+*
+* @param {string} etag The ETag value to check against the resource's ETag
+* @return {AccessConditions} An AccessCondition object that represents the If-Match condition
+*/
+exports.generateIfMatchCondition = function (etag) {
+ var accessCondition = {};
+ accessCondition.EtagMatch = etag;
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource has been
+* modified since the specified time
+*
+* Setting this access condition modifies the request to include the HTTP If-Modified-Since conditional header
+*
+* @param {Date|string} time A date object specifying the time since which the resource must have been modified
+* @return {AccessConditions} An AccessCondition object that represents the If-Modified-Since condition
+*/
+exports.generateIfModifiedSinceCondition = function (time) {
+ var accessCondition = {};
+ accessCondition.DateModifedSince = time;
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource has not been
+* modified since the specified time
+*
+* Setting this access condition modifies the request to include the HTTP If-Unmodified-Since conditional header
+*
+* @param {Date|string} time A date object specifying the time since which the resource must have not been modified
+* @return {AccessConditions} An AccessCondition object that represents the If-Unmodified-Since condition
+*/
+exports.generateIfNotModifiedSinceCondition = function (time) {
+ var accessCondition = {};
+ accessCondition.DateUnModifiedSince = time;
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource's sequence number
+* is equal to the specified value
+*
+* Setting this access condition modifies the request to include the HTTP x-ms-if-sequence-number-eq conditional header
+*
+* @param {Number|string} sequenceNumber A date object specifying the time since which the resource must have not been modified
+* @return {AccessConditions} An AccessCondition object that represents the If-Unmodified-Since condition
+*/
+exports.generateSequenceNumberEqualCondition = function (sequenceNumber) {
+ var accessCondition = {};
+ accessCondition.SequenceNumberEqual = sequenceNumber;
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource's sequence number
+* is less than the specified value
+*
+* Setting this access condition modifies the request to include the HTTP x-ms-if-sequence-number-lt conditional header
+*
+* @param {Number|string} sequenceNumber A date object specifying the time since which the resource must have not been modified
+* @return {AccessConditions} An AccessCondition object that represents the If-Unmodified-Since condition
+*/
+exports.generateSequenceNumberLessThanCondition = function (sequenceNumber) {
+ var accessCondition = {};
+ accessCondition.SequenceNumberLessThan = sequenceNumber;
+ return accessCondition;
+};
+
+/**
+* Constructs an access condition such that an operation will be performed only if the resource's sequence number
+* is less than or equal to the specified value
+*
+* Setting this access condition modifies the request to include the HTTP x-ms-if-sequence-number-le conditional header
+*
+* @param {Number|string} sequenceNumber A date object specifying the time since which the resource must have not been modified
+* @return {AccessConditions} An AccessCondition object that represents the If-Unmodified-Since condition
+*/
+exports.generateSequenceNumberLessThanOrEqualCondition = function (sequenceNumber) {
+ var accessCondition = {};
+ accessCondition.SequenceNumberLessThanOrEqual = sequenceNumber;
+ return accessCondition;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/constants.js b/src/node_modules/azure-storage/lib/common/util/constants.js
new file mode 100644
index 0000000..4d8dc80
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/constants.js
@@ -0,0 +1,2607 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'Constants'.
+exports = module.exports;
+
+var storageDnsSuffix = process.env.AZURE_STORAGE_DNS_SUFFIX || 'core.windows.net';
+
+/**
+* Defines constants.
+*/
+var Constants = {
+ /*
+ * Specifies the value to use for UserAgent header.
+ *
+ * @const
+ * @type {string}
+ */
+ USER_AGENT_PRODUCT_NAME: 'Azure-Storage',
+
+ /*
+ * Specifies the value to use for UserAgent header.
+ *
+ * @const
+ * @type {string}
+ */
+ USER_AGENT_PRODUCT_VERSION: '2.10.3',
+
+ /**
+ * The number of default concurrent requests for parallel operation.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_PARALLEL_OPERATION_THREAD_COUNT: 5,
+
+ /**
+ * The value of default socket reuse for batch operation.
+ *
+ * @const
+ * @type {boolean}
+ */
+ DEFAULT_ENABLE_REUSE_SOCKET: true,
+
+ /**
+ * Constant representing a kilobyte (Non-SI version).
+ *
+ * @const
+ * @type {int}
+ */
+ KB: 1024,
+
+ /**
+ * Constant representing a megabyte (Non-SI version).
+ *
+ * @const
+ * @type {int}
+ */
+ MB: 1024 * 1024,
+
+ /**
+ * Constant representing a gigabyte (Non-SI version).
+ *
+ * @const
+ * @type {int}
+ */
+ GB: 1024 * 1024 * 1024,
+
+ /**
+ * Specifies HTTP.
+ *
+ * @const
+ * @type {string}
+ */
+ HTTP: 'http:',
+
+ /**
+ * Specifies HTTPS.
+ *
+ * @const
+ * @type {string}
+ */
+ HTTPS: 'https:',
+
+ /**
+ * Default HTTP port.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_HTTP_PORT: 80,
+
+ /**
+ * Default HTTPS port.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_HTTPS_PORT: 443,
+
+ /**
+ * Default client request timeout in milliseconds.
+ * Integer containing the number of milliseconds to wait for a server to send response headers (and start the response body) before aborting the request.
+ * 2 minutes by default.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_CLIENT_REQUEST_TIMEOUT_IN_MS: 120000,
+
+ /**
+ * Marker for atom metadata.
+ *
+ * @const
+ * @type {string}
+ */
+ XML_METADATA_MARKER: '$',
+
+ /**
+ * Marker for atom value.
+ *
+ * @const
+ * @type {string}
+ */
+ XML_VALUE_MARKER: '_',
+
+ /**
+ * Defines the service types indicators.
+ *
+ * @const
+ * @enum {string}
+ */
+ ServiceType: {
+ Blob: 'blob',
+ Queue: 'queue',
+ Table: 'table',
+ File: 'file'
+ },
+
+ /**
+ * Specifies the location used to indicate which location the operation can be performed against.
+ *
+ * @const
+ * @enum {int}
+ */
+ RequestLocationMode: {
+ PRIMARY_ONLY: 0,
+ SECONDARY_ONLY: 1,
+ PRIMARY_OR_SECONDARY: 2
+ },
+
+ /**
+ * Represents a storage service location.
+ *
+ * @const
+ * @enum {int}
+ */
+ StorageLocation: {
+ PRIMARY: 0,
+ SECONDARY: 1
+ },
+
+ /**
+ * Defines constants for use with account SAS.
+ */
+ AccountSasConstants:{
+ /**
+ * Permission types.
+ *
+ * @const
+ * @enum {string}
+ */
+ Permissions: {
+ READ: 'r',
+ ADD: 'a',
+ CREATE: 'c',
+ UPDATE: 'u',
+ PROCESS: 'p',
+ WRITE: 'w',
+ DELETE: 'd',
+ LIST: 'l'
+ },
+
+ /**
+ * Services types.
+ *
+ * @const
+ * @enum {string}
+ */
+ Services: {
+ BLOB: 'b',
+ FILE: 'f',
+ QUEUE: 'q',
+ TABLE: 't'
+ },
+
+ /**
+ * Resources types.
+ *
+ * @const
+ * @enum {string}
+ */
+ Resources: {
+ SERVICE: 's',
+ CONTAINER: 'c',
+ OBJECT: 'o'
+ },
+
+ /**
+ * Protocols types.
+ *
+ * @const
+ * @enum {string}
+ */
+ Protocols: {
+ HTTPSONLY: 'https',
+ HTTPSORHTTP: 'https,http'
+ }
+ },
+
+ /**
+ * Defines constants for use with shared access policies.
+ */
+ AclConstants: {
+ /**
+ * XML element for an access policy.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCESS_POLICY: 'AccessPolicy',
+
+ /**
+ * XML element for the end time of an access policy.
+ *
+ * @const
+ * @type {string}
+ */
+ EXPIRY: 'Expiry',
+
+ /**
+ * XML attribute for IDs.
+ *
+ * @const
+ * @type {string}
+ */
+ ID: 'Id',
+
+ /**
+ * XML element for the permission of an access policy.
+ *
+ * @const
+ * @type {string}
+ */
+ PERMISSION: 'Permission',
+
+ /**
+ * XML element for a signed identifier.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_IDENTIFIER_ELEMENT: 'SignedIdentifier',
+
+ /**
+ * XML element for signed identifiers.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_IDENTIFIERS_ELEMENT: 'SignedIdentifiers',
+
+ /**
+ * XML element for the start time of an access policy.
+ *
+ * @const
+ * @type {string}
+ */
+ START: 'Start'
+ },
+
+ /**
+ * Defines constants for use with service properties.
+ */
+ ServicePropertiesConstants: {
+ /**
+ * XML element for storage service properties.
+ *
+ * @const
+ * @type {string}
+ */
+ STORAGE_SERVICE_PROPERTIES_ELEMENT: 'StorageServiceProperties',
+
+ /**
+ * Default analytics version to send for logging, hour metrics and minute metrics.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_ANALYTICS_VERSION: '1.0',
+
+ /**
+ * XML element for logging.
+ *
+ * @const
+ * @type {string}
+ */
+ LOGGING_ELEMENT: 'Logging',
+
+ /**
+ * XML element for version.
+ *
+ * @const
+ * @type {string}
+ */
+ VERSION_ELEMENT: 'Version',
+
+ /**
+ * XML element for delete.
+ *
+ * @const
+ * @type {string}
+ */
+ DELETE_ELEMENT: 'Delete',
+
+ /**
+ * XML element for read.
+ *
+ * @const
+ * @type {string}
+ */
+ READ_ELEMENT: 'Read',
+
+ /**
+ * XML element for write.
+ *
+ * @const
+ * @type {string}
+ */
+ WRITE_ELEMENT: 'Write',
+
+ /**
+ * XML element for retention policy.
+ *
+ * @const
+ * @type {string}
+ */
+ RETENTION_POLICY_ELEMENT: 'RetentionPolicy',
+
+ /**
+ * XML element for enabled.
+ *
+ * @const
+ * @type {string}
+ */
+ ENABLED_ELEMENT: 'Enabled',
+
+ /**
+ * XML element for days.
+ *
+ * @const
+ * @type {string}
+ */
+ DAYS_ELEMENT: 'Days',
+
+ /**
+ * XML element for HourMetrics.
+ *
+ * @const
+ * @type {string}
+ */
+ HOUR_METRICS_ELEMENT: 'HourMetrics',
+
+ /**
+ * XML element for MinuteMetrics.
+ *
+ * @const
+ * @type {string}
+ */
+ MINUTE_METRICS_ELEMENT: 'MinuteMetrics',
+
+ /**
+ * XML element for Cors.
+ *
+ * @const
+ * @type {string}
+ */
+ CORS_ELEMENT: 'Cors',
+
+ /**
+ * XML element for CorsRule.
+ *
+ * @const
+ * @type {string}
+ */
+ CORS_RULE_ELEMENT: 'CorsRule',
+
+ /**
+ * XML element for AllowedOrigins.
+ *
+ * @const
+ * @type {string}
+ */
+ ALLOWED_ORIGINS_ELEMENT: 'AllowedOrigins',
+
+ /**
+ * XML element for AllowedMethods.
+ *
+ * @const
+ * @type {string}
+ */
+ ALLOWED_METHODS_ELEMENT: 'AllowedMethods',
+
+ /**
+ * XML element for MaxAgeInSeconds.
+ *
+ * @const
+ * @type {string}
+ */
+ MAX_AGE_IN_SECONDS_ELEMENT: 'MaxAgeInSeconds',
+
+ /**
+ * XML element for ExposedHeaders.
+ *
+ * @const
+ * @type {string}
+ */
+ EXPOSED_HEADERS_ELEMENT: 'ExposedHeaders',
+
+ /**
+ * XML element for AllowedHeaders.
+ *
+ * @const
+ * @type {string}
+ */
+ ALLOWED_HEADERS_ELEMENT: 'AllowedHeaders',
+
+ /**
+ * XML element for IncludeAPIs.
+ *
+ * @const
+ * @type {string}
+ */
+ INCLUDE_APIS_ELEMENT: 'IncludeAPIs',
+
+ /**
+ * XML element for DefaultServiceVersion.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_SERVICE_VERSION_ELEMENT: 'DefaultServiceVersion',
+
+ /**
+ * XML element for DeleteRetentionPolicy.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_DELETE_RETENTION_POLICY_ELEMENT: 'DeleteRetentionPolicy',
+
+ /**
+ * XML element for StaticWebsite.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_STATIC_WEBSITE_ELEMENT: 'StaticWebsite',
+
+ /**
+ * XML element for StaticWebsite/IndexDocument.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_INDEX_DOCUMENT_ELEMENT: 'IndexDocument',
+
+ /**
+ * XML element for StaticWebsite/ErrorDocument404Path.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_ERROR_DOCUMENT_404_PATH_ELEMENT: 'ErrorDocument404Path'
+ },
+
+ /**
+ * Defines constants for use with blob operations.
+ */
+ BlobConstants: {
+ /**
+ * XML element for the latest.
+ *
+ * @const
+ * @type {string}
+ */
+ LATEST_ELEMENT: 'Latest',
+
+ /**
+ * XML element for uncommitted blocks.
+ *
+ * @const
+ * @type {string}
+ */
+ UNCOMMITTED_ELEMENT: 'Uncommitted',
+
+ /**
+ * XML element for a block list.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOCK_LIST_ELEMENT: 'BlockList',
+
+ /**
+ * XML element for committed blocks.
+ *
+ * @const
+ * @type {string}
+ */
+ COMMITTED_ELEMENT: 'Committed',
+
+ /**
+ * The default write page size, in bytes, used by blob streams.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_WRITE_PAGE_SIZE_IN_BYTES: 4 * 1024 * 1024,
+
+ /**
+ * The minimum write page size, in bytes, used by blob streams.
+ *
+ * @const
+ * @type {int}
+ */
+ MIN_WRITE_PAGE_SIZE_IN_BYTES: 2 * 1024 * 1024,
+
+ /**
+ * The default maximum size, in bytes, of a blob before it must be separated into blocks.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES: 32 * 1024 * 1024,
+
+ /**
+ * The default write block size, in bytes, used by blob streams.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES: 4 * 1024 * 1024,
+
+ /**
+ * The default critical memory limitation in 32bit Node.js environment, in bytes.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_CRITICAL_MEMORY_LIMITATION_32_IN_BYTES: 800 * 1024 * 1024,
+
+ /**
+ * The default critical memory limitation in browser environment, in bytes.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_CRITICAL_MEMORY_LIMITATION_BROWSER_IN_BYTES: 1 * 1024 * 1024 * 1024,
+
+ /**
+ * The default minimum memory usage in browser environment, in bytes.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_MINIMUM_MEMORY_USAGE_BROWSER_IN_BYTES: 4 * 1024 * 1024,
+
+ /**
+ * The maximum size of a single block of block blob.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_BLOCK_BLOB_BLOCK_SIZE: 100 * 1024 * 1024,
+
+ /**
+ * The maximum size of a single block of append blob.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_APPEND_BLOB_BLOCK_SIZE: 4 * 1024 * 1024,
+
+ /**
+ * The maximum size, in bytes, of a blob before it must be separated into blocks.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES: 64 * 1024 * 1024,
+
+ /**
+ * The maximum range get size when requesting for a contentMD5.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_RANGE_GET_SIZE_WITH_MD5 : 4 * 1024 * 1024,
+
+ /**
+ * The maximum page range size for a page update operation.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_UPDATE_PAGE_SIZE : 4 * 1024 * 1024,
+
+ /**
+ * The maximum buffer size for writing a stream buffer.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_QUEUED_WRITE_DISK_BUFFER_SIZE : 64 * 1024 * 1024,
+
+ /**
+ * Max size for single get page range. The max value should be 150MB.
+ * http://blogs.msdn.com/b/windowsazurestorage/archive/2012/03/26/getting-the-page-ranges-of-a-large-page-blob-in-segments.aspx
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_SINGLE_GET_PAGE_RANGE_SIZE : 37 * 4 * 1024 * 1024,
+
+ /**
+ * The size of a page, in bytes, in a page blob.
+ *
+ * @const
+ * @type {int}
+ */
+ PAGE_SIZE: 512,
+
+ /**
+ * Resource types.
+ *
+ * @const
+ * @enum {string}
+ */
+ ResourceTypes: {
+ CONTAINER: 'c',
+ BLOB: 'b'
+ },
+
+ /**
+ * List blob types.
+ *
+ * @const
+ * @enum {string}
+ */
+ ListBlobTypes: {
+ Blob: 'b',
+ Directory: 'd'
+ },
+
+ /**
+ * Put page write options
+ *
+ * @const
+ * @enum {string}
+ */
+ PageWriteOptions: {
+ UPDATE: 'update',
+ CLEAR: 'clear'
+ },
+
+ /**
+ * Blob types
+ *
+ * @const
+ * @enum {string}
+ */
+ BlobTypes: {
+ BLOCK: 'BlockBlob',
+ PAGE: 'PageBlob',
+ APPEND: 'AppendBlob'
+ },
+
+ /**
+ * Blob lease constants
+ *
+ * @const
+ * @enum {string}
+ */
+ LeaseOperation: {
+ ACQUIRE: 'acquire',
+ RENEW: 'renew',
+ CHANGE: 'change',
+ RELEASE: 'release',
+ BREAK: 'break'
+ }
+ },
+
+ /**
+ * Defines constants for use with file operations.
+ */
+ FileConstants: {
+ /**
+ * The default write size, in bytes, used by file streams.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_WRITE_SIZE_IN_BYTES: 4 * 1024 * 1024,
+
+ /**
+ * The maximum range size when requesting for a contentMD5.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_RANGE_GET_SIZE_WITH_MD5 : 4 * 1024 * 1024,
+
+ /**
+ * The maximum range size for a file update operation.
+ *
+ * @const
+ * @type {int}
+ */
+ MAX_UPDATE_FILE_SIZE : 4 * 1024 * 1024,
+
+ /**
+ * The default minimum size, in bytes, of a file when it must be separated into ranges.
+ *
+ * @const
+ * @type {int}
+ */
+ DEFAULT_SINGLE_FILE_GET_THRESHOLD_IN_BYTES: 32 * 1024 * 1024,
+
+ /**
+ * The minimum write file size, in bytes, used by file streams.
+ *
+ * @const
+ * @type {int}
+ */
+ MIN_WRITE_FILE_SIZE_IN_BYTES: 2 * 1024 * 1024,
+
+ /**
+ * Put range write options
+ *
+ * @const
+ * @enum {string}
+ */
+ RangeWriteOptions: {
+ UPDATE: 'update',
+ CLEAR: 'clear'
+ },
+
+ /**
+ * Resource types.
+ *
+ * @const
+ * @enum {string}
+ */
+ ResourceTypes: {
+ SHARE: 's',
+ FILE: 'f'
+ }
+ },
+
+ /**
+ * Defines constants for use with queue storage.
+ */
+ QueueConstants: {
+ /**
+ * XML element for QueueMessage.
+ *
+ * @const
+ * @type {string}
+ */
+ QUEUE_MESSAGE_ELEMENT: 'QueueMessage',
+
+ /**
+ * XML element for MessageText.
+ *
+ * @const
+ * @type {string}
+ */
+ MESSAGE_TEXT_ELEMENT: 'MessageText'
+ },
+
+ /**
+ * Defines constants for use with table storage.
+ */
+ TableConstants: {
+ /**
+ * The changeset response delimiter.
+ *
+ * @const
+ * @type {string}
+ */
+ CHANGESET_DELIMITER: '--changesetresponse_',
+
+ /**
+ * The batch response delimiter.
+ *
+ * @const
+ * @type {string}
+ */
+ BATCH_DELIMITER: '--batchresponse_',
+
+ /**
+ * The next continuation row key token.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTINUATION_NEXT_ROW_KEY: 'x-ms-continuation-nextrowkey',
+
+ /**
+ * The next continuation partition key token.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTINUATION_NEXT_PARTITION_KEY: 'x-ms-continuation-nextpartitionkey',
+
+ /**
+ * The next continuation table name token.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTINUATION_NEXT_TABLE_NAME: 'x-ms-continuation-nexttablename',
+
+ /**
+ * The next row key query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ NEXT_ROW_KEY: 'NextRowKey',
+
+ /**
+ * The next partition key query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ NEXT_PARTITION_KEY: 'NextPartitionKey',
+
+ /**
+ * The next table name query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ NEXT_TABLE_NAME: 'NextTableName',
+
+ /**
+ * Prefix of the odata properties returned in a JSON query.
+ *
+ * @const
+ * @type {string}
+ */
+ ODATA_PREFIX: 'odata.',
+
+ /**
+ * Constant representing the string following a type annotation in a JSON table query.
+ *
+ * @const
+ * @type {string}
+ */
+ ODATA_TYPE_SUFFIX: '@odata.type',
+
+ /**
+ * Constant representing the property where the odata metadata elements are stored.
+ *
+ * @const
+ * @type {string}
+ */
+ ODATA_METADATA_MARKER: '.metadata',
+
+ /**
+ * Constant representing the value for an entity property.
+ *
+ * @const
+ * @type {string}
+ */
+ ODATA_VALUE_MARKER: '_',
+
+ /**
+ * Constant representing the type for an entity property.
+ *
+ * @const
+ * @type {string}
+ */
+ ODATA_TYPE_MARKER: '$',
+
+ /**
+ * The value to set the maximum data service version header.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_DATA_SERVICE_VERSION: '3.0;NetFx',
+
+ /**
+ * The name of the property that stores the table name.
+ *
+ * @const
+ * @type {string}
+ */
+ TABLE_NAME: 'TableName',
+
+ /**
+ * The name of the special table used to store tables.
+ *
+ * @const
+ * @type {string}
+ */
+ TABLE_SERVICE_TABLE_NAME: 'Tables',
+
+ /**
+ * Operations.
+ *
+ * @const
+ * @enum {string}
+ */
+ Operations: {
+ RETRIEVE: 'RETRIEVE',
+ INSERT: 'INSERT',
+ REPLACE: 'REPLACE',
+ MERGE: 'MERGE',
+ DELETE: 'DELETE',
+ INSERT_OR_REPLACE: 'INSERT_OR_REPLACE',
+ INSERT_OR_MERGE: 'INSERT_OR_MERGE'
+ }
+ },
+
+ /**
+ * Defines constants for use with HTTP headers.
+ */
+ HeaderConstants: {
+ /**
+ * The accept ranges header.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCEPT_RANGES: 'accept_ranges',
+
+ /**
+ * The content transfer encoding header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_TRANSFER_ENCODING: 'content-transfer-encoding',
+
+ /**
+ * The transfer encoding header.
+ *
+ * @const
+ * @type {string}
+ */
+ TRANSFER_ENCODING: 'transfer-encoding',
+
+ /**
+ * The server header.
+ *
+ * @const
+ * @type {string}
+ */
+ SERVER: 'server',
+
+ /**
+ * The location header.
+ *
+ * @const
+ * @type {string}
+ */
+ LOCATION: 'location',
+
+ /**
+ * The Last-Modified header.
+ *
+ * @const
+ * @type {string}
+ */
+ LAST_MODIFIED: 'Last-Modified',
+
+ /**
+ * The creation time header.
+ *
+ * @const
+ * @type {string}
+ */
+ CREATION_TIME: 'x-ms-creation-time',
+
+ /**
+ * The data service version.
+ *
+ * @const
+ * @type {string}
+ */
+ DATA_SERVICE_VERSION: 'dataserviceversion',
+
+ /**
+ * The maximum data service version.
+ *
+ * @const
+ * @type {string}
+ */
+ MAX_DATA_SERVICE_VERSION: 'maxdataserviceversion',
+
+ /**
+ * The master Windows Azure Storage header prefix.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFIX_FOR_STORAGE: 'x-ms-',
+
+ /**
+ * The client request Id header.
+ *
+ * @const
+ * @type {string}
+ */
+ CLIENT_REQUEST_ID: 'x-ms-client-request-id',
+
+ /**
+ * The header that specifies the approximate message count of a queue.
+ *
+ * @const
+ * @type {string}
+ */
+ APPROXIMATE_MESSAGES_COUNT: 'x-ms-approximate-messages-count',
+
+ /**
+ * The Authorization header.
+ *
+ * @const
+ * @type {string}
+ */
+ AUTHORIZATION: 'authorization',
+
+ /**
+ * The header that is used to avoid browser cache.
+ *
+ * @const
+ * @type {string}
+ */
+ FORCE_NO_CACHE_IN_BROWSER: '_',
+
+ /**
+ * The header that specifies public access to blobs.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_PUBLIC_ACCESS: 'x-ms-blob-public-access',
+
+ /**
+ * The header that specifies container immutability policy.
+ *
+ * @const
+ * @type {boolean}
+ */
+ HAS_IMMUTABILITY_POLICY: 'x-ms-has-immutability-policy',
+
+ /**
+ * The header that specifies container has legal hold.
+ *
+ * @const
+ * @type {boolean}
+ */
+ HAS_LEGAL_HOLD: 'x-ms-has-legal-hold',
+
+ /**
+ * The header for the blob type.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_TYPE: 'x-ms-blob-type',
+
+ /**
+ * The header for the type.
+ *
+ * @const
+ * @type {string}
+ */
+ TYPE: 'x-ms-type',
+
+ /**
+ * Specifies the block blob type.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOCK_BLOB: 'blockblob',
+
+ /**
+ * The CacheControl header.
+ *
+ * @const
+ * @type {string}
+ */
+ CACHE_CONTROL: 'cache-control',
+
+ /**
+ * The header that specifies blob caching control.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CACHE_CONTROL: 'x-ms-blob-cache-control',
+
+ /**
+ * The header that specifies caching control.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CACHE_CONTROL: 'x-ms-cache-control',
+
+ /**
+ * The copy status.
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_STATUS: 'x-ms-copy-status',
+
+ /**
+ * The copy completion time
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_COMPLETION_TIME: 'x-ms-copy-completion-time',
+
+ /**
+ * The copy status message
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_STATUS_DESCRIPTION: 'x-ms-copy-status-description',
+
+ /**
+ * The copy identifier.
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_ID: 'x-ms-copy-id',
+
+ /**
+ * Progress of any copy operation
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_PROGRESS: 'x-ms-copy-progress',
+
+ /**
+ * The copy action.
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_ACTION: 'x-ms-copy-action',
+
+ /**
+ * Flag if the blob is incremental copy blob.
+ *
+ * @const
+ * @type {string}
+ */
+ INCREMENTAL_COPY: 'x-ms-incremental-copy',
+
+ /**
+ * Snapshot time of the last successful incremental copy snapshot for this blob.
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_DESTINATION_SNAPSHOT: 'x-ms-copy-destination-snapshot',
+
+ /**
+ * The ContentID header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_ID: 'content-id',
+
+ /**
+ * The ContentEncoding header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_ENCODING: 'content-encoding',
+
+ /**
+ * The header that specifies blob content encoding.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONTENT_ENCODING: 'x-ms-blob-content-encoding',
+
+ /**
+ * The header that specifies content encoding.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CONTENT_ENCODING: 'x-ms-content-encoding',
+
+ /**
+ * The ContentLangauge header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_LANGUAGE: 'content-language',
+
+ /**
+ * The header that specifies blob content language.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONTENT_LANGUAGE: 'x-ms-blob-content-language',
+
+ /**
+ * The header that specifies content language.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CONTENT_LANGUAGE: 'x-ms-content-language',
+
+ /**
+ * The ContentLength header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_LENGTH: 'content-length',
+
+ /**
+ * The header that specifies blob content length.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONTENT_LENGTH: 'x-ms-blob-content-length',
+
+ /**
+ * The header that specifies content length.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CONTENT_LENGTH: 'x-ms-content-length',
+
+ /**
+ * The ContentDisposition header.
+ * @const
+ * @type {string}
+ */
+ CONTENT_DISPOSITION: 'content-disposition',
+
+ /**
+ * The header that specifies blob content disposition.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONTENT_DISPOSITION: 'x-ms-blob-content-disposition',
+
+ /**
+ * The header that specifies content disposition.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CONTENT_DISPOSITION: 'x-ms-content-disposition',
+
+ /**
+ * The ContentMD5 header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_MD5: 'content-md5',
+
+ /**
+ * The header that specifies blob content MD5.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONTENT_MD5: 'x-ms-blob-content-md5',
+
+ /**
+ * The header that specifies content MD5.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CONTENT_MD5: 'x-ms-content-md5',
+
+ /**
+ * The ContentRange header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_RANGE: 'cache-range',
+
+ /**
+ * The ContentType header.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_TYPE: 'content-type',
+
+ /**
+ * The header that specifies blob content type.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONTENT_TYPE: 'x-ms-blob-content-type',
+
+ /**
+ * The header that specifies content type.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_CONTENT_TYPE: 'x-ms-content-type',
+
+ /**
+ * The header for copy source.
+ *
+ * @const
+ * @type {string}
+ */
+ COPY_SOURCE: 'x-ms-copy-source',
+
+ /**
+ * The header that specifies the date.
+ *
+ * @const
+ * @type {string}
+ */
+ DATE: 'date',
+
+ /**
+ * The header that specifies the date.
+ *
+ * @const
+ * @type {string}
+ */
+ MS_DATE: 'x-ms-date',
+
+ /**
+ * The header to delete snapshots.
+ *
+ * @const
+ * @type {string}
+ */
+ DELETE_SNAPSHOT: 'x-ms-delete-snapshots',
+
+ /**
+ * The ETag header.
+ *
+ * @const
+ * @type {string}
+ */
+ ETAG: 'etag',
+
+ /**
+ * The IfMatch header.
+ *
+ * @const
+ * @type {string}
+ */
+ IF_MATCH: 'if-match',
+
+ /**
+ * The IfModifiedSince header.
+ *
+ * @const
+ * @type {string}
+ */
+ IF_MODIFIED_SINCE: 'if-modified-since',
+
+ /**
+ * The IfNoneMatch header.
+ *
+ * @const
+ * @type {string}
+ */
+ IF_NONE_MATCH: 'if-none-match',
+
+ /**
+ * The IfUnmodifiedSince header.
+ *
+ * @const
+ * @type {string}
+ */
+ IF_UNMODIFIED_SINCE: 'if-unmodified-since',
+
+ /**
+ * Specifies snapshots are to be included.
+ *
+ * @const
+ * @type {string}
+ */
+ INCLUDE_SNAPSHOTS_VALUE: 'include',
+
+ /**
+ * Specifies that the content-type is JSON.
+ *
+ * @const
+ * @type {string}
+ */
+ JSON_CONTENT_TYPE_VALUE: 'application/json',
+
+ /**
+ * The header that specifies storage SKU, also known as account type.
+ *
+ * @const
+ * @type {string}
+ */
+ SKU_NAME: 'x-ms-sku-name',
+
+ /**
+ * The header that describes the flavour of the storage account, also known as account kind.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCOUNT_KIND: 'x-ms-account-kind',
+
+ /**
+ * The header that specifies lease ID.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_ID: 'x-ms-lease-id',
+
+ /**
+ * The header that specifies the lease break period.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_BREAK_PERIOD: 'x-ms-lease-break-period',
+
+ /**
+ * The header that specifies the proposed lease identifier.
+ *
+ * @const
+ * @type {string}
+ */
+ PROPOSED_LEASE_ID: 'x-ms-proposed-lease-id',
+
+ /**
+ * The header that specifies the lease duration.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_DURATION: 'x-ms-lease-duration',
+
+ /**
+ * The header that specifies the source lease ID.
+ *
+ * @const
+ * @type {string}
+ */
+ SOURCE_LEASE_ID: 'x-ms-source-lease-id',
+
+ /**
+ * The header that specifies lease time.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_TIME: 'x-ms-lease-time',
+
+ /**
+ * The header that specifies lease status.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_STATUS: 'x-ms-lease-status',
+
+ /**
+ * The header that specifies lease state.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_STATE: 'x-ms-lease-state',
+
+ /**
+ * Specifies the page blob type.
+ *
+ * @const
+ * @type {string}
+ */
+ PAGE_BLOB: 'PageBlob',
+
+ /**
+ * The header that specifies page write mode.
+ *
+ * @const
+ * @type {string}
+ */
+ PAGE_WRITE: 'x-ms-page-write',
+
+ /**
+ * The header that specifies file range write mode.
+ *
+ * @const
+ * @type {string}
+ */
+ FILE_WRITE: 'x-ms-write',
+
+ /**
+ * The header that specifies whether the response should include the inserted entity.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFER: 'Prefer',
+
+ /**
+ * The header value which specifies that the response should include the inserted entity.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFER_CONTENT: 'return-content',
+
+ /**
+ * The header value which specifies that the response should not include the inserted entity.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFER_NO_CONTENT: 'return-no-content',
+
+ /**
+ * The header prefix for metadata.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFIX_FOR_STORAGE_METADATA: 'x-ms-meta-',
+
+ /**
+ * The header prefix for properties.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFIX_FOR_STORAGE_PROPERTIES: 'x-ms-prop-',
+
+ /**
+ * The Range header.
+ *
+ * @const
+ * @type {string}
+ */
+ RANGE: 'Range',
+
+ /**
+ * The Source Range header.
+ *
+ * @const
+ * @type {string}
+ */
+ SOURCE_RANGE: 'x-ms-source-range',
+
+ /**
+ * The header that specifies if the request will populate the ContentMD5 header for range gets.
+ *
+ * @const
+ * @type {string}
+ */
+ RANGE_GET_CONTENT_MD5: 'x-ms-range-get-content-md5',
+
+ /**
+ * The format string for specifying ranges.
+ *
+ * @const
+ * @type {string}
+ */
+ RANGE_HEADER_FORMAT: 'bytes:%d-%d',
+
+ /**
+ * The header that indicates the request ID.
+ *
+ * @const
+ * @type {string}
+ */
+ REQUEST_ID: 'x-ms-request-id',
+
+ /**
+ * The header for specifying the sequence number.
+ *
+ * @const
+ * @type {string}
+ */
+ SEQUENCE_NUMBER: 'x-ms-blob-sequence-number',
+
+ /**
+ * The header for specifying the If-Sequence-Number-EQ condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SEQUENCE_NUMBER_EQUAL: 'x-ms-if-sequence-number-eq',
+
+ /**
+ * The header for specifying the If-Sequence-Number-LT condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SEQUENCE_NUMBER_LESS_THAN: 'x-ms-if-sequence-number-lt',
+
+ /**
+ * The header for specifying the If-Sequence-Number-LE condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SEQUENCE_NUMBER_LESS_THAN_OR_EQUAL: 'x-ms-if-sequence-number-le',
+
+ /**
+ * The header that specifies sequence number action.
+ *
+ * @const
+ * @type {string}
+ */
+ SEQUENCE_NUMBER_ACTION: 'x-ms-sequence-number-action',
+
+ /**
+ * The header for the blob content length.
+ *
+ * @const
+ * @type {string}
+ */
+ SIZE: 'x-ms-blob-content-length',
+
+ /**
+ * The header for snapshots.
+ *
+ * @const
+ * @type {string}
+ */
+ SNAPSHOT: 'x-ms-snapshot',
+
+ /**
+ * Specifies only snapshots are to be included.
+ *
+ * @const
+ * @type {string}
+ */
+ SNAPSHOTS_ONLY_VALUE: 'only',
+
+ /**
+ * The header for the If-Match condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SOURCE_IF_MATCH: 'x-ms-source-if-match',
+
+ /**
+ * The header for the If-Modified-Since condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SOURCE_IF_MODIFIED_SINCE: 'x-ms-source-if-modified-since',
+
+ /**
+ * The header for the If-None-Match condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SOURCE_IF_NONE_MATCH: 'x-ms-source-if-none-match',
+
+ /**
+ * The header for the If-Unmodified-Since condition.
+ *
+ * @const
+ * @type {string}
+ */
+ SOURCE_IF_UNMODIFIED_SINCE: 'x-ms-source-if-unmodified-since',
+
+ /**
+ * The header for data ranges.
+ *
+ * @const
+ * @type {string}
+ */
+ STORAGE_RANGE: 'x-ms-range',
+
+ /**
+ * The header for storage version.
+ *
+ * @const
+ * @type {string}
+ */
+ STORAGE_VERSION: 'x-ms-version',
+
+ /**
+ * The current storage version header value.
+ *
+ * @const
+ * @type {string}
+ */
+ TARGET_STORAGE_VERSION: '2018-03-28',
+
+ /**
+ * The UserAgent header.
+ *
+ * @const
+ * @type {string}
+ */
+ USER_AGENT: 'user-agent',
+
+ /**
+ * The pop receipt header.
+ *
+ * @const
+ * @type {string}
+ */
+ POP_RECEIPT: 'x-ms-popreceipt',
+
+ /**
+ * The time next visibile header.
+ *
+ * @const
+ * @type {string}
+ */
+ TIME_NEXT_VISIBLE: 'x-ms-time-next-visible',
+
+ /**
+ * The approximate message counter header.
+ *
+ * @const
+ * @type {string}
+ */
+ APPROXIMATE_MESSAGE_COUNT: 'x-ms-approximate-message-count',
+
+ /**
+ * The lease action header.
+ *
+ * @const
+ * @type {string}
+ */
+ LEASE_ACTION: 'x-ms-lease-action',
+
+ /**
+ * The accept header.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCEPT: 'accept',
+
+ /**
+ * The accept charset header.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCEPT_CHARSET: 'Accept-Charset',
+
+ /**
+ * The host header.
+ *
+ * @const
+ * @type {string}
+ */
+ HOST: 'host',
+
+ /**
+ * The correlation identifier header.
+ *
+ * @const
+ * @type {string}
+ */
+ CORRELATION_ID: 'x-ms-correlation-id',
+
+ /**
+ * The group identifier header.
+ *
+ * @const
+ * @type {string}
+ */
+ GROUP_ID: 'x-ms-group-id',
+
+ /**
+ * The share quota header.
+ *
+ * @const
+ * @type {string}
+ */
+ SHARE_QUOTA: 'x-ms-share-quota',
+
+ /**
+ * The max blob size header.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONDITION_MAX_SIZE: 'x-ms-blob-condition-maxsize',
+
+ /**
+ * The append blob position header.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_CONDITION_APPEND_POSITION: 'x-ms-blob-condition-appendpos',
+
+ /**
+ * The append blob append offset header.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_APPEND_OFFSET: 'x-ms-blob-append-offset',
+
+ /**
+ * The append blob committed block header.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOB_COMMITTED_BLOCK_COUNT: 'x-ms-blob-committed-block-count',
+
+ /**
+ * If the contents of the request have been successfully encrypted using the specified algorithm.
+ *
+ * @const
+ * @type {string}
+ */
+ REQUEST_SERVER_ENCRYPTED: 'x-ms-request-server-encrypted',
+
+ /**
+ * If the data and application metadata are completely encrypted using the specified algorithm.
+ *
+ * @const
+ * @type {string}
+ */
+ SERVER_ENCRYPTED: 'x-ms-server-encrypted',
+
+ /**
+ * Header indicates the resulting tier of the blob.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCESS_TIER: 'x-ms-access-tier',
+
+ /**
+ * This is the datetime of when the last time tier was changed on the blob.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCESS_TIER_CHANGE_TIME: 'x-ms-access-tier-change-time',
+
+ /**
+ * If the access tier is not explicitly set on the blob,
+ * the tier is inferred based on its content length
+ * and this header will be returned with true value.
+ *
+ * @const
+ * @type {string}
+ */
+ ACCESS_TIER_INFERRED: 'x-ms-access-tier-inferred',
+
+ /**
+ * For BlobStorage accounts, the header is returned if archive tier is set
+ * and rehydrate operation is pending for the request version is 2017-04-17 or later.
+ * The valid values are rehydrate-pending-to-hot or rehydrate-pending-to-cool.
+ *
+ * @const
+ * @type {string}
+ */
+ ARCHIVE_STATUS: 'x-ms-archive-status'
+ },
+
+ QueryStringConstants: {
+
+ /**
+ * Query component for SAS API version.
+ * @const
+ * @type {string}
+ */
+ API_VERSION: 'api-version',
+
+ /**
+ * The Comp value.
+ *
+ * @const
+ * @type {string}
+ */
+ COMP: 'comp',
+
+ /**
+ * The Res Type.
+ *
+ * @const
+ * @type {string}
+ */
+ RESTYPE: 'restype',
+
+ /**
+ * The copy Id.
+ * @const
+ * @type {string}
+ */
+ COPY_ID: 'copyid',
+
+ /**
+ * The snapshot value.
+ *
+ * @const
+ * @type {string}
+ */
+ SNAPSHOT: 'snapshot',
+
+ /**
+ * The share snapshot value.
+ *
+ * @const
+ * @type {string}
+ */
+ SHARE_SNAPSHOT: 'sharesnapshot',
+
+ /**
+ * The previous snapshot value.
+ *
+ * @const
+ * @type {string}
+ */
+ PREV_SNAPSHOT: 'prevsnapshot',
+
+ /**
+ * The timeout value.
+ *
+ * @const
+ * @type {string}
+ */
+ TIMEOUT: 'timeout',
+
+ /**
+ * The signed start time query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_START: 'st',
+
+ /**
+ * The signed expiry time query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_EXPIRY: 'se',
+
+ /**
+ * The signed resource query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_RESOURCE: 'sr',
+
+ /**
+ * The signed permissions query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_PERMISSIONS: 'sp',
+
+ /**
+ * The signed services query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_SERVICES: 'ss',
+
+ /**
+ * The signed resource types query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_RESOURCE_TYPES: 'srt',
+
+ /**
+ * The signed IP query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_IP: 'sip',
+
+ /**
+ * The signed protocol query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_PROTOCOL: 'spr',
+
+ /**
+ * The signed identifier query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_IDENTIFIER: 'si',
+
+ /**
+ * The signature query string argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNATURE: 'sig',
+
+ /**
+ * The signed version argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ SIGNED_VERSION: 'sv',
+
+ /**
+ * The cache control argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ CACHE_CONTROL: 'rscc',
+
+ /**
+ * The content type argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_TYPE: 'rsct',
+
+ /**
+ * The content encoding argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_ENCODING: 'rsce',
+
+ /**
+ * The content language argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_LANGUAGE: 'rscl',
+
+ /**
+ * The content disposition argument for shared access signature.
+ *
+ * @const
+ * @type {string}
+ */
+ CONTENT_DISPOSITION: 'rscd',
+
+ /**
+ * The block identifier query string argument for blob service.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOCK_ID: 'blockid',
+
+ /**
+ * The block list type query string argument for blob service.
+ *
+ * @const
+ * @type {string}
+ */
+ BLOCK_LIST_TYPE: 'blocklisttype',
+
+ /**
+ * The prefix query string argument for listing operations.
+ *
+ * @const
+ * @type {string}
+ */
+ PREFIX: 'prefix',
+
+ /**
+ * The marker query string argument for listing operations.
+ *
+ * @const
+ * @type {string}
+ */
+ MARKER: 'marker',
+
+ /**
+ * The maxresults query string argument for listing operations.
+ *
+ * @const
+ * @type {string}
+ */
+ MAX_RESULTS: 'maxresults',
+
+ /**
+ * The delimiter query string argument for listing operations.
+ *
+ * @const
+ * @type {string}
+ */
+ DELIMITER: 'delimiter',
+
+ /**
+ * The include query string argument for listing operations.
+ *
+ * @const
+ * @type {string}
+ */
+ INCLUDE: 'include',
+
+ /**
+ * The peekonly query string argument for queue service.
+ *
+ * @const
+ * @type {string}
+ */
+ PEEK_ONLY: 'peekonly',
+
+ /**
+ * The numofmessages query string argument for queue service.
+ *
+ * @const
+ * @type {string}
+ */
+ NUM_OF_MESSAGES: 'numofmessages',
+
+ /**
+ * The popreceipt query string argument for queue service.
+ *
+ * @const
+ * @type {string}
+ */
+ POP_RECEIPT: 'popreceipt',
+
+ /**
+ * The visibilitytimeout query string argument for queue service.
+ *
+ * @const
+ * @type {string}
+ */
+ VISIBILITY_TIMEOUT: 'visibilitytimeout',
+
+ /**
+ * The messagettl query string argument for queue service.
+ *
+ * @const
+ * @type {string}
+ */
+ MESSAGE_TTL: 'messagettl',
+
+ /**
+ * The select query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ SELECT: '$select',
+
+ /**
+ * The filter query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ FILTER: '$filter',
+
+ /**
+ * The top query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ TOP: '$top',
+
+ /**
+ * The skip query string argument.
+ *
+ * @const
+ * @type {string}
+ */
+ SKIP: '$skip',
+
+ /**
+ * The next partition key query string argument for table service.
+ *
+ * @const
+ * @type {string}
+ */
+ NEXT_PARTITION_KEY: 'NextPartitionKey',
+
+ /**
+ * The next row key query string argument for table service.
+ *
+ * @const
+ * @type {string}
+ */
+ NEXT_ROW_KEY: 'NextRowKey',
+
+ /**
+ * The lock identifier for service bus messages.
+ *
+ * @const
+ * @type {string}
+ */
+ LOCK_ID: 'lockid',
+
+ /**
+ * The table name for table SAS URI's.
+ *
+ * @const
+ * @type {string}
+ */
+ TABLENAME: 'tn',
+
+ /**
+ * The starting Partition Key for tableSAS URI's.
+ *
+ * @const
+ * @type {string}
+ */
+ STARTPK: 'spk',
+
+ /**
+ * The starting Partition Key for tableSAS URI's.
+ *
+ * @const
+ * @type {string}
+ */
+ STARTRK: 'srk',
+
+ /**
+ * The ending Partition Key for tableSAS URI's.
+ *
+ * @const
+ * @type {string}
+ */
+ ENDPK: 'epk',
+
+ /**
+ * The ending Partition Key for tableSAS URI's.
+ *
+ * @const
+ * @type {string}
+ */
+ ENDRK: 'erk'
+ },
+
+ StorageServiceClientConstants: {
+ /**
+ * The default protocol.
+ *
+ * @const
+ * @type {string}
+ */
+ DEFAULT_PROTOCOL: 'https:',
+
+ /*
+ * Used environment variables.
+ *
+ * @const
+ * @enum {string}
+ */
+ EnvironmentVariables: {
+ AZURE_STORAGE_ACCOUNT: 'AZURE_STORAGE_ACCOUNT',
+ AZURE_STORAGE_ACCESS_KEY: 'AZURE_STORAGE_ACCESS_KEY',
+ AZURE_STORAGE_DNS_SUFFIX: 'AZURE_STORAGE_DNS_SUFFIX',
+ AZURE_STORAGE_CONNECTION_STRING: 'AZURE_STORAGE_CONNECTION_STRING',
+ HTTP_PROXY: 'HTTP_PROXY',
+ HTTPS_PROXY: 'HTTPS_PROXY',
+ EMULATED: 'EMULATED'
+ },
+
+ /**
+ * Default credentials.
+ */
+ DEVSTORE_STORAGE_ACCOUNT: 'devstoreaccount1',
+ DEVSTORE_STORAGE_ACCESS_KEY: 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==',
+
+ /**
+ * The development store URI.
+ *
+ * @const
+ * @type {string}
+ */
+ DEV_STORE_URI: 'http://127.0.0.1',
+
+ /**
+ * Development ServiceClient URLs.
+ */
+ DEVSTORE_DEFAULT_PROTOCOL: 'http://',
+ DEVSTORE_BLOB_HOST: '127.0.0.1:10000',
+ DEVSTORE_QUEUE_HOST: '127.0.0.1:10001',
+ DEVSTORE_TABLE_HOST: '127.0.0.1:10002',
+
+ /**
+ * Production ServiceClient URLs.
+ */
+ CLOUD_BLOB_HOST: 'blob.' + storageDnsSuffix,
+ CLOUD_QUEUE_HOST: 'queue.' + storageDnsSuffix,
+ CLOUD_TABLE_HOST: 'table.' + storageDnsSuffix,
+ CLOUD_FILE_HOST: 'file.' + storageDnsSuffix
+ },
+
+ HttpConstants: {
+ /**
+ * Http Verbs
+ *
+ * @const
+ * @enum {string}
+ */
+ HttpVerbs: {
+ PUT: 'PUT',
+ GET: 'GET',
+ DELETE: 'DELETE',
+ POST: 'POST',
+ MERGE: 'MERGE',
+ HEAD: 'HEAD'
+ },
+
+ /**
+ * Response codes.
+ *
+ * @const
+ * @enum {int}
+ */
+ HttpResponseCodes: {
+ Ok: 200,
+ Created: 201,
+ Accepted: 202,
+ NoContent: 204,
+ PartialContent: 206,
+ BadRequest: 400,
+ Unauthorized: 401,
+ Forbidden: 403,
+ NotFound: 404,
+ Conflict: 409,
+ LengthRequired: 411,
+ PreconditionFailed: 412
+ }
+ },
+
+ CompatibleVersionConstants: {
+ /**
+ * Constant for the 2013-08-15 version.
+ *
+ * @const
+ * @type {string}
+ */
+ AUGUST_2013: '2013-08-15',
+
+ /**
+ * Constant for the 2012-02-12 version.
+ *
+ * @const
+ * @type {string}
+ */
+ FEBRUARY_2012: '2012-02-12'
+ },
+
+ BlobErrorCodeStrings: {
+ INVALID_BLOCK_ID: 'InvalidBlockId',
+ BLOB_NOT_FOUND: 'BlobNotFound',
+ BLOB_ALREADY_EXISTS: 'BlobAlreadyExists',
+ CONTAINER_ALREADY_EXISTS: 'ContainerAlreadyExists',
+ CONTAINER_NOT_FOUND: 'ContainerNotFound',
+ INVALID_BLOB_OR_BLOCK: 'InvalidBlobOrBlock',
+ INVALID_BLOCK_LIST: 'InvalidBlockList'
+ },
+
+ FileErrorCodeStrings: {
+ SHARE_ALREADY_EXISTS: 'ShareAlreadyExists',
+ SHARE_NOT_FOUND: 'ShareNotFound',
+ FILE_NOT_FOUND: 'FileNotFound'
+ },
+
+ QueueErrorCodeStrings: {
+ QUEUE_NOT_FOUND: 'QueueNotFound',
+ QUEUE_DISABLED: 'QueueDisabled',
+ QUEUE_ALREADY_EXISTS: 'QueueAlreadyExists',
+ QUEUE_NOT_EMPTY: 'QueueNotEmpty',
+ QUEUE_BEING_DELETED: 'QueueBeingDeleted',
+ POP_RECEIPT_MISMATCH: 'PopReceiptMismatch',
+ INVALID_PARAMETER: 'InvalidParameter',
+ MESSAGE_NOT_FOUND: 'MessageNotFound',
+ MESSAGE_TOO_LARGE: 'MessageTooLarge',
+ INVALID_MARKER: 'InvalidMarker'
+ },
+
+ /**
+ * Constants for storage error strings
+ *
+ * More details are at: http://msdn.microsoft.com/en-us/library/azure/dd179357.aspx
+ */
+ StorageErrorCodeStrings: {
+ // Not Modified (304): The condition specified in the conditional header(s) was not met for a read operation.
+ // Precondition Failed (412): The condition specified in the conditional header(s) was not met for a write operation.
+ CONDITION_NOT_MET: 'ConditionNotMet',
+ // Bad Request (400): A required HTTP header was not specified.
+ MISSING_REQUIRED_HEADER: 'MissingRequiredHeader',
+ // Bad Request (400): A required XML node was not specified in the request body.
+ MISSING_REQUIRED_XML_NODE: 'MissingRequiredXmlNode',
+ // Bad Request (400): One of the HTTP headers specified in the request is not supported.
+ UNSUPPORTED_HEADER: 'UnsupportedHeader',
+ // Bad Request (400): One of the XML nodes specified in the request body is not supported.
+ UNSUPPORTED_XML_NODE: 'UnsupportedXmlNode',
+ // Bad Request (400): The value provided for one of the HTTP headers was not in the correct format.
+ INVALID_HEADER_VALUE: 'InvalidHeaderValue',
+ // Bad Request (400): The value provided for one of the XML nodes in the request body was not in the correct format.
+ INVALID_XML_NODE_VALUE: 'InvalidXmlNodeValue',
+ // Bad Request (400): A required query parameter was not specified for this request.
+ MISSING_REQUIRED_QUERY_PARAMETER: 'MissingRequiredQueryParameter',
+ // Bad Request (400): One of the query parameters specified in the request URI is not supported.
+ UNSUPPORTED_QUERY_PARAMETER: 'UnsupportedQueryParameter',
+ // Bad Request (400): An invalid value was specified for one of the query parameters in the request URI.
+ INVALID_QUERY_PARAMETER_VALUE: 'InvalidQueryParameterValue',
+ // Bad Request (400): A query parameter specified in the request URI is outside the permissible range.
+ OUT_OF_RANGE_QUERY_PARAMETER_VALUE: 'OutOfRangeQueryParameterValue',
+ // Bad Request (400): The url in the request could not be parsed.
+ REQUEST_URL_FAILED_TO_PARSE: 'RequestUrlFailedToParse',
+ // Bad Request (400): The requested URI does not represent any resource on the server.
+ INVALID_URI: 'InvalidUri',
+ // Bad Request (400): The HTTP verb specified was not recognized by the server.
+ INVALID_HTTP_VERB: 'InvalidHttpVerb',
+ // Bad Request (400): The key for one of the metadata key-value pairs is empty.
+ EMPTY_METADATA_KEY: 'EmptyMetadataKey',
+ // Bad Request (400): The specified XML is not syntactically valid.
+ INVALID_XML_DOCUMENT: 'InvalidXmlDocument',
+ // Bad Request (400): The MD5 value specified in the request did not match the MD5 value calculated by the server.
+ MD5_MISMATCH: 'Md5Mismatch',
+ // Bad Request (400): The MD5 value specified in the request is invalid. The MD5 value must be 128 bits and Base64-encoded.
+ INVALID_MD5: 'InvalidMd5',
+ // Bad Request (400): One of the request inputs is out of range.
+ OUT_OF_RANGE_INPUT: 'OutOfRangeInput',
+ // Bad Request (400): The authentication information was not provided in the correct format. Verify the value of Authorization header.
+ INVALID_AUTHENTICATION_INFO: 'InvalidAuthenticationInfo',
+ // Bad Request (400): One of the request inputs is not valid.
+ INVALID_INPUT: 'InvalidInput',
+ // Bad Request (400): The specified metadata is invalid. It includes characters that are not permitted.
+ INVALID_METADATA: 'InvalidMetadata',
+ // Bad Request (400): The specifed resource name contains invalid characters.
+ INVALID_RESOURCE_NAME: 'InvalidResourceName',
+ // Bad Request (400): The size of the specified metadata exceeds the maximum size permitted.
+ METADATA_TOO_LARGE: 'MetadataTooLarge',
+ // Bad Request (400): Condition headers are not supported.
+ CONDITION_HEADER_NOT_SUPPORTED: 'ConditionHeadersNotSupported',
+ // Bad Request (400): Multiple condition headers are not supported.
+ MULTIPLE_CONDITION_HEADER_NOT_SUPPORTED: 'MultipleConditionHeadersNotSupported',
+ // Forbidden (403): Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature.
+ AUTHENTICATION_FAILED: 'AuthenticationFailed',
+ // Forbidden (403): Read-access geo-redundant replication is not enabled for the account.
+ // Forbidden (403): Write operations to the secondary location are not allowed.
+ // Forbidden (403): The account being accessed does not have sufficient permissions to execute this operation.
+ INSUFFICIENT_ACCOUNT_PERMISSIONS: 'InsufficientAccountPermissions',
+ // Not Found (404): The specified resource does not exist.
+ RESOURCE_NOT_FOUND: 'ResourceNotFound',
+ // Forbidden (403): The specified account is disabled.
+ ACCOUNT_IS_DISABLED: 'AccountIsDisabled',
+ // Method Not Allowed (405): The resource doesn't support the specified HTTP verb.
+ UNSUPPORTED_HTTP_VERB: 'UnsupportedHttpVerb',
+ // Conflict (409): The specified account already exists.
+ ACCOUNT_ALREADY_EXISTS: 'AccountAlreadyExists',
+ // Conflict (409): The specified account is in the process of being created.
+ ACCOUNT_BEING_CREATED: 'AccountBeingCreated',
+ // Conflict (409): The specified resource already exists.
+ RESOURCE_ALREADY_EXISTS: 'ResourceAlreadyExists',
+ // Conflict (409): The specified resource type does not match the type of the existing resource.
+ RESOURCE_TYPE_MISMATCH: 'ResourceTypeMismatch',
+ // Length Required (411): The Content-Length header was not specified.
+ MISSING_CONTENT_LENGTH_HEADER: 'MissingContentLengthHeader',
+ // Request Entity Too Large (413): The size of the request body exceeds the maximum size permitted.
+ REQUEST_BODY_TOO_LARGE: 'RequestBodyTooLarge',
+ // Requested Range Not Satisfiable (416): The range specified is invalid for the current size of the resource.
+ INVALID_RANGE: 'InvalidRange',
+ // Internal Server Error (500): The server encountered an internal error. Please retry the request.
+ INTERNAL_ERROR: 'InternalError',
+ // Internal Server Error (500): The operation could not be completed within the permitted time.
+ OPERATION_TIMED_OUT: 'OperationTimedOut',
+ // Service Unavailable (503): The server is currently unable to receive requests. Please retry your request.
+ SERVER_BUSY: 'ServerBusy',
+
+ // Legacy error code strings
+ UPDATE_CONDITION_NOT_SATISFIED: 'UpdateConditionNotSatisfied',
+ CONTAINER_NOT_FOUND: 'ContainerNotFound',
+ CONTAINER_ALREADY_EXISTS: 'ContainerAlreadyExists',
+ CONTAINER_DISABLED: 'ContainerDisabled',
+ CONTAINER_BEING_DELETED: 'ContainerBeingDeleted'
+ },
+
+ TableErrorCodeStrings: {
+ XMETHOD_NOT_USING_POST: 'XMethodNotUsingPost',
+ XMETHOD_INCORRECT_VALUE: 'XMethodIncorrectValue',
+ XMETHOD_INCORRECT_COUNT: 'XMethodIncorrectCount',
+ TABLE_HAS_NO_PROPERTIES: 'TableHasNoProperties',
+ DUPLICATE_PROPERTIES_SPECIFIED: 'DuplicatePropertiesSpecified',
+ TABLE_HAS_NO_SUCH_PROPERTY: 'TableHasNoSuchProperty',
+ DUPLICATE_KEY_PROPERTY_SPECIFIED: 'DuplicateKeyPropertySpecified',
+ TABLE_ALREADY_EXISTS: 'TableAlreadyExists',
+ TABLE_NOT_FOUND: 'TableNotFound',
+ ENTITY_NOT_FOUND: 'EntityNotFound',
+ ENTITY_ALREADY_EXISTS: 'EntityAlreadyExists',
+ PARTITION_KEY_NOT_SPECIFIED: 'PartitionKeyNotSpecified',
+ OPERATOR_INVALID: 'OperatorInvalid',
+ UPDATE_CONDITION_NOT_SATISFIED: 'UpdateConditionNotSatisfied',
+ PROPERTIES_NEED_VALUE: 'PropertiesNeedValue',
+ PARTITION_KEY_PROPERTY_CANNOT_BE_UPDATED: 'PartitionKeyPropertyCannotBeUpdated',
+ TOO_MANY_PROPERTIES: 'TooManyProperties',
+ ENTITY_TOO_LARGE: 'EntityTooLarge',
+ PROPERTY_VALUE_TOO_LARGE: 'PropertyValueTooLarge',
+ INVALID_VALUE_TYPE: 'InvalidValueType',
+ TABLE_BEING_DELETED: 'TableBeingDeleted',
+ TABLE_SERVER_OUT_OF_MEMORY: 'TableServerOutOfMemory',
+ PRIMARY_KEY_PROPERTY_IS_INVALID_TYPE: 'PrimaryKeyPropertyIsInvalidType',
+ PROPERTY_NAME_TOO_LONG: 'PropertyNameTooLong',
+ PROPERTY_NAME_INVALID: 'PropertyNameInvalid',
+ BATCH_OPERATION_NOT_SUPPORTED: 'BatchOperationNotSupported',
+ JSON_FORMAT_NOT_SUPPORTED: 'JsonFormatNotSupported',
+ METHOD_NOT_ALLOWED: 'MethodNotAllowed',
+ NOT_IMPLEMENTED: 'NotImplemented'
+ },
+
+ ConnectionStringKeys: {
+ USE_DEVELOPMENT_STORAGE_NAME: 'UseDevelopmentStorage',
+ DEVELOPMENT_STORAGE_PROXY_URI_NAME: 'DevelopmentStorageProxyUri',
+ DEFAULT_ENDPOINTS_PROTOCOL_NAME: 'DefaultEndpointsProtocol',
+ ACCOUNT_NAME_NAME: 'AccountName',
+ ACCOUNT_KEY_NAME: 'AccountKey',
+ BLOB_ENDPOINT_NAME: 'BlobEndpoint',
+ FILE_ENDPOINT_NAME: 'FileEndpoint',
+ QUEUE_ENDPOINT_NAME: 'QueueEndpoint',
+ TABLE_ENDPOINT_NAME: 'TableEndpoint',
+ SHARED_ACCESS_SIGNATURE_NAME: 'SharedAccessSignature',
+ ENDPOINT_SUFFIX_NAME: 'EndpointSuffix',
+ BLOB_BASE_DNS_NAME: 'blob.core.windows.net',
+ FILE_BASE_DNS_NAME: 'file.core.windows.net',
+ QUEUE_BASE_DNS_NAME: 'queue.core.windows.net',
+ TABLE_BASE_DNS_NAME: 'table.core.windows.net'
+ }
+};
+
+module.exports = Constants;
diff --git a/src/node_modules/azure-storage/lib/common/util/date.js b/src/node_modules/azure-storage/lib/common/util/date.js
new file mode 100644
index 0000000..8a9bb67
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/date.js
@@ -0,0 +1,69 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* Date/time related helper functions
+* @module date
+*
+*/
+
+/**
+* Generates a Date object which is in the given days from now.
+*
+* @param {int} days The days timespan.
+* @return {Date}
+*/
+exports.daysFromNow = function (days) {
+ var date = new Date();
+ date.setDate(date.getDate() + days);
+ return date;
+};
+
+/**
+* Generates a Date object which is in the given hours from now.
+*
+* @param {int} hours The hours timespan.
+* @return {Date}
+*/
+exports.hoursFromNow = function (hours) {
+ var date = new Date();
+ date.setHours(date.getHours() + hours);
+ return date;
+};
+
+/**
+* Generates a Date object which is in the given minutes from now.
+*
+* @param {int} minutes The minutes timespan.
+* @return {Date}
+*/
+exports.minutesFromNow = function (minutes) {
+ var date = new Date();
+ date.setMinutes(date.getMinutes() + minutes);
+ return date;
+};
+
+/**
+* Generates a Date object which is in the given seconds from now.
+*
+* @param {int} seconds The seconds timespan.
+* @return {Date}
+*/
+exports.secondsFromNow = function (seconds) {
+ var date = new Date();
+ date.setSeconds(date.getSeconds() + seconds);
+ return date;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/iso8061date.js b/src/node_modules/azure-storage/lib/common/util/iso8061date.js
new file mode 100644
index 0000000..62555aa
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/iso8061date.js
@@ -0,0 +1,66 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var rightPad = function (n, number) {
+ var currentN = '' + n;
+ while (currentN.length < number) {
+ currentN = currentN + '0';
+ }
+
+ return currentN;
+};
+
+/**
+* Formats a date into an iso 8061 string.
+*
+* @param {date} date The date to format.
+* @param {bool} skipMilliseconds Boolean value indicating if the miliseconds part of the date should not be included.
+* @param {integer} millisecondsPading Number of digits to left pad the miliseconds.
+* @return {string} The date formated in the ISO 8061 date format.
+*/
+exports.format = function (date) {
+ var dateString = date.toISOString();
+ return dateString.substring(0, dateString.length - 1) + '0000Z';
+};
+
+/**
+* Parses an ISO 8061 date string into a date object.
+*
+* @param {string} stringDateTime The string with the date to parse in the ISO 8061 format.
+* @return {date} The parsed date.
+*/
+exports.parse = function (stringDateTime) {
+ var parts = stringDateTime.split('T');
+ var ymd = parts[0].split('-');
+ var time = parts[1].split('.');
+ var hms = time[0].split(':');
+ var ms = 0;
+ if (time[1]) {
+ ms = time[1].split('Z');
+ }
+
+ var date = new Date(Date.UTC(
+ parseInt(ymd[0], 10),
+ parseInt(ymd[1], 10) - 1,
+ parseInt(ymd[2], 10),
+ parseInt(hms[0], 10),
+ parseInt(hms[1], 10),
+ parseInt(hms[2], 10),
+ Math.round(parseInt(rightPad(ms[0], 7), 10) / 10000)
+ ));
+
+ return date;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/patch-xmlbuilder.js b/src/node_modules/azure-storage/lib/common/util/patch-xmlbuilder.js
new file mode 100644
index 0000000..5a12049
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/patch-xmlbuilder.js
@@ -0,0 +1,32 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+'use strict';
+
+var XMLStringifier = require('xmlbuilder/lib/XMLStringifier');
+
+// Patch xmlbuilder to allow Unicode surrogate pair code
+// points in XML bodies
+
+XMLStringifier.prototype.assertLegalChar = function(str) {
+ var chars, chr;
+ chars = /[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uFFFE-\uFFFF]/;
+ chr = str.match(chars);
+ if (chr) {
+ throw new Error('Invalid character (' + chr + ') in string: ' + str);
+ }
+ return str;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/sr.js b/src/node_modules/azure-storage/lib/common/util/sr.js
new file mode 100644
index 0000000..1125b10
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/sr.js
@@ -0,0 +1,76 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+exports = module.exports;
+
+var SR = {
+ ANONYMOUS_ACCESS_BLOBSERVICE_ONLY: 'Anonymous access is only valid for the BlobService.',
+ ARGUMENT_NULL_OR_EMPTY: 'The argument must not be null or an empty string. Argument name: %s.',
+ ARGUMENT_NULL_OR_UNDEFINED: 'The argument must not be null or undefined. Argument name: %s.',
+ ARGUMENT_OUT_OF_RANGE_ERROR: 'The argument is out of range. Argument name: %s, Value passed: %s.',
+ BATCH_ONE_PARTITION_KEY: 'All entities in the batch must have the same PartitionKey value.',
+ BATCH_ONE_RETRIEVE: 'If a retrieve operation is part of a batch, it must be the only operation in the batch.',
+ BATCH_TOO_LARGE: 'Batches must not contain more than 100 operations.',
+ BLOB_INVALID_SEQUENCE_NUMBER: 'The sequence number may not be specified for an increment operation.',
+ BLOB_TYPE_MISMATCH: 'Blob type of the blob reference doesn\'t match blob type of the blob.',
+ CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY: 'Cannot create Shared Access Signature unless the Account Name and Key are used to create the ServiceClient.',
+ CONTENT_LENGTH_MISMATCH: 'An incorrect number of bytes was read from the connection. The connection may have been closed.',
+ CONTENT_TYPE_MISSING: 'Content-Type response header is missing or invalid.',
+ EMPTY_BATCH: 'Batch must not be empty.',
+ EXCEEDED_SIZE_LIMITATION: 'Upload exceeds the size limitation. Max size is %s but the current size is %s',
+ HASH_MISMATCH: 'Hash mismatch (integrity check failed), Expected value is %s, retrieved %s.',
+ INCORRECT_ENTITY_KEYS: 'PartitionKey and RowKey must be specified as strings in the entity object.',
+ INVALID_BLOB_LENGTH: 'createBlockBlobFromText requires the size of text to be less than 64MB. Please use createBlockBlobFromLocalFile or createBlockBlobFromStream to upload large blobs.',
+ INVALID_CONNECTION_STRING: 'Connection strings must be of the form "key1=value1;key2=value2".',
+ INVALID_CONNECTION_STRING_BAD_KEY: 'Connection string contains unrecognized key: "%s"',
+ INVALID_CONNECTION_STRING_DUPLICATE_KEY: 'Connection string contains duplicate key: "%s"',
+ INVALID_CONNECTION_STRING_EMPTY_KEY: 'Connection strings must not contain empty keys.',
+ INVALID_DELETE_SNAPSHOT_OPTION: 'The deleteSnapshots option cannot be included when deleting a specific snapshot using the snapshotId option.',
+ INVALID_EDM_TYPE: 'The value \'%s\' does not match the type \'%s\'.',
+ INVALID_FILE_LENGTH: 'createFileFromText requires the size of text to be less than 4MB. Please use createFileFromLocalFile or createFileFromStream to upload large files.',
+ INVALID_FILE_RANGE_FOR_UPDATE: 'Range size should be less than 4MB for a file range update operation.',
+ INVALID_HEADERS: 'Headers are not supported in the 2012-02-12 version.',
+ INVALID_MESSAGE_ID: 'Message ID cannot be null or undefined for deleteMessage and updateMessage operations.',
+ INVALID_PAGE_BLOB_LENGTH: 'Page blob length must be multiple of 512.',
+ INVALID_PAGE_END_OFFSET: 'Page end offset must be multiple of 512.',
+ INVALID_PAGE_RANGE_FOR_UPDATE: 'Page range size should be less than 4MB for a page update operation.',
+ INVALID_PAGE_START_OFFSET: 'Page start offset must be multiple of 512.',
+ INVALID_POP_RECEIPT: 'Pop Receipt cannot be null or undefined for deleteMessage and updateMessage operations.',
+ INVALID_PROPERTY_RESOLVER: 'The specified property resolver returned an invalid type. %s:{_:%s,$:%s }',
+ INVALID_RANGE_FOR_MD5: 'The requested range should be less than 4MB when contentMD5 is expected from the server',
+ INVALID_SAS_VERSION: 'SAS Version ? is invalid. Valid versions include: ?.',
+ INVALID_SAS_TOKEN: 'The SAS token should not contain api-version.',
+ INVALID_SIGNED_IDENTIFIERS: 'Signed identifiers need to be a hash object with key as the id and the value as the access policy.',
+ INVALID_STREAM_LENGTH: 'The length of the provided stream is invalid.',
+ INVALID_STRING_ERROR: 'Invalid string error.',
+ INVALID_TABLE_OPERATION: 'Operation not found: %s',
+ INVALID_TEXT_LENGTH: 'The length of the provided text is invalid.',
+ MAXIMUM_EXECUTION_TIMEOUT_EXCEPTION: 'The client could not finish the operation within specified maximum execution timeout.',
+ MD5_NOT_POSSIBLE: 'MD5 cannot be calculated for an existing blob because it would require reading the existing data. Please disable storeBlobContentMD5.',
+ MD5_NOT_PRESENT_ERROR: 'MD5 does not exist. If you do not want to force validation, please disable useTransactionalMD5.',
+ METADATA_KEY_INVALID: 'The key for one of the metadata key-value pairs is null, empty, or whitespace.',
+ METADATA_VALUE_INVALID: 'The value for one of the metadata key-value pairs is null, empty, or whitespace.',
+ NO_CREDENTIALS_PROVIDED: 'Credentials must be provided when creating a service client.',
+ PRIMARY_ONLY_COMMAND: 'This operation can only be executed against the primary storage location.',
+ QUERY_OPERATOR_REQUIRES_WHERE: '%s operator needs to be used after where.',
+ SECONDARY_ONLY_COMMAND: 'This operation can only be executed against the secondary storage location.',
+ STORAGE_HOST_LOCATION_REQUIRED: 'The host for the storage service must be specified.',
+ STORAGE_HOST_MISSING_LOCATION: 'The host for the target storage location is not specified. Please consider changing the request\'s location mode.',
+ TYPE_NOT_SUPPORTED: 'Type not supported when sending data to the service: ',
+ MAX_BLOB_SIZE_CONDITION_NOT_MEET: 'Append block data should not exceed the maximum blob size condition value.',
+};
+
+module.exports = SR;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/storageutilities.js b/src/node_modules/azure-storage/lib/common/util/storageutilities.js
new file mode 100644
index 0000000..bc5d205
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/storageutilities.js
@@ -0,0 +1,42 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'StorageUtilities'.
+
+/**
+* Defines constants, enums, and utility functions for use with storage.
+* @namespace
+*/
+var StorageUtilities = {
+ /**
+ * Specifies the location mode used to decide which location the request should be sent to.
+ *
+ * @const
+ * @enum {number}
+ */
+ LocationMode: {
+ /** The primary location only */
+ PRIMARY_ONLY: 0,
+ /** The primary location first, then the secondary */
+ PRIMARY_THEN_SECONDARY: 1,
+ /** The secondary location only */
+ SECONDARY_ONLY: 2,
+ /** The secondary location first, then the primary */
+ SECONDARY_THEN_PRIMARY: 3
+ }
+};
+
+module.exports = StorageUtilities;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/util.js b/src/node_modules/azure-storage/lib/common/util/util.js
new file mode 100644
index 0000000..17ec192
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/util.js
@@ -0,0 +1,618 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var _ = require('underscore');
+var util = require('util');
+var url = require('url');
+var stream = require('stream');
+var Constants = require('./constants');
+var Md5Wrapper = require('../md5-wrapper');
+var StorageUtilities = require('./storageutilities');
+var SR = require('./sr');
+
+/**
+* Trim the default port in the url.
+*
+* @param {string} uri The URI to be encoded.
+* @return {string} The URI without defualt port.
+*/
+exports.trimPortFromUri = function (uri) {
+ var uri = url.parse(uri);
+ if ((uri.protocol === Constants.HTTPS && uri.port == Constants.DEFAULT_HTTPS_PORT) || (uri.protocol === Constants.HTTP && uri.port == Constants.DEFAULT_HTTP_PORT)) {
+ uri.host = uri.hostname;
+ }
+ return url.format(uri);
+};
+
+/**
+* Returns the number of keys (properties) in an object.
+*
+* @param {object} value The object which keys are to be counted.
+* @return {number} The number of keys in the object.
+*/
+exports.objectKeysLength = function (value) {
+ if (!value) {
+ return 0;
+ }
+
+ return _.keys(value).length;
+};
+
+/**
+* Checks if in a browser environment.
+*
+* @return {bool} True if in a browser environment, false otherwise.
+*/
+exports.isBrowser = function () {
+ return typeof window !== 'undefined';
+};
+
+/**
+* Checks if in IE.
+*
+* @return {bool} True if in IE, false otherwise.
+*/
+exports.isIE = function () {
+ if (!exports.isBrowser()) {
+ return false;
+ }
+
+ var ua = window.navigator.userAgent;
+ var msie = ua.indexOf('MSIE ');
+ var trident = ua.indexOf('Trident/');
+ return msie > 0 || trident > 0;
+};
+
+/**
+* Checks if in a 32bit Node.js environment.
+*
+* @return {bool} True if in a 32bit Node.js environment, false otherwise.
+*/
+exports.is32 = function () {
+ return !exports.isBrowser() && process.arch === 'ia32';
+};
+
+/**
+* Checks if a value is null or undefined.
+*
+* @param {object} value The value to check for null or undefined.
+* @return {bool} True if the value is null or undefined, false otherwise.
+*/
+exports.objectIsNull = function (value) {
+ return _.isNull(value) || _.isUndefined(value);
+};
+
+/**
+* Checks if an object is empty.
+*
+* @param {object} object The object to check if it is null.
+* @return {bool} True if the object is empty, false otherwise.
+*/
+exports.objectIsEmpty = function (object) {
+ return _.isEmpty(object);
+};
+
+/**
+* Determines if an object contains an integer number.
+*
+* @param {object} value The object to assert.
+* @return {bool} True if the object contains an integer number; false otherwise.
+*/
+exports.objectIsInt = function (value) {
+ return typeof value === 'number' && parseFloat(value) == parseInt(value, 10) && !isNaN(value);
+};
+
+/**
+* Determines if an object is a NaN.
+*
+* @param {object} value The object to assert.
+* @return {bool} True if the object is a NaN; false otherwise.
+*/
+exports.objectIsNaN = function (value) {
+ return typeof(value) === 'number' && isNaN(value);
+};
+
+/**
+* Checks if an object is a string.
+*
+* @param {object} object The object to check if it is a string.
+* @return {bool} True if the object is a string, false otherwise.
+*/
+exports.objectIsString = function (object) {
+ return _.isString(object);
+};
+
+/**
+* Check if an object is a function
+* @param {object} object The object to check whether it is function
+* @return {bool} True if the specified object is function, otherwise false
+*/
+exports.objectIsFunction = function (object) {
+ return _.isFunction(object);
+};
+
+
+/**
+* Front zero padding of string to sepcified length
+*/
+exports.zeroPaddingString = function(str, len) {
+ var paddingStr = '0000000000' + str;
+ if(paddingStr.length < len) {
+ return exports.zeroPaddingString(paddingStr, len);
+ } else {
+ return paddingStr.substr(-1 * len);
+ }
+};
+
+/**
+* Checks if a value is an empty string, null or undefined.
+*
+* @param {object} value The value to check for an empty string, null or undefined.
+* @return {bool} True if the value is an empty string, null or undefined, false otherwise.
+*/
+exports.stringIsEmpty = function (value) {
+ return _.isNull(value) || _.isUndefined(value) || value === '';
+};
+
+/**
+* Checks if a value is null, empty, undefined or consists only of white-space characters.
+*
+* @param {object} value The value to check for null, empty, undefined and white-space only characters.
+* @return {bool} True if the value is an empty string, null, undefined, or consists only of white-space characters, false otherwise.
+*/
+exports.IsNullOrEmptyOrUndefinedOrWhiteSpace = function (value) {
+ if(_.isNull(value) || _.isUndefined(value) || value === '') {
+ return true;
+ }
+
+ if(_.isString(value) && value.trim().length === 0) {
+ return true;
+ }
+
+ return false;
+};
+
+/**
+* Formats a text replacing '?' by the arguments.
+*
+* @param {string} text The string where the ? should be replaced.
+* @param {array} arguments Value(s) to insert in question mark (?) parameters.
+* @return {string}
+*/
+exports.stringFormat = function (text) {
+ if (arguments.length > 1) {
+ for (var i = 1; text.indexOf('?') !== -1; i++) {
+ text = text.replace('?', arguments[i]);
+ }
+ }
+
+ return text;
+};
+
+/**
+* Determines if a string starts with another.
+*
+* @param {string} text The string to assert.
+* @param {string} prefix The string prefix.
+* @return {Bool} True if the string starts with the prefix; false otherwise.
+*/
+exports.stringStartsWith = function (text, prefix) {
+ if (_.isNull(prefix)) {
+ return true;
+ }
+
+ return text.substr(0, prefix.length) === prefix;
+};
+
+/**
+* Determines if a string ends with another.
+*
+* @param {string} text The string to assert.
+* @param {string} suffix The string suffix.
+* @return {Bool} True if the string ends with the suffix; false otherwise.
+*/
+exports.stringEndsWith = function (text, suffix) {
+ if (_.isNull(suffix)) {
+ return true;
+ }
+
+ return text.substr(text.length - suffix.length) === suffix;
+};
+
+/**
+* Removes the BOM from a string.
+*
+* @param {string} str The string from where the BOM is to be removed
+* @return {string} The string without the BOM.
+*/
+exports.removeBOM = function (str) {
+ if (str.charCodeAt(0) === 0xfeff || str.charCodeAt(0) === 0xffef) {
+ str = str.substring(1);
+ }
+
+ return str;
+};
+
+/**
+* Merges multiple objects.
+*
+* @param {object} object The objects to be merged
+* @return {object} The merged object.
+*/
+exports.merge = function () {
+ return _.extend.apply(this, arguments);
+};
+
+/**
+* Checks if a value exists in an array. The comparison is done in a case
+* insensitive manner.
+*
+* @param {string} needle The searched value.
+* @param {array} haystack The array.
+*
+* @static
+*
+* @return {boolean}
+*/
+exports.inArrayInsensitive = function (needle, haystack) {
+ return _.contains(_.map(haystack, function (h) { return h.toLowerCase(); }), needle.toLowerCase());
+};
+
+/**
+* Returns the specified value of the key passed from object and in case that
+* this key doesn't exist, the default value is returned. The key matching is
+* done in a case insensitive manner.
+*
+* @param {string} key The array key.
+* @param {object} haystack The object to be used.
+* @param {mix} default The value to return if $key is not found in $array.
+*
+* @static
+*
+* @return mix
+*/
+exports.tryGetValueInsensitive = function (key, haystack, defaultValue) {
+ if (haystack) {
+ for (var i in haystack) {
+ if (haystack.hasOwnProperty(i) && i.toString().toLowerCase() === key.toString().toLowerCase()) {
+ return haystack[i];
+ }
+ }
+ }
+
+ return defaultValue;
+};
+
+/**
+* Returns the value in a chained object.
+*
+* @param {object} object The object with the values.
+* @param {array} keys The keys.
+* @param {mix} default The value to return if $key is not found in $array.
+*
+* @static
+*
+* @return mix
+*/
+exports.tryGetValueChain = function (object, keys, defaultValue) {
+ if (keys.length === 0) {
+ return object;
+ }
+
+ var currentKey = keys.shift();
+ if (object && object[currentKey] !== undefined) {
+ return exports.tryGetValueChain(object[currentKey], keys, defaultValue);
+ }
+
+ return defaultValue;
+};
+
+/**
+* Set the value of an inner property of an object.
+*
+* @param {object} object The target object.
+* @param {array} keys The property chain keys.
+* @param {mix} object The value to be set.
+*
+* @static
+
+* @example
+* // Set targetObject.propA.propB to 'testValue'
+* var targetObject = {};
+* util.setObjectInnerPropertyValue(targetObject, ['propA', 'propB'], 'testValue');
+*/
+exports.setObjectInnerPropertyValue = function(object, propertyChainKeys, value){
+ if(!object || propertyChainKeys.length < 1) {
+ return;
+ }
+
+ var currentKey = propertyChainKeys.shift();
+ if(propertyChainKeys.length === 0) {
+ object[currentKey] = value;
+ return;
+ }
+
+ if (!object[currentKey]) {
+ object[currentKey] = {};
+ }
+
+ exports.setObjectInnerPropertyValue(object[currentKey], propertyChainKeys, value);
+};
+
+/**
+* Rounds a date off to seconds.
+*
+* @param {Date} a date
+* @return {string} the date in ISO8061 format, with no milliseconds component
+*/
+exports.truncatedISO8061Date = function (date) {
+ var dateString = date.toISOString();
+ return dateString.substring(0, dateString.length - 5) + 'Z';
+};
+
+exports.normalizeArgs = function (optionsOrCallback, callback, result) {
+ var options = {};
+ if(_.isFunction(optionsOrCallback) && !callback) {
+ callback = optionsOrCallback;
+ } else if (optionsOrCallback) {
+ options = optionsOrCallback;
+ }
+
+ result(options, callback);
+};
+
+exports.getNodeVersion = function () {
+ var parsedVersion = process.version.split('.');
+ return {
+ major: parseInt(parsedVersion[0].substr(1), 10),
+ minor: parseInt(parsedVersion[1], 10),
+ patch: parseInt(parsedVersion[2], 10)
+ };
+};
+
+/**
+* Calculate md5sum for the stream
+* @ignore
+*/
+exports.calculateMD5 = function(readStream, bufferLength, options, callback) {
+ var internalBuff = Buffer.alloc(bufferLength);
+ var index = 0;
+ var internalHash = new Md5Wrapper().createMd5Hash();
+ readStream.on('data', function(data) {
+ if (index + data.length > bufferLength) {
+ var copyLength = bufferLength - index;
+ if (copyLength > 0) {
+ data = data.slice(0, copyLength);
+ data.copy(internalBuff, index);
+ internalHash.update(data);
+ index += copyLength;
+ }
+ readStream.emit('end');
+ } else {
+ data.copy(internalBuff, index);
+ internalHash.update(data);
+ index += data.length;
+ }
+ }).on('end', function() {
+ if (!readStream.endEmitted) {
+ internalBuff = internalBuff.slice(0, index);
+ var contentMD5 = internalHash.digest('base64');
+ // Set the flag to be compatible with Nodejs 0.10 which will keep emitting data from
+ // the file stream when the read stream has emitted the end event from its listner.
+ readStream.endEmitted = true;
+ callback(internalBuff, contentMD5);
+ }
+ });
+};
+
+/**
+* Whether the content of buffer is all zero
+*/
+exports.isBufferAllZero = function (buffer) {
+ for(var i = 0, len = buffer.length; i < len; i++) {
+ if (buffer[i] !== 0) {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+* Write zero to stream
+*/
+var zeroBuffer = null;
+exports.writeZerosToStream = function (stream, length, md5Hash, progressCallback, callback) {
+ var defaultBufferSize = Constants.BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+ var bufferSize = Math.min(defaultBufferSize, length);
+ var remaining = length - bufferSize;
+ var buffer = null;
+ if (bufferSize == defaultBufferSize) {
+ if (!zeroBuffer) {
+ zeroBuffer = Buffer.alloc(defaultBufferSize);
+ zeroBuffer.fill(0);
+ }
+ buffer = zeroBuffer;
+ } else {
+ buffer = Buffer.alloc(bufferSize);
+ buffer.fill(0);
+ }
+ if (md5Hash) {
+ md5Hash.update(buffer);
+ }
+ //We can only write the entire buffer to stream instead of part of buffer.
+ return stream.write(buffer, function () {
+ if (exports.objectIsFunction(progressCallback)) {
+ progressCallback(null, buffer.length);
+ }
+ buffer = null;
+ if (remaining > 0) {
+ exports.writeZerosToStream(stream, remaining, md5Hash, progressCallback, callback);
+ } else if (exports.objectIsFunction(callback)) {
+ callback(null, null);
+ }
+ });
+};
+
+/**
+* Calculate md5sum for the content
+*/
+exports.getContentMd5 = function (content, encoding) {
+ if (!encoding) encoding = 'base64';
+ var internalHash = new Md5Wrapper().createMd5Hash();
+ internalHash.update(content, 'utf8');
+ return internalHash.digest(encoding);
+};
+
+exports.getNextLocation = function(lastLocation, locationMode) {
+ switch(locationMode) {
+ case StorageUtilities.LocationMode.PRIMARY_ONLY:
+ return Constants.StorageLocation.PRIMARY;
+ case StorageUtilities.LocationMode.SECONDARY_ONLY:
+ return Constants.StorageLocation.SECONDARY;
+ case StorageUtilities.LocationMode.PRIMARY_THEN_SECONDARY:
+ case StorageUtilities.LocationMode.SECONDARY_THEN_PRIMARY:
+ return (lastLocation === Constants.StorageLocation.PRIMARY) ? Constants.StorageLocation.SECONDARY : Constants.StorageLocation.PRIMARY;
+ default:
+ throw new RangeError(util.format(SR.ARGUMENT_OUT_OF_RANGE_ERROR, 'locationMode', locationMode));
+ }
+};
+
+exports.getNextListingLocationMode = function (token) {
+ if(_.isNull(token) || _.isUndefined(token)) {
+ return Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }
+ else {
+ switch (token.targetLocation) {
+ case Constants.StorageLocation.PRIMARY:
+ return Constants.RequestLocationMode.PRIMARY_ONLY;
+ case Constants.StorageLocation.SECONDARY:
+ return Constants.RequestLocationMode.SECONDARY_ONLY;
+ default:
+ throw new RangeError(util.format(SR.ARGUMENT_OUT_OF_RANGE_ERROR, 'targetLocation', token.targetLocation));
+ }
+ }
+};
+
+exports.isStreamPaused = function (object) {
+ if (object instanceof stream) {
+ return object._paused === true || (object._readableState && object._readableState.flowing === false);
+ }
+ return false;
+};
+
+/**
+* Parse copy progress string in the format of bytesCopied/totalBytes
+*/
+exports.parseCopyProgress = function (progress) {
+ if (typeof progress != 'string' || progress.indexOf('/') === -1) {
+ return {};
+ }
+
+ var progressInfo = progress.split('/');
+ return { bytesCopied: progressInfo[0], totalBytes: progressInfo[1] };
+};
+
+/**
+* The list of the properties should be normalized with explicit mapping
+*/
+var normalizePropertyNameExceptionList = {
+ 'x-ms-blob-sequence-number': 'sequenceNumber',
+ 'content-Type': 'contentSettings.contentType',
+ 'content-Encoding': 'contentSettings.contentEncoding',
+ 'content-Language': 'contentSettings.contentLanguage',
+ 'cache-Control': 'contentSettings.cacheControl',
+ 'content-Disposition': 'contentSettings.contentDisposition',
+ 'content-MD5': 'contentSettings.contentMD5',
+ 'leaseId': 'lease.id',
+ 'leaseStatus': 'lease.status',
+ 'leaseDuration': 'lease.duration',
+ 'leaseState': 'lease.state',
+ 'copyId': 'copy.id',
+ 'copyStatus': 'copy.status',
+ 'copySource': 'copy.source',
+ 'copyProgress': 'copy.progress',
+ 'copyCompletionTime': 'copy.completionTime',
+ 'copyStatusDescription': 'copy.statusDescription',
+ 'copyDestinationSnapshot': 'copy.destinationSnapshot',
+ 'publicAccess': 'publicAccessLevel',
+ 'incrementalCopy': 'isIncrementalCopy'
+};
+
+/**
+* Normalize the property name from XML to keep consistent with
+* the name defined in the property headers
+*/
+exports.normalizePropertyNameFromXML = function (propertyName) {
+ if (this.IsNullOrEmptyOrUndefinedOrWhiteSpace(propertyName)) {
+ return '';
+ }
+
+ propertyName = propertyName.trim();
+ propertyName = propertyName[0].toLowerCase() + propertyName.substring(1);
+ // So far the cases are:
+ // for the 'last-modified' property in listing resources
+ // for the 'content-*' properties in listing resources
+ // for the 'cache-control' property in listing blobs
+ // for the 'x-ms-blob-sequence-number' in listing blobs
+ if (propertyName in normalizePropertyNameExceptionList) {
+ return normalizePropertyNameExceptionList[propertyName];
+ } else if (propertyName.toLowerCase().indexOf('-') != -1) {
+ return propertyName.replace('-', '');
+ } else {
+ return propertyName;
+ }
+};
+
+/**
+* Set the property value from XML
+*/
+exports.setPropertyValueFromXML = function (result, xmlNode, toNormalize) {
+ for (var subPropertyName in xmlNode) {
+ if (xmlNode.hasOwnProperty(subPropertyName)) {
+ if (toNormalize) {
+ var propertyChain = this.normalizePropertyNameFromXML(subPropertyName).split('.');
+ exports.setObjectInnerPropertyValue(result, propertyChain, xmlNode[subPropertyName]);
+ } else {
+ result[subPropertyName.toLowerCase()] = xmlNode[subPropertyName];
+ }
+
+ if (subPropertyName.toLowerCase() === 'copyprogress') {
+ var info = this.parseCopyProgress(xmlNode[subPropertyName]);
+ exports.setObjectInnerPropertyValue(result, ['copy', 'bytesCopied'], parseInt(info.bytesCopied));
+ exports.setObjectInnerPropertyValue(result, ['copy', 'totalBytes'], parseInt(info.totalBytes));
+ }
+ }
+ }
+};
+
+/**
+ * Filter out non-reserved properties from options
+ */
+exports.filterOutNonReservedProperties = function (reserved, options) {
+ var nonReservedProperties = {};
+ if (options) {
+ for (var prop in options) {
+ if (options.hasOwnProperty(prop)) {
+ var isReserved = reserved.hasOwnProperty(prop);
+ var isFunction = typeof options[prop] === 'function';
+ if (!isReserved && !isFunction) {
+ nonReservedProperties[prop] = options[prop];
+ }
+ }
+ }
+ }
+ return nonReservedProperties;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/common/util/validate.js b/src/node_modules/azure-storage/lib/common/util/validate.js
new file mode 100644
index 0000000..25a0506
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/common/util/validate.js
@@ -0,0 +1,560 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var _ = require('underscore');
+var util = require('util');
+
+var constants = require('./../util/constants');
+var blobConstants = constants.BlobConstants;
+var BlobUtilities = require('./../../services/blob/blobutilities');
+var FileUtilities = require('./../../services/file/fileutilities');
+var azureutil = require('./util');
+var SR = require('./sr');
+var check = require('validator');
+var errors = require('../errors/errors');
+var ArgumentError = errors.ArgumentError;
+var ArgumentNullError = errors.ArgumentNullError;
+
+exports = module.exports;
+
+function initCallback(callbackParam, resultsCb) {
+ var fail;
+ if (callbackParam) {
+ fail = function (err) {
+ callbackParam(err);
+ return false;
+ };
+ } else {
+ fail = function (err) {
+ throw err;
+ };
+ callbackParam = function () {};
+ }
+
+ resultsCb(fail, callbackParam);
+}
+
+/**
+* Checks if the given value is a valid enumeration or not.
+*
+* @param {object} value The value to validate.
+* @param {object} list The enumeration values.
+* @return {boolean}
+*/
+exports.isValidEnumValue = function (value, list, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (!list.some(function (current) {
+ return current.toLowerCase() === value.toLowerCase();
+ })) {
+ return fail(new RangeError(util.format('Invalid value: %s. Options are: %s.', value, list)));
+ }
+
+ callback();
+ return true;
+};
+
+/**
+* Creates a anonymous function that check if the given uri is valid or not.
+*
+* @param {string} uri The uri to validate.
+* @return {boolean}
+*/
+exports.isValidUri = function (uri) {
+ if (!check.isURL(uri, { 'require_tld': false })){
+ throw new URIError('The provided URI "' + uri + '" is invalid.');
+ }
+ return true;
+};
+
+/**
+* Checks if the given host is valid or not.
+*
+* @param {string|object} host The host to validate.
+* @return {boolean}
+*/
+exports.isValidHost= function (host) {
+ if (azureutil.objectIsNull(host)) {
+ throw new ArgumentNullError('host', SR.STORAGE_HOST_LOCATION_REQUIRED);
+ } else {
+ var storageHost = {};
+ storageHost.primaryHost = _.isString(host) ? host : host.primaryHost;
+ if (storageHost.primaryHost && !check.isURL(storageHost.primaryHost, { 'require_tld': false })){
+ throw new URIError('The provided URI "' + storageHost.primaryHost + '" is invalid.');
+ }
+
+ storageHost.secondaryHost = _.isString(host) ? undefined : host.secondaryHost;
+ if (storageHost.secondaryHost && !check.isURL(storageHost.secondaryHost, { 'require_tld': false })){
+ throw new URIError('The provided URI "' + storageHost.secondaryHost + '" is invalid.');
+ }
+
+ if (!storageHost.primaryHost && !storageHost.secondaryHost) {
+ throw new ArgumentNullError('host', SR.STORAGE_HOST_LOCATION_REQUIRED);
+ }
+ }
+
+ return true;
+};
+
+/**
+* Checks if the given value is a valid UUID or not.
+*
+* @param {string|object} uuid The uuid to validate.
+* @return {boolean}
+*/
+exports.isValidUuid = function(uuid, callback) {
+ var validUuidRegex = /^[a-zA-Z0-9]{8}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{12}$/;
+
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (!validUuidRegex.test(uuid)) {
+ return fail(new SyntaxError('The value is not a valid UUID format.'));
+ }
+
+ callback();
+ return true;
+};
+
+/**
+* Creates a anonymous function that check if a given key is base 64 encoded.
+*
+* @param {string} key The key to validate.
+* @return {function}
+*/
+exports.isBase64Encoded = function (key) {
+ var isValidBase64String = key.match(/^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/);
+
+ if (isValidBase64String) {
+ return true;
+ } else {
+ throw new SyntaxError('The provided account key ' + key + ' is not a valid base64 string.');
+ }
+};
+
+/**
+* Validates a function.
+*
+* @param {object} function The function to validate.
+* @return {function}
+*/
+exports.isValidFunction = function (functionObject, functionName) {
+ if (!functionObject) {
+ throw new ArgumentNullError('functionObject', functionName + ' must be specified.');
+ }
+ if(!_.isFunction(functionObject)){
+ throw new TypeError(functionName + ' specified should be a function.');
+ }
+ return true;
+};
+
+var getNameError = function(name, typeName) {
+ // checks if name is null, undefined or empty
+ if (azureutil.stringIsEmpty(name)) {
+ return new ArgumentNullError('name', util.format('%s name must be a non empty string.', typeName));
+ }
+
+ // check if name is between 3 and 63 characters
+ if (name.length < 3 || name.length > 63) {
+ return new ArgumentError('name', util.format('%s name must be between 3 and 63 characters long.', typeName));
+ }
+
+ // check if name follows naming rules
+ if (name.match(/^([a-z0-9]+(-[a-z0-9]+)*)$/) === null) {
+ return new SyntaxError(util.format('%s name format is incorrect.', typeName));
+ }
+
+ return null;
+};
+
+/**
+* Validates a container name.
+*
+* @param {string} containerName The container name.
+*/
+exports.containerNameIsValid = function (containerName, callback) {
+ var fail;
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ var nameError = getNameError(containerName, 'Container');
+
+ if (!nameError || containerName.match(/^(\$root|\$logs|\$web)$/)) {
+ callback();
+ return true;
+ } else {
+ return fail(nameError);
+ }
+};
+
+/**
+* Validates a blob name.
+*
+* @param {string} containerName The container name.
+* @param {string} blobname The blob name.
+*/
+exports.blobNameIsValid = function (containerName, blobName, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (!blobName) {
+ return fail(new ArgumentNullError('blobName', 'Blob name is not specified.'));
+ }
+
+ if (containerName === '$root' && blobName.indexOf('/') !== -1) {
+ return fail(new SyntaxError('Blob name format is incorrect.'));
+ }
+
+ callback();
+ return true;
+};
+
+/**
+* Validates a blob tier name.
+*
+* @param {string} blobTier The blob tier name.
+*/
+exports.blobTierNameIsValid = function (blobTier, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (!blobTier) {
+ return fail(new ArgumentNullError('blobTier', 'Blob tier is not specified.'));
+ }
+
+ if (!_.chain(_.union(
+ _.values(BlobUtilities.BlobTier.PremiumPageBlobTier),
+ _.values(BlobUtilities.BlobTier.StandardBlobTier)
+ ))
+ .map(function (val) { return val.toString().toUpperCase(); })
+ .contains(blobTier.toString().toUpperCase())
+ .value()) {
+ return fail(new SyntaxError('Blob tier is incorrect. Refer to BlobUtilities.BlobTier for possible values.'));
+ }
+
+ callback();
+ return true;
+};
+
+/**
+* Validates a share name.
+*
+* @param {string} shareName The share name.
+*/
+exports.shareNameIsValid = function (shareName, callback) {
+ var fail;
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ var nameError = getNameError(shareName, 'Share');
+
+ if (!nameError) {
+ callback();
+ return true;
+ } else {
+ return fail(nameError);
+ }
+};
+
+/**
+* Validates a queue name.
+*
+* @param {string} queueName The queue name.
+*/
+exports.queueNameIsValid = function (queueName, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ var nameError = getNameError(queueName, 'Queue');
+
+ if (!nameError) {
+ callback();
+ return true;
+ } else {
+ return fail(nameError);
+ }
+};
+
+/**
+* Validates a table name.
+*
+* @param {string} table The table name.
+*/
+exports.tableNameIsValid = function (table, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (azureutil.stringIsEmpty(table)) {
+ return fail(new ArgumentNullError('table', 'Table name must be a non empty string.'));
+ }
+
+ if (table.length < 3 || table.length > 63) {
+ return fail(new ArgumentError('table', 'Table name must be between 3 and 63 characters long.'));
+ }
+
+ if(table.toLowerCase() === 'tables') {
+ return fail(new RangeError('Table name cannot be \'Tables\'.'));
+ }
+
+ if (table.match(/^([A-Za-z][A-Za-z0-9]{2,62})$/) !== null || table === '$MetricsCapacityBlob' || table.match(/^(\$Metrics(HourPrimary|MinutePrimary|HourSecondary|MinuteSecondary)?(Transactions)(Blob|Queue|Table|File))$/) !== null)
+ {
+ callback();
+ return true;
+ } else {
+ return fail(new SyntaxError('Table name format is incorrect.'));
+ }
+};
+
+/**
+* Validates an HTML File object.
+*
+* @param {File} browserFile The HTML File object.
+*/
+exports.browserFileIsValid = function (browserFile, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ // IE doesn't support File.constructor.name
+ if (!azureutil.isBrowser() ||
+ !browserFile ||
+ !browserFile.constructor ||
+ (!azureutil.isIE() && !browserFile.constructor.name) ||
+ (!azureutil.isIE() && browserFile.constructor.name !== 'File' && browserFile.constructor.name !== 'Blob') ||
+ !azureutil.objectIsInt(browserFile.size)) {
+ return fail(new ArgumentError('type', 'Invalid HTML File object.'));
+ } else {
+ callback();
+ return true;
+ }
+};
+
+/**
+* Validates page ranges.
+*
+* @param {int} rangeStart The range starting position.
+* @param {int} rangeEnd The range ending position.
+* @param {int} writeBlockSizeInBytes The block size.
+*/
+exports.pageRangesAreValid = function (rangeStart, rangeEnd, writeBlockSizeInBytes, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (rangeStart % 512 !== 0) {
+ return fail(new RangeError('Start byte offset must be a multiple of 512.'));
+ }
+
+ var size = null;
+ if (!azureutil.objectIsNull(rangeEnd)) {
+ if ((rangeEnd + 1) % 512 !== 0) {
+ return fail(new RangeError('End byte offset must be a multiple of 512 minus 1.'));
+ }
+
+ size = (rangeEnd - rangeStart) + 1;
+ if (size > writeBlockSizeInBytes) {
+ return fail(new RangeError('Page blob size cannot be larger than ' + writeBlockSizeInBytes + ' bytes.'));
+ }
+ }
+
+ callback();
+ return true;
+};
+
+/**
+* Validates a blob type.
+*
+* @param {string} type The type name.
+*/
+exports.blobTypeIsValid = function (type, callback) {
+ var getEnumValues = function (obj) {
+ var values = [];
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ values.push(obj[prop]);
+ }
+ }
+ return values;
+ };
+
+ return this.isValidEnumValue(type, getEnumValues(blobConstants.BlobTypes), callback);
+};
+
+/**
+* Validates share ACL type.
+*
+* @param {string} type The type name.
+*/
+exports.shareACLIsValid = function (type, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (type != FileUtilities.SharePublicAccessType.OFF) {
+ fail(new ArgumentError('type', 'The access type is not supported.'));
+ }
+
+ callback();
+ return true;
+};
+
+/**
+* Validates share quota value.
+*
+* @param {int} type The quota value.
+*/
+exports.shareQuotaIsValid = function (quota, callback) {
+ var fail;
+
+ initCallback(callback, function (f, cb) {
+ fail = f;
+ callback = cb;
+ });
+
+ if (quota && quota <= 0) {
+ fail(new RangeError('The share quota value, in GB, must be greater than 0.'));
+ }
+
+ callback();
+ return true;
+};
+
+// common functions for validating arguments
+
+function throwMissingArgument(name, func) {
+ throw new ArgumentNullError(name, 'Required argument ' + name + ' for function ' + func + ' is not defined');
+}
+
+function ArgumentValidator(functionName) {
+ this.func = functionName;
+}
+
+_.extend(ArgumentValidator.prototype, {
+ string: function (val, name) {
+ this.exists(val, name);
+ if (typeof val !== 'string') {
+ throw new TypeError('Parameter ' + name + ' for function ' + this.func + ' should be a non-empty string');
+ }
+ },
+
+ stringAllowEmpty: function (val, name) {
+ if (typeof val !== 'string') {
+ throw new TypeError('Parameter ' + name + ' for function ' + this.func + ' should be a string');
+ }
+ },
+
+ object: function (val, name) {
+ this.exists(val, name);
+ if (typeof val !== 'object') {
+ throw new TypeError('Parameter ' + name + ' for function ' + this.func + ' should be an object');
+ }
+ },
+
+ exists: function (val, name) {
+ if (!val) {
+ throwMissingArgument(name, this.func);
+ }
+ },
+
+ function: function (val, name) {
+ this.exists(val, name);
+ if (typeof val !== 'function') {
+ throw new TypeError('Parameter ' + name + ' for function ' + this.func + ' should be a function');
+ }
+ },
+
+ value: function (val, name) {
+ if (!val && val !== 0) {
+ throwMissingArgument(name, this.func);
+ }
+ },
+
+ nonEmptyArray: function (val, name) {
+ if (!val || val.length === 0) {
+ throw new TypeError('Required array argument ' + name + ' for function ' + this.func + ' is either not defined or empty');
+ }
+ },
+
+ callback: function (val) {
+ this.exists(val, 'callback');
+ this.function(val, 'callback');
+ },
+
+ test: function (predicate, message) {
+ if (!predicate()) {
+ throw new Error(message + ' in function ' + this.func);
+ }
+ },
+
+ tableNameIsValid: exports.tableNameIsValid,
+ browserFileIsValid: exports.browserFileIsValid,
+ containerNameIsValid: exports.containerNameIsValid,
+ shareNameIsValid: exports.shareNameIsValid,
+ blobNameIsValid: exports.blobNameIsValid,
+ blobTierNameIsValid: exports.blobTierNameIsValid,
+ pageRangesAreValid: exports.pageRangesAreValid,
+ queueNameIsValid: exports.queueNameIsValid,
+ blobTypeIsValid: exports.blobTypeIsValid,
+ shareACLIsValid: exports.shareACLIsValid,
+ shareQuotaIsValid: exports.shareQuotaIsValid,
+ isValidEnumValue: exports.isValidEnumValue
+});
+
+function validateArgs(functionName, validationRules) {
+ var validator = new ArgumentValidator(functionName);
+ validationRules(validator);
+}
+
+exports.ArgumentValidator = ArgumentValidator;
+exports.validateArgs = validateArgs;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/blob/blobservice.browser.js b/src/node_modules/azure-storage/lib/services/blob/blobservice.browser.js
new file mode 100644
index 0000000..0b50d66
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/blobservice.browser.js
@@ -0,0 +1,319 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var BlobService = require('./blobservice.core');
+var azureCommon = require('./../../common/common.browser');
+var extend = require('extend');
+var mime = require('browserify-mime');
+
+var Constants = azureCommon.Constants;
+var azureutil = azureCommon.util;
+var BlobConstants = Constants.BlobConstants;
+var BrowserFileReadStream = azureCommon.BrowserFileReadStream;
+var SpeedSummary = azureCommon.SpeedSummary;
+var validate = azureCommon.validate;
+
+/**
+* Creates a new block blob. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* (Only available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {File} browserFile The File object to be uploaded created by HTML File API.
+* @param {object} [options] The request options.
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createBlockBlobFromBrowserFile = function (container, blob, browserFile, optionsOrCallback, callback) {
+ return this._createBlobFromBrowserFile(container, blob, BlobConstants.BlobTypes.BLOCK, browserFile, optionsOrCallback, callback);
+};
+
+/**
+* Uploads a page blob from an HTML file. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* (Only available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {File} browserFile The File object to be uploaded created by HTML File API.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createPageBlobFromBrowserFile = function (container, blob, browserFile, optionsOrCallback, callback) {
+ return this._createBlobFromBrowserFile(container, blob, BlobConstants.BlobTypes.PAGE, browserFile, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new append blob from an HTML File object. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* If you want to append data to an already existing blob, please look at appendFromBrowserFile.
+* (Only available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {File} browserFile The File object to be uploaded created by HTML File API.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 ahash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createAppendBlobFromBrowserFile = function (container, blob, browserFile, optionsOrCallback, callback) {
+ return this._createBlobFromBrowserFile(container, blob, BlobConstants.BlobTypes.APPEND, browserFile, optionsOrCallback, callback);
+};
+
+/**
+* Appends to an append blob from an HTML File object. Assumes the blob already exists on the service.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* (Only available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {File} browserFile The File object to be uploaded created by HTML File API.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.appendFromBrowserFile = function (container, blob, browserFile, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('appendFromBrowserFile', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.browserFileIsValid(browserFile);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+
+ var stream = new BrowserFileReadStream(browserFile);
+ var streamCallback = function (appendError, blob, response) {
+ if (azureutil.objectIsFunction(stream.destroy)) {
+ stream.destroy();
+ }
+ callback(appendError, blob, response);
+ };
+ this._uploadBlobFromStream(false, container, blob, BlobConstants.BlobTypes.APPEND, stream, browserFile.size, options, streamCallback);
+
+ return options.speedSummary;
+};
+
+// Private methods
+
+/**
+* Creates a new blob (Block/Page/Append). If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* (Only available in the JavaScript Client Library for Browsers)
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param {File} browserFile The File object to be uploaded created by HTML File API.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The MD5 hash of the blob content.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback The callback function.
+*
+* @return {SpeedSummary}
+*
+*/
+BlobService.prototype._createBlobFromBrowserFile = function (container, blob, blobType, browserFile, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_createBlobFromBrowserFile', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.blobTypeIsValid(blobType);
+ v.browserFileIsValid(browserFile);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+
+ var self = this;
+ var creationCallback = function (createError, createBlob, createResponse) {
+ if (createError) {
+ callback(createError, createBlob, createResponse);
+ } else {
+ // Automatically detect the mime type
+ if(azureutil.tryGetValueChain(options, ['contentSettings','contentType'], undefined) === undefined) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings','contentType'], mime.lookup(browserFile.name));
+ }
+
+ var stream = new BrowserFileReadStream(browserFile);
+ var streamCallback = function (createError, createBlob, createResponse) {
+ if (azureutil.objectIsFunction(stream.destroy)) {
+ stream.destroy();
+ }
+ callback(createError, createBlob, createResponse);
+ };
+ self._uploadBlobFromStream(true, container, blob, blobType, stream, browserFile.size, options, streamCallback);
+ }
+ };
+
+ this._createBlob(container, blob, blobType, browserFile.size, options, creationCallback);
+
+ return options.speedSummary;
+};
+
+module.exports = BlobService;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/blob/blobservice.core.js b/src/node_modules/azure-storage/lib/services/blob/blobservice.core.js
new file mode 100644
index 0000000..adaac07
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/blobservice.core.js
@@ -0,0 +1,5871 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var qs = require('querystring');
+var url = require('url');
+var util = require('util');
+var _ = require('underscore');
+var extend = require('extend');
+
+var azureCommon = require('./../../common/common.core');
+var BlockRangeStream = require('./internal/blockrangestream');
+var Md5Wrapper = require('./../../common/md5-wrapper');
+var PageRangeStream = require('./internal/pagerangestream');
+var RangeStream = require('./../../common/streams/rangestream');
+var azureutil = azureCommon.util;
+var SR = azureCommon.SR;
+var validate = azureCommon.validate;
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var WebResource = azureCommon.WebResource;
+
+// Constants
+var Constants = azureCommon.Constants;
+var BlobConstants = Constants.BlobConstants;
+var HeaderConstants = Constants.HeaderConstants;
+var QueryStringConstants = Constants.QueryStringConstants;
+var RequestLocationMode = Constants.RequestLocationMode;
+
+// Streams
+var BatchOperation = azureCommon.BatchOperation;
+var SpeedSummary = azureCommon.SpeedSummary;
+var ChunkAllocator = azureCommon.ChunkAllocator;
+var ChunkStream = azureCommon.ChunkStream;
+var ChunkStreamWithStream = azureCommon.ChunkStreamWithStream;
+
+// Models requires
+var AclResult = azureCommon.AclResult;
+var ServiceStatsParser = azureCommon.ServiceStatsParser;
+var AccountPropertiesResult = require('../../common/models/accountpropertiesresult');
+var BlockListResult = require('./models/blocklistresult');
+var BlobResult = require('./models/blobresult');
+var ContainerResult = require('./models/containerresult');
+var LeaseResult = require('./models/leaseresult');
+
+var BlobUtilities = require('./blobutilities');
+
+// Errors requires
+var errors = require('../../common/errors/errors');
+var ArgumentError = errors.ArgumentError;
+var ArgumentNullError = errors.ArgumentNullError;
+var StorageError = errors.StorageError;
+
+/**
+* Creates a new BlobService object.
+* If no connection string or storageaccount and storageaccesskey are provided,
+* the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
+* @class
+* The BlobService class is used to perform operations on the Microsoft Azure Blob Service.
+* The Blob Service provides storage for binary large objects, and provides
+* functions for working with data stored in blobs as either streams or pages of data.
+*
+* For more information on the Blob Service, as well as task focused information on using it in a Node.js application, see
+* [How to Use the Blob Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-blob-storage/).
+* The following defaults can be set on the blob service.
+* singleBlobPutThresholdInBytes The default maximum size, in bytes, of a blob before it must be separated into blocks.
+* defaultEnableReuseSocket The default boolean value to enable socket reuse when uploading local files or streams.
+* If the Node.js version is lower than 0.10.x, socket reuse will always be turned off.
+* defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Blob service.
+* defaultClientRequestTimeoutInMs The default timeout of client requests, in milliseconds, to use for the request made via the Blob service.
+* defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Blob service.
+* defaultLocationMode The default location mode for requests made via the Blob service.
+* parallelOperationThreadCount The number of parallel operations that may be performed when uploading a blob that is greater than
+* the value specified by the singleBlobPutThresholdInBytes property in size.
+* useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Blob service; true to use the
+* Nagle algorithm; otherwise, false. The default value is false.
+* enableGlobalHttpAgent Determines whether global HTTP(s) agent is enabled; true to use Global HTTP(s) agent; otherwise, false to use
+* http(s).Agent({keepAlive:true}).
+* @constructor
+* @extends {StorageServiceClient}
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} [sas] The Shared Access Signature string.
+* @param {string} [endpointSuffix] The endpoint suffix.
+* @param {TokenCredential} [token] The {@link TokenCredential} object.
+*/
+function BlobService(storageAccountOrConnectionString, storageAccessKey, host, sas, endpointSuffix, token) {
+ var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sas, endpointSuffix, token);
+
+ BlobService['super_'].call(this,
+ storageServiceSettings._name,
+ storageServiceSettings._key,
+ storageServiceSettings._blobEndpoint,
+ storageServiceSettings._usePathStyleUri,
+ storageServiceSettings._sasToken,
+ token);
+
+ this.defaultEnableReuseSocket = Constants.DEFAULT_ENABLE_REUSE_SOCKET;
+ this.singleBlobPutThresholdInBytes = BlobConstants.DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES;
+ this.parallelOperationThreadCount = Constants.DEFAULT_PARALLEL_OPERATION_THREAD_COUNT;
+}
+
+util.inherits(BlobService, StorageServiceClient);
+
+// Non-class methods
+
+/**
+* Create resource name
+* @ignore
+*
+* @param {string} containerName Container name
+* @param {string} blobName Blob name
+* @return {string} The encoded resource name.
+*/
+function createResourceName(containerName, blobName, forSAS) {
+ // Resource name
+ if (blobName && !forSAS) {
+ blobName = encodeURIComponent(blobName);
+ blobName = blobName.replace(/%2F/g, '/');
+ blobName = blobName.replace(/%5C/g, '/');
+ blobName = blobName.replace(/\+/g, '%20');
+ }
+
+ // return URI encoded resource name
+ if (blobName) {
+ return containerName + '/' + blobName;
+ }
+ else {
+ return containerName;
+ }
+}
+
+// Blob service methods
+
+/**
+* Gets the service stats for a storage account’s Blob service.
+*
+* @this {BlobService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `[result]{@link ServiceStats}` will contain the stats and
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getServiceStats = function (optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ validate.validateArgs('getServiceStats', function (v) {
+ v.callback(callback);
+ });
+
+ var webResource = WebResource.get()
+ .withQueryOption(QueryStringConstants.COMP, 'stats')
+ .withQueryOption(QueryStringConstants.RESTYPE, 'service');
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.serviceStatsResult = null;
+ if (!responseObject.error) {
+ responseObject.serviceStatsResult = ServiceStatsParser.parse(responseObject.response.body.StorageServiceStats);
+ }
+
+ // function to be called after all filters
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.serviceStatsResult, returnObject.response);
+ };
+
+ // call the first filter
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets the properties of a storage account’s Blob service, including Azure Storage Analytics.
+*
+* @this {BlobService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `[result]{@link BlobServiceProperties}` will contain the properties
+* and `response` will contain information related to this operation.
+*/
+BlobService.prototype.getServiceProperties = function (optionsOrCallback, callback) {
+ return this.getAccountServiceProperties(optionsOrCallback, callback);
+};
+
+/**
+* Gets the properties of a storage account.
+*
+* @this {BlobService}
+* @param {string} [container] Optional. Name of an existing container. Required when using a SAS token to a specific container or blob.
+* @param {string} [blob] Optional. Name of an existing blob. Required when using a SAS token to a specific blob.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `[result]{@link ServiceProperties}` will contain the properties
+* and `response` will contain information related to this operation.
+*/
+BlobService.prototype.getAccountProperties = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getAccountProperties', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var webResource = WebResource.head(createResourceName(container, blob))
+ .withQueryOption(QueryStringConstants.COMP, 'properties')
+ .withQueryOption(QueryStringConstants.RESTYPE, 'account');
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.accountPropertiesResult = null;
+ if (!responseObject.error) {
+ responseObject.accountPropertiesResult = AccountPropertiesResult.parse(responseObject.response.headers);
+ }
+
+ // function to be called after all filters
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.accountPropertiesResult, returnObject.response);
+ };
+
+ // call the first filter
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets the properties of a storage account's Blob service, including Azure Storage Analytics.
+* You can also use this operation to set the default request version for all incoming requests that do not have a version specified.
+* When you set blob service properties (such as enabling soft delete), it may take up to 30 seconds to take effect.
+*
+* @this {BlobService}
+* @param {object} serviceProperties A `[BlobServiceProperties]{@link BlobServiceProperties}` object.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise, `response`
+* will contain information related to this operation.
+*/
+BlobService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) {
+ return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback);
+};
+
+/**
+* Sets the tier of a blockblob under a blob storage account, or the tier of a pageblob under a premium storage account.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} blobTier Please see BlobUtilities.BlobTier.StandardBlobTier or BlobUtilities.BlobTier.PremiumPageBlobTier for possible values.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise, `response`
+* will contain information related to this operation.
+*/
+BlobService.prototype.setBlobTier = function (container, blob, blobTier, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setBlobTier', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.string(blobTier, 'blobTier');
+ v.containerNameIsValid(container);
+ v.blobNameIsValid(container, blob);
+ v.blobTierNameIsValid(blobTier);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'tier')
+ .withHeader(HeaderConstants.ACCESS_TIER, blobTier);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Lists a segment containing a collection of container items under the specified account.
+*
+* @this {BlobService}
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.maxResults] Specifies the maximum number of containers to return per call to Azure storage.
+* @param {string} [options.include] Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[containers]{@link ContainerResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listContainersSegmented = function (currentToken, optionsOrCallback, callback) {
+ this.listContainersSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of container items whose names begin with the specified prefix under the specified account.
+*
+* @this {BlobService}
+* @param {string} prefix The prefix of the container name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.maxResults] Specifies the maximum number of containers to return per call to Azure storage.
+* @param {string} [options.include] Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[containers]{@link ContainerResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listContainersSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listContainers', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get()
+ .withQueryOption(QueryStringConstants.COMP, 'list')
+ .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults)
+ .withQueryOption(QueryStringConstants.INCLUDE, options.include);
+
+ if (!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker);
+ }
+
+ webResource.withQueryOption(QueryStringConstants.PREFIX, prefix);
+
+ options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.listContainersResult = null;
+
+ if (!responseObject.error) {
+ responseObject.listContainersResult = {
+ entries: null,
+ continuationToken: null
+ };
+ responseObject.listContainersResult.entries = [];
+
+ var containers = [];
+
+ if (responseObject.response.body.EnumerationResults.Containers && responseObject.response.body.EnumerationResults.Containers.Container) {
+ containers = responseObject.response.body.EnumerationResults.Containers.Container;
+ if (!_.isArray(containers)) {
+ containers = [containers];
+ }
+ }
+
+ containers.forEach(function (currentContainer) {
+ var containerResult = ContainerResult.parse(currentContainer);
+ responseObject.listContainersResult.entries.push(containerResult);
+ });
+
+ if (responseObject.response.body.EnumerationResults.NextMarker) {
+ responseObject.listContainersResult.continuationToken = {
+ nextMarker: null,
+ targetLocation: null
+ };
+
+ responseObject.listContainersResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker;
+ responseObject.listContainersResult.continuationToken.targetLocation = responseObject.targetLocation;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.listContainersResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+// Container methods
+
+/**
+* Checks whether or not a container exists on the service.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerResult}` will contain
+* the container information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.doesContainerExist = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('doesContainerExist', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ this._doesContainerExist(container, false, options, callback);
+};
+
+/**
+* Creates a new container under the specified account.
+* If a container with the same name already exists, the operation fails.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerResult}` will contain
+* the container information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createContainer = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createContainer', function (v) {
+ v.string(container, 'container');
+ v.test(function () { return container !== '$logs'; },
+ 'Container name format is incorrect');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container');
+
+ webResource.addOptionalMetadataHeaders(options.metadata);
+ webResource.withHeader(HeaderConstants.BLOB_PUBLIC_ACCESS, options.publicAccessLevel);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.containerResult = new ContainerResult(container);
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ if (options.metadata) {
+ responseObject.containerResult.metadata = options.metadata;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Creates a new container under the specified account if the container does not exists.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerResult}` will contain
+* the container information including `created` boolean member.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* blobService.createContainerIfNotExists('taskcontainer', {publicAccessLevel : 'blob'}, function(error) {
+* if(!error) {
+* // Container created or exists, and is public
+* }
+* });
+*/
+BlobService.prototype.createContainerIfNotExists = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createContainerIfNotExists', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var self = this;
+ self._doesContainerExist(container, true, options, function (error, result, response) {
+ var exists = result.exists;
+ result.created = false;
+ delete result.exists;
+
+ if (error) {
+ callback(error, result, response);
+ } else if (exists) {
+ response.isSuccessful = true;
+ callback(error, result, response);
+ } else {
+ self.createContainer(container, options, function (createError, containerResult, createResponse) {
+ if (!createError) {
+ containerResult.created = true;
+ }
+ else if (createError && createError.statusCode === Constants.HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.BlobErrorCodeStrings.CONTAINER_ALREADY_EXISTS) {
+ // If it was created before, there was no actual error.
+ createError = null;
+ createResponse.isSuccessful = true;
+ }
+
+ callback(createError, containerResult, createResponse);
+ });
+ }
+ });
+};
+
+/**
+* Retrieves a container and its properties from a specified account.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerResult}` will contain
+* information for the container.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getContainerProperties = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getContainerProperties', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.containerResult = new ContainerResult(container);
+ responseObject.containerResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Returns all user-defined metadata for the container.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerResult}` will contain
+* information for the container.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getContainerMetadata = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getContainerMetadata', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withQueryOption(QueryStringConstants.COMP, 'metadata')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.containerResult = new ContainerResult(container);
+ responseObject.containerResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets the container's metadata.
+*
+* Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container.
+* It's not possible to modify an individual name/value pair.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} metadata The metadata key/value pairs.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.setContainerMetadata = function (container, metadata, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setContainerMetadata', function (v) {
+ v.string(container, 'container');
+ v.object(metadata, 'metadata');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withQueryOption(QueryStringConstants.COMP, 'metadata')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ webResource.addOptionalMetadataHeaders(metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.containerResult = new ContainerResult(container);
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets the container's ACL.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerAclResult}` will contain
+* information for the container.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getContainerAcl = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getContainerAcl', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withQueryOption(QueryStringConstants.COMP, 'acl')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.containerResult = new ContainerResult(container);
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+ responseObject.containerResult.signedIdentifiers = AclResult.parse(responseObject.response.body);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Updates the container's ACL.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {Object.} signedIdentifiers The container ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ContainerAclResult}` will contain
+* information for the container.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.setContainerAcl = function (container, signedIdentifiers, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setContainerAcl', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var policies = null;
+ if (signedIdentifiers) {
+ if (_.isArray(signedIdentifiers)) {
+ throw new TypeError(SR.INVALID_SIGNED_IDENTIFIERS);
+ }
+ policies = AclResult.serialize(signedIdentifiers);
+ }
+
+ var webResource = WebResource.put(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withQueryOption(QueryStringConstants.COMP, 'acl')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0)
+ .withHeader(HeaderConstants.BLOB_PUBLIC_ACCESS, options.publicAccessLevel)
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId)
+ .withBody(policies);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.containerResult = new ContainerResult(container, options.publicAccessLevel);
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+ if (signedIdentifiers) {
+ responseObject.containerResult.signedIdentifiers = signedIdentifiers;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Marks the specified container for deletion.
+* The container and any blobs contained within it are later deleted during garbage collection.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.deleteContainer = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteContainer', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.del(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified container for deletion if it exists.
+* The container and any blobs contained within it are later deleted during garbage collection.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {string} [options.leaseId] The container lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will
+* be true if the container exists and was deleted, or false if the container
+* did not exist.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.deleteContainerIfExists = function (container, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteContainerIfExists', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var self = this;
+ self._doesContainerExist(container, true, options, function (error, result, response) {
+ if (error) {
+ callback(error, result.exists, response);
+ } else if (!result.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteContainer(container, options, function (deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError) {
+ deleted = true;
+ } else if (deleteError && deleteError.statuscode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.BlobErrorCodeStrings.CONTAINER_NOT_FOUND) {
+ // If it was deleted already, there was no actual error.
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+/**
+* Lists a segment containing a collection of blob directory items in the container.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {int} [options.maxResults] Specifies the maximum number of directories to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[directories]{@link DirectoryResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listBlobDirectoriesSegmented = function (container, currentToken, optionsOrCallback, callback) {
+ this.listBlobDirectoriesSegmentedWithPrefix(container, null /* prefix */, currentToken, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of blob directory items in the container.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} prefix The prefix of the blob directory.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {int} [options.maxResults] Specifies the maximum number of directories to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[directories]{@link BlobResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listBlobDirectoriesSegmentedWithPrefix = function (container, prefix, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+ userOptions.delimiter = '/';
+
+ this._listBlobsOrDircotriesSegmentedWithPrefix(container, prefix, currentToken, BlobConstants.ListBlobTypes.Directory, userOptions, callback);
+};
+
+/**
+* Lists a segment containing a collection of blob items in the container.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {string} [options.delimiter] Delimiter, i.e. '/', for specifying folder hierarchy.
+* @param {int} [options.maxResults] Specifies the maximum number of blobs to return per call to Azure ServiceClient. (maximum: 5000)
+* @param {string} [options.include] Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs', 'copy', 'deleted').
+* Please find these values in BlobUtilities.BlobListingDetails. Multiple values can be added separated with a comma (,).
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[blobs]{@link BlobResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listBlobsSegmented = function (container, currentToken, optionsOrCallback, callback) {
+ this.listBlobsSegmentedWithPrefix(container, null /* prefix */, currentToken, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of blob items whose names begin with the specified prefix in the container.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} prefix The prefix of the blob name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {string} [options.delimiter] Delimiter, i.e. '/', for specifying folder hierarchy.
+* @param {int} [options.maxResults] Specifies the maximum number of blobs to return per call to Azure ServiceClient. (maximum: 5000)
+* @param {string} [options.include] Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs', 'copy', 'deleted').
+* Please find these values in BlobUtilities.BlobListingDetails. Multiple values can be added separated with a comma (,).
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the entries of `[blobs]{@link BlobResult}` and the continuation token for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listBlobsSegmentedWithPrefix = function (container, prefix, currentToken, optionsOrCallback, callback) {
+ this._listBlobsOrDircotriesSegmentedWithPrefix(container, prefix, currentToken, BlobConstants.ListBlobTypes.Blob, optionsOrCallback, callback);
+};
+
+// Lease methods
+
+/**
+* Acquires a new lease. If container and blob are specified, acquires a blob lease. Otherwise, if only container is specified and blob is null, acquires a container lease.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseDuration] The lease duration in seconds. A non-infinite lease can be between 15 and 60 seconds. Default is never to expire.
+* @param {string} [options.proposedLeaseId] The proposed lease identifier. Must be a GUID.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link LeaseResult}` will contain
+* the lease information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.acquireLease = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('acquireLease', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ if (!options.leaseDuration) {
+ options.leaseDuration = -1;
+ }
+
+ this._leaseImpl(container, blob, null /* leaseId */, BlobConstants.LeaseOperation.ACQUIRE, options, callback);
+};
+
+/**
+* Renews an existing lease. If container and blob are specified, renews the blob lease. Otherwise, if only container is specified and blob is null, renews the container lease.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} leaseId The lease identifier. Must be a GUID.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link LeaseResult}` will contain
+* the lease information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.renewLease = function (container, blob, leaseId, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('renewLease', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ this._leaseImpl(container, blob, leaseId, BlobConstants.LeaseOperation.RENEW, options, callback);
+};
+
+/**
+* Changes the lease ID of an active lease. If container and blob are specified, changes the blob lease. Otherwise, if only container is specified and blob is null, changes the
+* container lease.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} leaseId The current lease identifier.
+* @param {string} proposedLeaseId The proposed lease identifier. Must be a GUID.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link LeaseResult}` will contain the lease information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.changeLease = function (container, blob, leaseId, proposedLeaseId, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('changeLease', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ options.proposedLeaseId = proposedLeaseId;
+ this._leaseImpl(container, blob, leaseId, BlobConstants.LeaseOperation.CHANGE, options, callback);
+};
+
+/**
+* Releases the lease. If container and blob are specified, releases the blob lease. Otherwise, if only container is specified and blob is null, releases the container lease.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} leaseId The lease identifier.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link LeaseResult}` will contain
+* the lease information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.releaseLease = function (container, blob, leaseId, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('releaseLease', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ this._leaseImpl(container, blob, leaseId, BlobConstants.LeaseOperation.RELEASE, options, callback);
+};
+
+/**
+* Breaks the lease but ensures that another client cannot acquire a new lease until the current lease period has expired. If container and blob are specified, breaks the blob lease.
+* Otherwise, if only container is specified and blob is null, breaks the container lease.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {int} [options.leaseBreakPeriod] The lease break period, between 0 and 60 seconds. If unspecified, a fixed-duration lease breaks after
+* the remaining lease period elapses, and an infinite lease breaks immediately.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link LeaseResult}` will contain
+* the lease information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.breakLease = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('breakLease', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ this._leaseImpl(container, blob, null /*leaseId*/, BlobConstants.LeaseOperation.BREAK, options, callback);
+};
+
+// Blob methods
+
+/**
+* Returns all user-defined metadata, standard HTTP properties, and system properties for the blob.
+* It does not return or modify the content of the blob.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* information about the blob.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getBlobProperties = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getBlobProperties', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.head(resourceName);
+
+ if (options.snapshotId) {
+ webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+ }
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Returns all user-defined metadata for the specified blob or snapshot.
+* It does not modify or return the content of the blob.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* information about the blob.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getBlobMetadata = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getBlobMetadata', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.head(resourceName);
+
+ webResource.withQueryOption(QueryStringConstants.COMP, 'metadata');
+ webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets user-defined properties for the specified blob or snapshot.
+* It does not modify or return the content of the blob.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [properties] The blob properties to set.
+* @param {string} [properties.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [properties.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [properties.contentLanguage] The natural languages used by this resource.
+* @param {string} [properties.cacheControl] The blob's cache control.
+* @param {string} [properties.contentDisposition] The blob's content disposition.
+* @param {string} [properties.contentMD5] The blob's MD5 hash.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* information about the blob.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.setBlobProperties = function (container, blob, properties, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setBlobProperties', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, { contentSettings: properties }, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'properties');
+
+ BlobResult.setPropertiesFromBlob(webResource, options);
+
+ this._setBlobPropertiesHelper({
+ webResource: webResource,
+ options: options,
+ container: container,
+ blob: blob,
+ callback: callback
+ });
+};
+
+/**
+* Sets user-defined metadata for the specified blob or snapshot as one or more name-value pairs
+* It does not modify or return the content of the blob.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} metadata The metadata key/value pairs.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* information on the blob.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.setBlobMetadata = function (container, blob, metadata, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setBlobMetadata', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.object(metadata, 'metadata');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'metadata');
+
+ webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+
+ options.metadata = metadata;
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+
+/**
+* Provides a stream to read from a blob.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link BlobResult}` will contain the blob information.
+* `response` will contain information related to this operation.
+* @return {Readable} A Node.js Readable stream.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* var writable = fs.createWriteStream(destinationFileNameTarget);
+* blobService.createReadStream(containerName, blobName).pipe(writable);
+*/
+BlobService.prototype.createReadStream = function (container, blob, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ validate.validateArgs('createReadStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ });
+
+ var readStream = new ChunkStream();
+ this.getBlobToStream(container, blob, readStream, options, function (error, responseBlob, response) {
+ if (error) {
+ readStream.emit('error', error);
+ }
+
+ if (callback) {
+ callback(error, responseBlob, response);
+ }
+ });
+
+ return readStream;
+};
+
+/**
+* Downloads a blob into a stream.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {Writable} writeStream The Node.js Writable stream.
+* @param {object} [options] The request options.
+* @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download.
+* Set the option to true for small blobs.
+* Parallel download and speed summary won't work with this option on.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link BlobResult}` will contain the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* blobService.getBlobToStream('taskcontainer', 'task1', fs.createWriteStream('task1-download.txt'), function(error, serverBlob) {
+* if(!error) {
+* // Blob available in serverBlob.blob variable
+* }
+* });
+*/
+BlobService.prototype.getBlobToStream = function (container, blob, writeStream, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+ userOptions.speedSummary = userOptions.speedSummary || new SpeedSummary(blob);
+
+ validate.validateArgs('getBlobToStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.object(writeStream, 'writeStream');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var propertiesRequestOptions = {
+ timeoutIntervalInMs: options.timeoutIntervalInMs,
+ clientRequestTimeoutInMs: options.clientRequestTimeoutInMs,
+ snapshotId: options.snapshotId,
+ accessConditions: options.accessConditions
+ };
+
+ if (options.skipSizeCheck) {
+ this._getBlobToStream(container, blob, writeStream, options, callback);
+ } else {
+ var self = this;
+ this.getBlobProperties(container, blob, propertiesRequestOptions, function (error, properties) {
+ if (error) {
+ callback(error);
+ } else {
+ var size;
+ if (options.rangeStart) {
+ var endOffset = properties.contentLength - 1;
+ var end = options.rangeEnd ? Math.min(options.rangeEnd, endOffset) : endOffset;
+ size = end - options.rangeStart + 1;
+ } else {
+ size = properties.contentLength;
+ }
+ options.speedSummary.totalSize = size;
+
+ if (size > self.singleBlobPutThresholdInBytes) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], azureutil.tryGetValueChain(properties, ['contentSettings', 'contentMD5'], null));
+ self._getBlobToRangeStream(container, blob, properties.blobType, writeStream, options, callback);
+ } else {
+ self._getBlobToStream(container, blob, writeStream, options, callback);
+ }
+ }
+ });
+ }
+
+ return options.speedSummary;
+};
+
+/**
+* Downloads a blob into a text string.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {BlobService~blobToText} callback `error` will contain information
+* if an error occurs; otherwise `text` will contain the blob contents,
+* and `[blockBlob]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getBlobToText = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getBlobToText', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.get(resourceName)
+ .withRawResponse();
+
+ webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+ this._setRangeContentMD5Header(webResource, options);
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.text = null;
+ responseObject.blobResult = null;
+
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ responseObject.text = responseObject.response.body;
+
+ self._validateLengthAndMD5(options, responseObject);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.text, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
+* If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots,
+* or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error
+* and nothing will be deleted.
+* If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.BlobUtilities.SnapshotDeleteOptions.*.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; `response` will contain information related to this operation.
+*/
+BlobService.prototype.deleteBlob = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.del(resourceName)
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ if (!azureutil.objectIsNull(options.snapshotId) && !azureutil.objectIsNull(options.deleteSnapshots)) {
+ throw new ArgumentError('options', SR.INVALID_DELETE_SNAPSHOT_OPTION);
+ }
+
+ webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+ webResource.withHeader(HeaderConstants.DELETE_SNAPSHOT, options.deleteSnapshots);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* The undelete Blob operation restores the contents and metadata of soft deleted blob or snapshot.
+* Attempting to undelete a blob or snapshot that is not soft deleted will succeed without any changes.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; `response` will contain information related to this operation.
+*/
+BlobService.prototype.undeleteBlob = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'undelete');
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks whether or not a blob exists on the service.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information including the `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.doesBlobExist = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('doesBlobExist', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ this._doesBlobExist(container, blob, false, options, callback);
+};
+
+/**
+* Marks the specified blob or snapshot for deletion if it exists. The blob is later deleted during garbage collection.
+* If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots,
+* or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error
+* and nothing will be deleted.
+* If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.BlobUtilities.SnapshotDeleteOptions.*.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will
+* be true if the blob was deleted, or false if the blob
+* does not exist.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.deleteBlobIfExists = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteBlobIfExists', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var self = this;
+ self._doesBlobExist(container, blob, true, options, function (error, existsResult, response) {
+ if (error) {
+ callback(error, existsResult.exists, response);
+ } else if (!existsResult.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteBlob(container, blob, options, function (deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError) {
+ deleted = true;
+ } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.BlobErrorCodeStrings.BLOB_NOT_FOUND) {
+ // If it was deleted already, there was no actual error.
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+/**
+* Creates a read-only snapshot of a blob.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the ID of the snapshot.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createBlobSnapshot = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createBlobSnapshot', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'snapshot');
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.snapshotId = null;
+ if (!responseObject.error) {
+ responseObject.snapshotId = responseObject.response.headers[HeaderConstants.SNAPSHOT];
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.snapshotId, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Starts to copy a blob or an Azure Storage file to a destination blob.
+*
+* For an asynchronous copy(by default), this operation returns a object including a copy ID which
+* you can use to check or abort the copy operation. The Blob service copies blobs on a best-effort basis.
+* The source blob for an asynchronous copy operation may be a block blob, an append blob,
+* a page blob or an Azure Storage file.
+*
+* Refer to https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob for more details.
+*
+* @this {BlobService}
+* @param {string} sourceUri The source blob URI.
+* @param {string} targetContainer The target container name.
+* @param {string} targetBlob The target blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {boolean} [options.isIncrementalCopy] If it's incremental copy or not. Refer to https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/incremental-copy-blob
+* @param {string} [options.snapshotId] The source blob snapshot identifier.
+* @param {object} [options.metadata] The target blob metadata key/value pairs.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.sourceLeaseId] The source blob lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {AccessConditions} [options.sourceAccessConditions] The source access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.startCopyBlob = function (sourceUri, targetContainer, targetBlob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('startCopyBlob', function (v) {
+ v.string(sourceUri, 'sourceUri');
+ v.string(targetContainer, 'targetContainer');
+ v.string(targetBlob, 'targetBlob');
+ v.containerNameIsValid(targetContainer);
+ v.callback(callback);
+ });
+
+ var targetResourceName = createResourceName(targetContainer, targetBlob);
+
+ var options = extend(true, {}, userOptions);
+
+ if (options.snapshotId) {
+ var uri = url.parse(sourceUri, true);
+ if (uri.query['snapshot']) {
+ throw new ArgumentError('options.snapshotId', 'Duplicate snapshot supplied in both the source uri and option.');
+ }
+
+ uri.search = undefined;
+ uri.query['snapshot'] = options.snapshotId;
+
+ sourceUri = url.format(uri);
+ }
+
+ var webResource = WebResource.put(targetResourceName)
+ .withHeader(HeaderConstants.COPY_SOURCE, sourceUri);
+
+ if (options.isIncrementalCopy) {
+ webResource.withQueryOption(QueryStringConstants.COMP, 'incrementalcopy');
+ }
+
+ webResource.withHeader(HeaderConstants.ACCESS_TIER, options.blobTier);
+ webResource.withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+ webResource.withHeader(HeaderConstants.SOURCE_LEASE_ID, options.sourceLeaseId);
+ webResource.addOptionalMetadataHeaders(options.metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(targetContainer, targetBlob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ if (options.metadata) {
+ responseObject.blobResult.metadata = options.metadata;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Abort a blob copy operation.
+*
+* @this {BlobService}
+* @param {string} container The destination container name.
+* @param {string} blob The destination blob name.
+* @param {string} copyId The copy operation identifier.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information if an error occurs;
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.abortCopyBlob = function (container, blob, copyId, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('abortCopyBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var resourceName = createResourceName(container, blob);
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COPY_ID, copyId)
+ .withQueryOption(QueryStringConstants.COMP, 'copy')
+ .withHeader(HeaderConstants.COPY_ACTION, 'abort');
+
+ webResource.withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Retrieves a shared access signature token.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} [blob] The blob name.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {string} [sharedAccessPolicy.Id] The signed identifier.
+* @param {object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used).
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired (The UTC value will be used).
+* @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} [sharedAccessPolicy.AccessPolicy.Protocols] The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* @param {object} [headers] The optional header values to set for a blob returned wth this SAS.
+* @param {string} [headers.cacheControl] The optional value of the Cache-Control response header to be returned when this SAS is used.
+* @param {string} [headers.contentType] The optional value of the Content-Type response header to be returned when this SAS is used.
+* @param {string} [headers.contentEncoding] The optional value of the Content-Encoding response header to be returned when this SAS is used.
+* @param {string} [headers.contentLanguage] The optional value of the Content-Language response header to be returned when this SAS is used.
+* @param {string} [headers.contentDisposition] The optional value of the Content-Disposition response header to be returned when this SAS is used.
+* @return {string} The shared access signature query string. Note this string does not contain the leading "?".
+*/
+BlobService.prototype.generateSharedAccessSignature = function (container, blob, sharedAccessPolicy, headers) {
+ // check if the BlobService is able to generate a shared access signature
+ if (!this.storageCredentials) {
+ throw new ArgumentNullError('storageCredentials');
+ }
+
+ if (!this.storageCredentials.generateSignedQueryString) {
+ throw new ArgumentError('storageCredentials', SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
+ }
+
+ // Validate container name. Blob name is optional.
+ validate.validateArgs('generateSharedAccessSignature', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.object(sharedAccessPolicy, 'sharedAccessPolicy');
+ });
+
+ var resourceType = BlobConstants.ResourceTypes.CONTAINER;
+ if (blob) {
+ validate.validateArgs('generateSharedAccessSignature', function (v) {
+ v.string(blob, 'blob');
+ });
+ resourceType = BlobConstants.ResourceTypes.BLOB;
+ }
+
+ if (sharedAccessPolicy.AccessPolicy) {
+ if (!azureutil.objectIsNull(sharedAccessPolicy.AccessPolicy.Start)) {
+ if (!_.isDate(sharedAccessPolicy.AccessPolicy.Start)) {
+ sharedAccessPolicy.AccessPolicy.Start = new Date(sharedAccessPolicy.AccessPolicy.Start);
+ }
+
+ sharedAccessPolicy.AccessPolicy.Start = azureutil.truncatedISO8061Date(sharedAccessPolicy.AccessPolicy.Start);
+ }
+
+ if (!azureutil.objectIsNull(sharedAccessPolicy.AccessPolicy.Expiry)) {
+ if (!_.isDate(sharedAccessPolicy.AccessPolicy.Expiry)) {
+ sharedAccessPolicy.AccessPolicy.Expiry = new Date(sharedAccessPolicy.AccessPolicy.Expiry);
+ }
+
+ sharedAccessPolicy.AccessPolicy.Expiry = azureutil.truncatedISO8061Date(sharedAccessPolicy.AccessPolicy.Expiry);
+ }
+ }
+
+ var resourceName = createResourceName(container, blob, true);
+ return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.Blob, resourceName, sharedAccessPolicy, null, { headers: headers, resourceType: resourceType });
+};
+
+/**
+* Retrieves a blob or container URL.
+*
+* @param {string} container The container name.
+* @param {string} [blob] The blob name.
+* @param {string} [sasToken] The Shared Access Signature token.
+* @param {boolean} [primary] A boolean representing whether to use the primary or the secondary endpoint.
+* @param {string} [snapshotId] The snapshot identifier.
+* @return {string} The formatted URL string.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* var sharedAccessPolicy = {
+* AccessPolicy: {
+* Permissions: azure.BlobUtilities.SharedAccessPermissions.READ,
+* Start: startDate,
+* Expiry: expiryDate
+* },
+* };
+*
+* var sasToken = blobService.generateSharedAccessSignature(containerName, blobName, sharedAccessPolicy);
+* var sasUrl = blobService.getUrl(containerName, blobName, sasToken);
+*/
+BlobService.prototype.getUrl = function (container, blob, sasToken, primary, snapshotId) {
+ validate.validateArgs('getUrl', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ });
+
+ var host;
+ if (!azureutil.objectIsNull(primary) && primary === false) {
+ host = this.host.secondaryHost;
+ } else {
+ host = this.host.primaryHost;
+ }
+
+ host = azureutil.trimPortFromUri(host);
+ if (host && host.lastIndexOf('/') !== (host.length - 1)) {
+ host = host + '/';
+ }
+
+ var query = qs.parse(sasToken);
+ if (snapshotId) {
+ query[QueryStringConstants.SNAPSHOT] = snapshotId;
+ }
+
+ var fullPath = url.format({ pathname: this._getPath(createResourceName(container, blob)), query: query });
+ return url.resolve(host, fullPath);
+};
+
+// Page blob methods
+
+/**
+* Creates a page blob of the specified length. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {int} length The length of the page blob in bytes.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The MD5 hash of the blob content.
+* @param {string} [options.sequenceNumber] The blob's sequence number.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createPageBlob = function (container, blob, length, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createPageBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.value(length, 'length');
+ v.callback(callback);
+ });
+
+ if (length && length % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_BLOB_LENGTH);
+ }
+
+ var options = extend(true, {}, userOptions);
+
+ var resourceName = createResourceName(container, blob);
+
+ var webResource = WebResource.put(resourceName)
+ .withHeader(HeaderConstants.BLOB_TYPE, BlobConstants.BlobTypes.PAGE)
+ .withHeader(HeaderConstants.BLOB_CONTENT_LENGTH, length)
+ .withHeader(HeaderConstants.CONTENT_LENGTH, 0)
+ .withHeader(HeaderConstants.ACCESS_TIER, options.blobTier)
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Uploads a page blob from a stream. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createPageBlobFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) {
+ return this._createBlobFromStream(container, blob, BlobConstants.BlobTypes.PAGE, stream, streamLength, optionsOrCallback, callback);
+};
+
+/**
+* Provides a stream to write to a page blob. Assumes that the blob exists.
+* If it does not, please create the blob using createPageBlob before calling this method or use createWriteStreamNewPageBlob.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs and true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* blobService.createPageBlob(containerName, blobName, 1024, function (err) {
+* // Pipe file to a blob
+* var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToExistingPageBlob(containerName, blobName));
+* });
+*/
+BlobService.prototype.createWriteStreamToExistingPageBlob = function (container, blob, optionsOrCallback, callback) {
+ return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.PAGE, 0, false, optionsOrCallback, callback);
+};
+
+/**
+* Provides a stream to write to a page blob. Creates the blob before writing data. If the blob already exists on the service, it will be overwritten.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} length The blob length.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs and true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* blobService.createPageBlob(containerName, blobName, 1024, function (err) {
+* // Pipe file to a blob
+* var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToNewPageBlob(containerName, blobName));
+* });
+*/
+BlobService.prototype.createWriteStreamToNewPageBlob = function (container, blob, length, optionsOrCallback, callback) {
+ return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.PAGE, length, true, optionsOrCallback, callback);
+};
+
+/**
+* Updates a page blob from a stream.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {Readable} readStream The Node.js Readable stream.
+* @param {int} rangeStart The range start.
+* @param {int} rangeEnd The range end.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.transactionalContentMD5] An optional hash value used to ensure transactional integrity for the page.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the page information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createPagesFromStream = function (container, blob, readStream, rangeStart, rangeEnd, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createPagesFromStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ if ((rangeEnd - rangeStart) + 1 > BlobConstants.MAX_UPDATE_PAGE_SIZE) {
+ throw new RangeError(SR.INVALID_PAGE_RANGE_FOR_UPDATE);
+ }
+
+ var self = this;
+ if (azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5) {
+ azureutil.calculateMD5(readStream, BlobConstants.MAX_UPDATE_PAGE_SIZE, options, function (internalBuff, contentMD5) {
+ options.transactionalContentMD5 = contentMD5;
+ self._createPages(container, blob, internalBuff, null /* stream */, rangeStart, rangeEnd, options, callback);
+ });
+ } else {
+ self._createPages(container, blob, null /* text */, readStream, rangeStart, rangeEnd, options, callback);
+ }
+};
+
+/**
+* Lists page ranges. Lists all of the page ranges by default, or only the page ranges over a specific range of bytes if rangeStart and rangeEnd are specified.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {int} [options.rangeStart] The range start.
+* @param {int} [options.rangeEnd] The range end.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the page ranges information, see `[Range]{@link Range}` for detailed information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listPageRanges = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listPageRanges', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'pagelist')
+ .withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+
+ if (options.rangeStart && options.rangeStart % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_START_OFFSET);
+ }
+
+ if (options.rangeEnd && (options.rangeEnd + 1) % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_END_OFFSET);
+ }
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.pageRanges = null;
+ if (!responseObject.error) {
+ responseObject.pageRanges = [];
+
+ var pageRanges = [];
+ if (responseObject.response.body.PageList.PageRange) {
+ pageRanges = responseObject.response.body.PageList.PageRange;
+
+ if (!_.isArray(pageRanges)) {
+ pageRanges = [pageRanges];
+ }
+ }
+
+ pageRanges.forEach(function (pageRange) {
+ var range = {
+ start: parseInt(pageRange.Start, 10),
+ end: parseInt(pageRange.End, 10)
+ };
+
+ responseObject.pageRanges.push(range);
+ });
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.pageRanges, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets page ranges that have been updated or cleared since the snapshot specified by `previousSnapshotTime` was taken. Gets all of the page ranges by default, or only the page ranges over a specific range of bytes if rangeStart and rangeEnd are specified.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} previousSnapshotTime The previous snapshot time for comparison. Must be prior to `options.snapshotId` if it's provided.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {int} [options.rangeStart] The range start.
+* @param {int} [options.rangeEnd] The range end.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the page ranges diff information, see `[RangeDiff]{@link RangeDiff}` for detailed information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.getPageRangesDiff = function (container, blob, previousSnapshotTime, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getPageRangesDiff', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'pagelist')
+ .withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId)
+ .withQueryOption(QueryStringConstants.PREV_SNAPSHOT, previousSnapshotTime);
+
+ if (options.rangeStart && options.rangeStart % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_START_OFFSET);
+ }
+
+ if (options.rangeEnd && (options.rangeEnd + 1) % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_END_OFFSET);
+ }
+
+ if (options.rangeEnd && (options.rangeEnd + 1) % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_END_OFFSET);
+ }
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.pageRangesDiff = null;
+ if (!responseObject.error) {
+ responseObject.pageRangesDiff = [];
+
+ if (responseObject.response.body.PageList.PageRange) {
+ var updatedPageRanges = responseObject.response.body.PageList.PageRange;
+
+ if (!_.isArray(updatedPageRanges)) {
+ updatedPageRanges = [updatedPageRanges];
+ }
+
+ updatedPageRanges.forEach(function (pageRange) {
+ var range = {
+ start: parseInt(pageRange.Start, 10),
+ end: parseInt(pageRange.End, 10),
+ isCleared: false
+ };
+
+ responseObject.pageRangesDiff.push(range);
+ });
+ }
+
+ if (responseObject.response.body.PageList.ClearRange) {
+ var clearedPageRanges = responseObject.response.body.PageList.ClearRange;
+
+ if (!_.isArray(clearedPageRanges)) {
+ clearedPageRanges = [clearedPageRanges];
+ }
+
+ clearedPageRanges.forEach(function (pageRange) {
+ var range = {
+ start: parseInt(pageRange.Start, 10),
+ end: parseInt(pageRange.End, 10),
+ isCleared: true
+ };
+
+ responseObject.pageRangesDiff.push(range);
+ });
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.pageRangesDiff, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Clears a range of pages.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {int} rangeStart The range start.
+* @param {int} rangeEnd The range end.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.clearPageRange = function (container, blob, rangeStart, rangeEnd, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('clearPageRange', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var request = this._updatePageBlobPagesImpl(container, blob, rangeStart, rangeEnd, BlobConstants.PageWriteOptions.CLEAR, options);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ self.performRequest(request, null, options, processResponseCallback);
+};
+
+/**
+* Resizes a page blob.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {String} size The size of the page blob, in bytes.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The blob lease identifier.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the page information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.resizePageBlob = function (container, blob, size, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('resizePageBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'properties')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ if (size && size % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_BLOB_LENGTH);
+ }
+
+ webResource.withHeader(HeaderConstants.BLOB_CONTENT_LENGTH, size);
+
+ this._setBlobPropertiesHelper({
+ webResource: webResource,
+ options: options,
+ container: container,
+ blob: blob,
+ callback: callback
+ });
+
+};
+
+/**
+* Sets the page blob's sequence number.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {SequenceNumberAction} sequenceNumberAction A value indicating the operation to perform on the sequence number.
+* The allowed values are defined in azure.BlobUtilities.SequenceNumberAction.
+* @param {string} sequenceNumber The sequence number. The value of the sequence number must be between 0 and 2^63 - 1.
+* Set this parameter to null if this operation is an increment action.
+* @param {object} [options] The request options.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the page information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.setPageBlobSequenceNumber = function (container, blob, sequenceNumberAction, sequenceNumber, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setPageBlobSequenceNumber', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ if (sequenceNumberAction === BlobUtilities.SequenceNumberAction.INCREMENT) {
+ if (!azureutil.objectIsNull(sequenceNumber)) {
+ throw new ArgumentError('sequenceNumber', SR.BLOB_INVALID_SEQUENCE_NUMBER);
+ }
+ } else {
+ if (azureutil.objectIsNull(sequenceNumber)) {
+ throw new ArgumentNullError('sequenceNumber', util.format(SR.ARGUMENT_NULL_OR_EMPTY, 'sequenceNumber'));
+ }
+ }
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'properties')
+ .withHeader(HeaderConstants.SEQUENCE_NUMBER_ACTION, sequenceNumberAction);
+
+ if (sequenceNumberAction !== BlobUtilities.SequenceNumberAction.INCREMENT) {
+ webResource.withHeader(HeaderConstants.SEQUENCE_NUMBER, sequenceNumber);
+ }
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+// Block blob methods
+
+/**
+* Uploads a block blob from a stream. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createBlockBlobFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) {
+ return this._createBlobFromStream(container, blob, BlobConstants.BlobTypes.BLOCK, stream, streamLength, optionsOrCallback, callback);
+};
+
+/**
+* Uploads a block blob from a text string. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|object} text The blob text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createBlockBlobFromText = function (container, blob, text, optionsOrCallback, callback) {
+ return this._createBlobFromText(container, blob, BlobConstants.BlobTypes.BLOCK, text, optionsOrCallback, callback);
+};
+
+/**
+* Provides a stream to write to a block blob. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs and true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToBlockBlob(containerName, blobName, { blockIdPrefix: 'block' }));
+*/
+BlobService.prototype.createWriteStreamToBlockBlob = function (container, blob, optionsOrCallback, callback) {
+ return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.BLOCK, 0, false, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new block to be committed as part of a blob.
+*
+* @this {BlobService}
+* @param {string} blockId The block identifier.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {Readable} readStream The Node.js Readable stream.
+* @param {int} streamLength The stream length.
+* @param {object} [options] The request options.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createBlockFromStream = function (blockId, container, blob, readStream, streamLength, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createBlockFromStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.exists(readStream, 'readStream');
+ v.value(streamLength, 'streamLength');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ if (streamLength > BlobConstants.MAX_BLOCK_BLOB_BLOCK_SIZE) {
+ throw new RangeError(SR.INVALID_STREAM_LENGTH);
+ } else {
+ this._createBlock(blockId, container, blob, null, readStream, streamLength, options, callback);
+ }
+};
+
+/**
+* Creates a new block to be committed as part of a blob.
+*
+* @this {BlobService}
+* @param {string} blockId The block identifier.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|buffer} content The block content.
+* @param {object} [options] The request options.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createBlockFromText = function (blockId, container, blob, content, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createBlockFromText', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var contentLength = (Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content));
+
+ if (contentLength > BlobConstants.MAX_BLOCK_BLOB_BLOCK_SIZE) {
+ throw new RangeError(SR.INVALID_TEXT_LENGTH);
+ } else {
+ this._createBlock(blockId, container, blob, content, null, contentLength, options, callback);
+ }
+};
+
+/**
+* Creates a new block to be committed as part of a blob from an URL of an Azure blob or file.
+*
+* @this {BlobService}
+* @param {string} blockId The block identifier.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} sourceURL The URL of the source data.
+* It can point to any Azure Blob or File, that is either public or has a shared access signature attached.
+* @param {int} sourceRangeStart The start of the range of bytes(inclusive) that has to be taken from the copy source.
+* @param {int} sourceRangeEnd The end of the range of bytes(inclusive) that has to be taken from the copy source.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createBlockFromURL = function (blockId, container, blob, sourceURL, sourceRangeStart, sourceRangeEnd, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createBlockFromURL', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.string(sourceURL, 'sourceURL');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(container, blob);
+
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'block')
+ .withQueryOption(QueryStringConstants.BLOCK_ID, Buffer.from(blockId).toString('base64'))
+ .withHeader(HeaderConstants.COPY_SOURCE, sourceURL);
+
+ options.sourceRangeStart = sourceRangeStart;
+ options.sourceRangeEnd = sourceRangeEnd;
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Creates a new block to be committed as part of a block blob.
+* @ignore
+*
+* @this {BlobService}
+* @param {string} blockId The block identifier.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|buffer} content The block content.
+* @param {Stream} stream The stream to the data to store.
+* @param {int} length The length of the stream or text to upload.
+* @param {object} [options] The request options.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._createBlock = function (blockId, container, blob, content, stream, length, options, callback) {
+ var resourceName = createResourceName(container, blob);
+
+ var self = this;
+ var startCreateBlock = function () {
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'block')
+ .withQueryOption(QueryStringConstants.BLOCK_ID, Buffer.from(blockId).toString('base64'))
+ .withHeader(HeaderConstants.CONTENT_LENGTH, length);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ if (!azureutil.objectIsNull(content)) {
+ self.performRequest(webResource, content, options, processResponseCallback);
+ } else {
+ self.performRequestOutputStream(webResource, stream, options, processResponseCallback);
+ }
+ };
+
+ if (azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5) {
+ if (!azureutil.objectIsNull(content)) {
+ options.transactionalContentMD5 = azureutil.getContentMd5(content);
+ startCreateBlock();
+ } else {
+ azureutil.calculateMD5(stream, length, options, function (internalBuff, contentMD5) {
+ options.transactionalContentMD5 = contentMD5;
+ content = internalBuff;
+ length = internalBuff.length;
+ startCreateBlock();
+ });
+ }
+ } else {
+ startCreateBlock();
+ }
+};
+
+/**
+* Writes a blob by specifying the list of block IDs that make up the blob.
+* In order to be written as part of a blob, a block must have been successfully written to the server in a prior
+* createBlock operation.
+* Note: If no valid list is specified in the blockList parameter, blob would be updated with empty content,
+* i.e. existing blocks in the blob will be removed, this behavior is kept for backward compatibility consideration.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} blockList The wrapper for block ID list contains block IDs that make up the blob.
+* Three kinds of list are provided, please choose one to use according to requirement.
+* For more background knowledge, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/put-block-list
+* @param {string[]} [blockList.LatestBlocks] The list contains block IDs that make up the blob sequentially.
+* All the block IDs in this list will be specified within Latest element.
+* Choose this list to contain block IDs indicates that the Blob service should first search
+* the uncommitted block list, and then the committed block list for the named block.
+* @param {string[]} [blockList.CommittedBlocks] The list contains block IDs that make up the blob sequentially.
+* All the block IDs in this list will be specified within Committed element.
+* Choose this list to contain block IDs indicates that the Blob service should only search
+* the committed block list for the named block.
+* @param {string[]} [blockList.UncommittedBlocks] The list contains block IDs that make up the blob sequentially.
+* All the block IDs in this list will be specified within Uncommitted element.
+* Choose this list to contain block IDs indicates that the Blob service should only search
+* the uncommitted block list for the named block.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* blobService.createBlockFromText("sampleBlockName", containerName, blobName, "sampleBlockContent", function(error) {
+* assert.equal(error, null);
+* // In this example, LatestBlocks is used, we hope the Blob service first search
+* // the uncommitted block list, and then the committed block list for the named block "sampleBlockName",
+* // and thus make sure the block is with latest content.
+* blobService.commitBlocks(containerName, blobName, { LatestBlocks: ["sampleBlockName"] }, function(error) {
+* assert.equal(error, null);
+* });
+* });
+*
+ */
+BlobService.prototype.commitBlocks = function (container, blob, blockList, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('commitBlocks', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.object(blockList, 'blockList');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var blockListXml = BlockListResult.serialize(blockList);
+
+ var resourceName = createResourceName(container, blob);
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'blocklist')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(blockListXml))
+ .withBody(blockListXml);
+
+ BlobResult.setPropertiesFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.list = null;
+ if (!responseObject.error) {
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ responseObject.blobResult.list = blockList;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Retrieves the list of blocks that have been uploaded as part of a block blob.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlockListFilter} blocklisttype The type of block list to retrieve.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The source blob snapshot identifier.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the blocklist information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.listBlocks = function (container, blob, blocklisttype, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listBlocks', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var resourceName = createResourceName(container, blob);
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'blocklist')
+ .withQueryOption(QueryStringConstants.BLOCK_LIST_TYPE, blocklisttype)
+ .withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blockListResult = null;
+ if (!responseObject.error) {
+ responseObject.blockListResult = BlockListResult.parse(responseObject.response.body.BlockList);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blockListResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Generate a random block id prefix
+*/
+BlobService.prototype.generateBlockIdPrefix = function () {
+ var prefix = Math.floor(Math.random() * 0x100000000).toString(16);
+ return azureutil.zeroPaddingString(prefix, 8);
+};
+
+/**
+* Get a block id according to prefix and block number
+*/
+BlobService.prototype.getBlockId = function (prefix, number) {
+ return prefix + '-' + azureutil.zeroPaddingString(number, 6);
+};
+
+// Append blob methods
+
+/**
+* Creates an empty append blob. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createOrReplaceAppendBlob = function (container, blob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createOrReplaceAppendBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var resourceName = createResourceName(container, blob);
+
+ var webResource = WebResource.put(resourceName)
+ .withHeader(HeaderConstants.BLOB_TYPE, BlobConstants.BlobTypes.APPEND)
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId)
+ .withHeader(HeaderConstants.CONTENT_LENGTH, 0);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Uploads an append blob from a stream. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* If you want to append data to an already existing blob, please look at appendFromStream.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createAppendBlobFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) {
+ return this._createBlobFromStream(container, blob, BlobConstants.BlobTypes.APPEND, stream, streamLength, optionsOrCallback, callback);
+};
+
+/**
+* Uploads an append blob from a text string. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* If you want to append data to an already existing blob, please look at appendFromText.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|object} text The blob text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.createAppendBlobFromText = function (container, blob, text, optionsOrCallback, callback) {
+ return this._createBlobFromText(container, blob, BlobConstants.BlobTypes.APPEND, text, optionsOrCallback, callback);
+};
+
+/**
+* Provides a stream to write to a new append blob. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs and true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback The callback function.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToAppendBlob(containerName, blobName));
+*/
+BlobService.prototype.createWriteStreamToNewAppendBlob = function (container, blob, optionsOrCallback, callback) {
+ return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.APPEND, 0, true, optionsOrCallback, callback);
+};
+
+/**
+* Provides a stream to write to an existing append blob. Assumes that the blob exists.
+* If it does not, please create the blob using createAppendBlob before calling this method or use createWriteStreamToNewAppendBlob.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs and true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback The callback function.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToAppendBlob(containerName, blobName));
+*/
+BlobService.prototype.createWriteStreamToExistingAppendBlob = function (container, blob, optionsOrCallback, callback) {
+ return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.APPEND, 0, false, optionsOrCallback, callback);
+};
+
+/**
+* Appends to an append blob from a stream. Assumes the blob already exists on the service.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.appendFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ validate.validateArgs('appendFromStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.exists(stream, 'stream');
+ v.value(streamLength, 'streamLength');
+ v.callback(callback);
+ });
+
+ return this._uploadBlobFromStream(false, container, blob, BlobConstants.BlobTypes.APPEND, stream, streamLength, options, callback);
+};
+
+/**
+* Appends to an append blob from a text string. Assumes the blob already exists on the service.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|object} text The blob text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.appendFromText = function (container, blob, text, optionsOrCallback, callback) {
+ return this._uploadBlobFromText(false, container, blob, BlobConstants.BlobTypes.APPEND, text, optionsOrCallback, callback);
+};
+
+
+/**
+* Creates a new block from a read stream to be appended to an append blob.
+* If the sequence of data to be appended is important, please use this API strictly in a single writer.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* If the sequence of data to be appended is not important, this API can be used in parallel,
+* in this case, options.appendPosition can be left without settings.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {Readable} readStream The Node.js Readable stream.
+* @param {int} streamLength The stream length.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to.
+* @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.appendBlockFromStream = function (container, blob, readStream, streamLength, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('appendBlockFromStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.exists(readStream, 'readStream');
+ v.value(streamLength, 'streamLength');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ if (streamLength > BlobConstants.MAX_APPEND_BLOB_BLOCK_SIZE) {
+ throw new RangeError(SR.INVALID_STREAM_LENGTH);
+ } else {
+ this._appendBlock(container, blob, null, readStream, streamLength, options, callback);
+ }
+};
+
+/**
+* Creates a new block from a text to be appended to an append blob.
+* If the sequence of data to be appended is important, please use this API strictly in a single writer.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* If the sequence of data to be appended is not important, this API can be used in parallel,
+* in this case, options.appendPosition can be left without settings.
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|object} content The block text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to.
+* @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype.appendBlockFromText = function (container, blob, content, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('appendBlockFromText', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var contentLength = (Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content));
+ if (contentLength > BlobConstants.MAX_APPEND_BLOB_BLOCK_SIZE) {
+ throw new RangeError(SR.INVALID_TEXT_LENGTH);
+ } else {
+ this._appendBlock(container, blob, content, null, contentLength, options, callback);
+ }
+};
+
+// Private methods
+
+/**
+* Creates a new blob from a stream. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback The callback function.
+* @return {SpeedSummary}
+*/
+BlobService.prototype._createBlobFromStream = function (container, blob, blobType, stream, streamLength, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_createBlobFromStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.blobTypeIsValid(blobType);
+ v.exists(stream, 'stream');
+ v.value(streamLength, 'streamLength');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var self = this;
+ var creationCallback = function (createError, createBlob, createResponse) {
+ if (createError) {
+ callback(createError, createBlob, createResponse);
+ } else {
+ self._uploadBlobFromStream(true, container, blob, blobType, stream, streamLength, options, callback);
+ }
+ };
+
+ this._createBlob(container, blob, blobType, streamLength, options, creationCallback);
+
+ return options.speedSummary;
+};
+
+/**
+* Uploads a block blob or an append blob from a text string. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param {string|buffer} content The blob text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* information about the blob.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._createBlobFromText = function (container, blob, blobType, content, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_createBlobFromText', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.blobTypeIsValid(blobType);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var self = this;
+ var creationCallback = function (createError, createBlob, createResponse) {
+ if (createError) {
+ callback(createError, createBlob, createResponse);
+ } else {
+ self._uploadBlobFromText(true, container, blob, blobType, content, options, callback);
+ }
+ };
+
+ var contentLength = azureutil.objectIsNull(content) ? 0 : ((Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content)));
+ this._createBlob(container, blob, blobType, contentLength, options, creationCallback);
+
+ return options.speedSummary;
+};
+
+/**
+* Provides a stream to write to a block blob or an append blob.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param {int} length The blob length.
+* @param {bool} createNewBlob Specifies whether create a new blob.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {string} [options.blockSize] The size of each block. Maximum is 100MB. (For block blob only)
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs and true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback The callback function.
+* @return {Writable} A Node.js Writable stream.
+*/
+BlobService.prototype._createWriteStreamToBlob = function (container, blob, blobType, length, createNewBlob, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_createWriteStreamToBlob', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.blobTypeIsValid(blobType);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var sizeLimitation;
+ if (blobType === BlobConstants.BlobTypes.BLOCK) {
+ // default to true, unless explicitly set to false
+ options.storeBlobContentMD5 = options.storeBlobContentMD5 === false ? false : true;
+ sizeLimitation = options.blockSize || BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+ } else if (blobType == BlobConstants.BlobTypes.PAGE) {
+ sizeLimitation = BlobConstants.DEFAULT_WRITE_PAGE_SIZE_IN_BYTES;
+ } else if (blobType == BlobConstants.BlobTypes.APPEND) {
+ sizeLimitation = BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+ }
+
+ var stream = new ChunkStream({ calcContentMd5: options.storeBlobContentMD5 });
+ stream._highWaterMark = sizeLimitation;
+
+ stream.pause(); //Immediately pause the stream in order to wait for the destination to getting ready
+
+ var self = this;
+ var createCallback = function (createError, createBlob, createResponse) {
+ if (createError) {
+ if (callback) {
+ callback(createError, createBlob, createResponse);
+ }
+ } else {
+ self._uploadBlobFromStream(createNewBlob, container, blob, blobType, stream, null, options, function (error, blob, response) {
+ if (error) {
+ stream.emit('error', error);
+ }
+
+ if (callback) {
+ callback(error, blob, response);
+ }
+ });
+ }
+ };
+
+ if (createNewBlob === true) {
+ this._createBlob(container, blob, blobType, length, options, createCallback);
+ } else {
+ createCallback();
+ }
+
+ return stream;
+};
+
+/**
+* Upload blob content from a stream. Assumes the blob already exists.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {bool} isNewBlob Specifies whether the blob is newly created.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback The callback function.
+* @return {SpeedSummary}
+*/
+BlobService.prototype._uploadBlobFromStream = function (isNewBlob, container, blob, blobType, stream, streamLength, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+
+ if (blobType === BlobConstants.BlobTypes.BLOCK) {
+ // default to true, unless explicitly set to false
+ options.storeBlobContentMD5 = options.storeBlobContentMD5 === false ? false : true;
+ }
+
+ stream.pause();
+
+ var self = this;
+ var startUpload = function () {
+ var putBlockBlobFromStream = function () {
+ if (streamLength > 0 && azureutil.objectIsNull(azureutil.tryGetValueChain(options, ['contentSettings', 'contentMD5'], null)) && options.storeBlobContentMD5) {
+ azureutil.calculateMD5(stream, Math.min(self.singleBlobPutThresholdInBytes, streamLength), options, function (internalBuff, contentMD5) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], contentMD5);
+ self._putBlockBlob(container, blob, internalBuff, null, internalBuff.length, options, callback);
+ });
+ stream.resume();
+ } else {
+ // Stream will resume when it has a pipe destination or a 'data' listener
+ self._putBlockBlob(container, blob, null, stream, streamLength, options, callback);
+ }
+ };
+
+ if (streamLength === null || streamLength >= self.singleBlobPutThresholdInBytes || blobType !== BlobConstants.BlobTypes.BLOCK) {
+ var chunkStream = new ChunkStreamWithStream(stream, { calcContentMd5: options.storeBlobContentMD5 });
+ self._uploadContentFromChunkStream(container, blob, blobType, chunkStream, streamLength, options, callback);
+ } else {
+ putBlockBlobFromStream();
+ }
+ };
+
+ if (!isNewBlob) {
+ if (options.storeBlobContentMD5 && blobType !== BlobConstants.BlobTypes.BLOCK) {
+ throw new Error(SR.MD5_NOT_POSSIBLE);
+ }
+
+ if (blobType === BlobConstants.BlobTypes.APPEND || options.accessConditions) {
+ // Do a getBlobProperties right at the beginning for existing blobs and use the user passed in access conditions.
+ // So any pre-condition failure on the first block (in a strictly single writer scenario) is caught.
+ // This call also helps us get the append position to append to if the user hasn’t specified an access condition.
+ this.getBlobProperties(container, blob, options, function (error, properties, response) {
+ if (error && !(options.accessConditions && options.accessConditions.EtagNonMatch === '*' && response.statusCode === 400)) {
+ callback(error);
+ } else {
+ if (blobType === BlobConstants.BlobTypes.APPEND) {
+ options.appendPosition = properties.contentLength;
+ }
+
+ startUpload();
+ }
+ });
+ } else {
+ startUpload();
+ }
+ } else {
+ startUpload();
+ }
+
+ return options.speedSummary;
+};
+
+/**
+* Upload blob content from a text. Assumes the blob already exists.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {bool} isNewBlob Specifies whether the blob is newly created.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param (string) content The blob text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback The callback function.
+* @return {SpeedSummary}
+*/
+BlobService.prototype._uploadBlobFromText = function (isNewBlob, container, blob, blobType, content, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+ options[HeaderConstants.CONTENT_TYPE] = (options.contentSettings && options.contentSettings.contentType) || 'text/plain;charset="utf-8"';
+
+ var self = this;
+ var startUpload = function () {
+ var operationFunc;
+ var length = azureutil.objectIsNull(content) ? 0 : (Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content));
+
+ if (blobType === BlobConstants.BlobTypes.BLOCK) {
+ // default to true, unless explicitly set to false
+ options.storeBlobContentMD5 = options.storeBlobContentMD5 === false ? false : true;
+ operationFunc = self._putBlockBlob;
+
+ if (length > BlobConstants.MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES) {
+ throw new RangeError(SR.INVALID_BLOB_LENGTH);
+ }
+ } else if (blobType === BlobConstants.BlobTypes.APPEND) {
+ operationFunc = self._appendBlock;
+
+ if (length > BlobConstants.MAX_APPEND_BLOB_BLOCK_SIZE) {
+ throw new RangeError(SR.INVALID_TEXT_LENGTH);
+ }
+ }
+
+ var finalCallback = function (error, blobResult, response) {
+ if (blobType !== BlobConstants.BlobTypes.BLOCK) {
+ self.setBlobProperties(container, blob, options.contentSettings, options, function (error, blob, response) {
+ blob = extend(false, blob, blobResult);
+ callback(error, blob, response);
+ });
+ } else {
+ callback(error, blobResult, response);
+ }
+ };
+
+ operationFunc.call(self, container, blob, content, null, length, options, finalCallback);
+ };
+
+ if (!isNewBlob) {
+ if (options.storeBlobContentMD5 && blobType !== BlobConstants.BlobTypes.BLOCK) {
+ throw new Error(SR.MD5_NOT_POSSIBLE);
+ }
+
+ if (blobType === BlobConstants.BlobTypes.APPEND || options.accessConditions) {
+ // Do a getBlobProperties right at the beginning for existing blobs and use the user passed in access conditions.
+ // So any pre-condition failure on the first block (in a strictly single writer scenario) is caught.
+ // This call also helps us get the append position to append to if the user hasn’t specified an access condition.
+ this.getBlobProperties(container, blob, options, function (error, properties) {
+ if (error) {
+ callback(error);
+ } else {
+ if (blobType === BlobConstants.BlobTypes.APPEND) {
+ options.appendPosition = properties.contentLength;
+ }
+
+ startUpload();
+ }
+ });
+ }
+ } else {
+ if (!azureutil.objectIsNull(content) && azureutil.objectIsNull(azureutil.tryGetValueChain(options, ['contentSettings', 'contentMD5'], null)) && options.storeBlobContentMD5) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], azureutil.getContentMd5(content));
+ }
+ startUpload();
+ }
+};
+
+/**
+* Uploads a block blob from a stream.
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} text The blob text.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} length The length of the stream or text to upload.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* information about the blob.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._putBlockBlob = function (container, blob, text, stream, length, options, callback) {
+ if (!options.speedSummary) {
+ options.speedSummary = new SpeedSummary(blob);
+ }
+
+ var speedSummary = options.speedSummary;
+ speedSummary.totalSize = length;
+
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withHeader(HeaderConstants.CONTENT_TYPE, 'application/octet-stream')
+ .withHeader(HeaderConstants.BLOB_TYPE, BlobConstants.BlobTypes.BLOCK)
+ .withHeader(HeaderConstants.CONTENT_LENGTH, length);
+
+ if (!azureutil.objectIsNull(text) && azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5) {
+ options.transactionalContentMD5 = azureutil.getContentMd5(text);
+ }
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ if (options.metadata) {
+ responseObject.blobResult.metadata = options.metadata;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ if (!returnObject || !returnObject.error) {
+ speedSummary.increment(length);
+ }
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ if (!azureutil.objectIsNull(text)) {
+ this.performRequest(webResource, text, options, processResponseCallback);
+ } else {
+ this.performRequestOutputStream(webResource, stream, options, processResponseCallback);
+ }
+
+ return options.speedSummary;
+};
+
+/**
+* Appends a new block to an append blob.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string|buffer} content The block content.
+* @param (Stream) stream The stream to the data to store.
+* @param {int} length The length of the stream or content to upload.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to.
+* @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] The blob’s MD5 hash. This hash is used to verify the integrity of the blob during transport.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._appendBlock = function (container, blob, content, stream, length, options, callback) {
+ var speedSummary = options.speedSummary || new SpeedSummary(blob);
+ speedSummary.totalSize = length;
+
+ var self = this;
+ var startAppendBlock = function () {
+ var resourceName = createResourceName(container, blob);
+
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'appendblock')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, length)
+ .withHeader(HeaderConstants.BLOB_CONDITION_MAX_SIZE, options.maxBlobSize)
+ .withHeader(HeaderConstants.BLOB_CONDITION_APPEND_POSITION, options.appendPosition);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ if (!returnObject || !returnObject.error) {
+ speedSummary.increment(length);
+ }
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ if (!azureutil.objectIsNull(content)) {
+ self.performRequest(webResource, content, options, processResponseCallback);
+ } else {
+ self.performRequestOutputStream(webResource, stream, options, processResponseCallback);
+ }
+ };
+
+ if (azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5) {
+ if (!azureutil.objectIsNull(content)) {
+ options.transactionalContentMD5 = azureutil.getContentMd5(content);
+ startAppendBlock();
+ } else {
+ azureutil.calculateMD5(stream, length, options, function (internalBuff, contentMD5) {
+ options.transactionalContentMD5 = contentMD5;
+ content = internalBuff;
+ length = internalBuff.length;
+ startAppendBlock();
+ });
+ }
+ } else {
+ startAppendBlock();
+ }
+
+ return options.speedSummary;
+};
+
+/**
+* Creates and dispatches lease requests.
+* @ignore
+*
+* @this {BlobService}
+* @param {object} webResource The web resource.
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} leaseId The lease identifier. Required to renew, change or release the lease.
+* @param {string} leaseAction The lease action (BlobConstants.LeaseOperation.*). Required.
+* @param {object} userOptions The request options.
+* @param {int} [userOptions.leaseBreakPeriod] The lease break period.
+* @param {string} [userOptions.leaseDuration] The lease duration. Default is never to expire.
+* @param {string} [userOptions.proposedLeaseId] The proposed lease identifier. This is required for the CHANGE lease action.
+* @param {LocationMode} [userOptions.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {int} [userOptions.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [userOptions.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, lease, response)} callback `error` will contain information
+* if an error occurs; otherwise `lease` will contain
+* the lease information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._leaseImpl = function (container, blob, leaseId, leaseAction, options, callback) {
+ var webResource;
+ if (!azureutil.objectIsNull(blob)) {
+ validate.validateArgs('_leaseImpl', function (v) {
+ v.string(blob, 'blob');
+ });
+ var resourceName = createResourceName(container, blob);
+ webResource = WebResource.put(resourceName);
+ } else {
+ webResource = WebResource.put(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container');
+ }
+
+ webResource.withQueryOption(QueryStringConstants.COMP, 'lease')
+ .withHeader(HeaderConstants.LEASE_ID, leaseId)
+ .withHeader(HeaderConstants.LEASE_ACTION, leaseAction.toLowerCase())
+ .withHeader(HeaderConstants.LEASE_BREAK_PERIOD, options.leaseBreakPeriod)
+ .withHeader(HeaderConstants.PROPOSED_LEASE_ID, options.proposedLeaseId)
+ .withHeader(HeaderConstants.LEASE_DURATION, options.leaseDuration);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.leaseResult = null;
+ if (!responseObject.error) {
+ responseObject.leaseResult = new LeaseResult(container, blob);
+ responseObject.leaseResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.leaseResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Updates a page blob from text.
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} text The text string.
+* @param {Readable} readStream The Node.js Readable stream.
+* @param {int} rangeStart The range start.
+* @param {int} rangeEnd The range end.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The target blob lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the page content. This hash is used to verify the integrity of the page during transport.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, pageBlob, response)} callback `error` will contain information
+* if an error occurs; otherwise `pageBlob` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._createPages = function (container, blob, text, readStream, rangeStart, rangeEnd, options, callback) {
+ var request = this._updatePageBlobPagesImpl(container, blob, rangeStart, rangeEnd, BlobConstants.PageWriteOptions.UPDATE, options);
+
+ // At this point, we have already validated that the range is less than 4MB. Therefore, we just need to calculate the contentMD5 if required.
+ // Even when this is called from the createPagesFromStream method, it is pre-buffered and called with text.
+ if (!azureutil.objectIsNull(text) && azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5) {
+ request.withHeader(HeaderConstants.CONTENT_MD5, azureutil.getContentMd5(text));
+ }
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ if (!azureutil.objectIsNull(text)) {
+ this.performRequest(request, text, options, processResponseCallback);
+ } else {
+ this.performRequestOutputStream(request, readStream, options, processResponseCallback);
+ }
+};
+
+/**
+* @ignore
+*/
+BlobService.prototype._updatePageBlobPagesImpl = function (container, blob, rangeStart, rangeEnd, writeMethod, options) {
+ if (rangeStart && rangeStart % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_START_OFFSET);
+ }
+
+ if (rangeEnd && (rangeEnd + 1) % BlobConstants.PAGE_SIZE !== 0) {
+ throw new RangeError(SR.INVALID_PAGE_END_OFFSET);
+ }
+
+ // this is necessary if this is called from _uploadContentFromChunkStream->_createPages
+ if (!options) {
+ options = {};
+ }
+
+ options.rangeStart = rangeStart;
+ options.rangeEnd = rangeEnd;
+
+ options.contentLength = writeMethod === BlobConstants.PageWriteOptions.UPDATE ? (rangeEnd - rangeStart) + 1 : 0;
+
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'page')
+ .withHeader(HeaderConstants.CONTENT_TYPE, 'application/octet-stream')
+ .withHeader(HeaderConstants.PAGE_WRITE, writeMethod);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ return webResource;
+};
+
+/**
+* Uploads blob content from a stream.
+* For block blob, it creates a new block to be committed.
+* For page blob, it writes a range of pages.
+* For append blob, it appends a new block.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} blobType The blob type.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object|function} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to.
+* @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {function(error, null)} callback The callback function.
+* @return {SpeedSummary}
+*/
+
+BlobService.prototype._uploadContentFromChunkStream = function (container, blob, blobType, chunkStream, streamLength, options, callback) {
+ this.logger.debug(util.format('_uploadContentFromChunkStream for blob %s', blob));
+
+ var apiName;
+ var isBlockBlobUpload;
+ var isPageBlobUpload;
+ var isAppendBlobUpload;
+ var sizeLimitation;
+ var originalContentMD5 = azureutil.tryGetValueChain(options, ['contentSettings', 'contentMD5'], null);
+ var parallelOperationThreadCount = options.parallelOperationThreadCount || this.parallelOperationThreadCount;
+
+ if (blobType == BlobConstants.BlobTypes.BLOCK) {
+ apiName = 'createBlockFromText';
+ isBlockBlobUpload = true;
+
+ // BlockBlob can only have 50000 blocks in maximum
+ var minBlockSize = Math.ceil(streamLength / 50000);
+ if (options.blockSize) {
+ if (options.blockSize < minBlockSize) {
+ // options.blockSize is less than the minBlockSize, error callback
+ var error = new ArgumentError('options.blockSize', util.format('The minimum blockSize is %s and the provided blockSize %s is too small.', minBlockSize, options.blockSize));
+ callback(error);
+ return;
+ } else {
+ sizeLimitation = options.blockSize;
+ }
+ } else {
+ // 4MB minimum for auto-calculated block size
+ sizeLimitation = Math.max(minBlockSize, BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES);
+ }
+ } else if (blobType == BlobConstants.BlobTypes.PAGE) {
+ apiName = '_createPages';
+ isPageBlobUpload = true;
+ sizeLimitation = BlobConstants.DEFAULT_WRITE_PAGE_SIZE_IN_BYTES;
+ } else if (blobType == BlobConstants.BlobTypes.APPEND) {
+ apiName = 'appendBlockFromText';
+ isAppendBlobUpload = true;
+ parallelOperationThreadCount = 1;
+ sizeLimitation = BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES;
+ } else {
+ var error = new ArgumentError('blobType', util.format('Unknown blob type %s', blobType));
+ callback(error);
+ return;
+ }
+
+ chunkStream._highWaterMark = sizeLimitation;
+
+ this._setOperationExpiryTime(options);
+
+ // initialize the speed summary
+ var speedSummary = options.speedSummary || new SpeedSummary(blob);
+ speedSummary.totalSize = streamLength;
+
+ // initialize chunk allocator
+ var allocator = new ChunkAllocator(sizeLimitation, parallelOperationThreadCount, { logger: this.logger });
+ chunkStream.setMemoryAllocator(allocator);
+ chunkStream.setOutputLength(streamLength);
+
+ // if this is a FileReadStream, set the allocator on that stream
+ if (chunkStream._stream && chunkStream._stream.setMemoryAllocator) {
+ var fileReadStreamAllocator = new ChunkAllocator(chunkStream._stream._highWaterMark, parallelOperationThreadCount, { logger: this.logger });
+ chunkStream._stream.setMemoryAllocator(fileReadStreamAllocator);
+ }
+
+ // initialize batch operations
+ var batchOperations = new BatchOperation(apiName, {
+ callInOrder: isAppendBlobUpload,
+ callbackInOrder: isAppendBlobUpload,
+ logger: this.logger,
+ enableReuseSocket: this.defaultEnableReuseSocket,
+ operationMemoryUsage: sizeLimitation
+ });
+ batchOperations.setConcurrency(parallelOperationThreadCount);
+
+ // initialize options
+ var rangeOptions = {
+ leaseId: options.leaseId,
+ timeoutIntervalInMs: options.timeoutIntervalInMs,
+ clientRequestTimeoutInMs: options.clientRequestTimeoutInMs,
+ operationExpiryTime: options.operationExpiryTime,
+ maxBlobSize: options.maxBlobSize,
+ appendPosition: options.appendPosition || 0,
+ initialAppendPosition: options.appendPosition || 0,
+ absorbConditionalErrorsOnRetry: options.absorbConditionalErrorsOnRetry
+ };
+
+ // initialize block blob variables
+ var blockIdPrefix = options.blockIdPrefix || this.generateBlockIdPrefix();
+ var blockCount = 0;
+ var blockIds = [];
+ var blobResult = {};
+
+ var self = this;
+ chunkStream.on('data', function (data, range) {
+ var operation = null;
+ var full = false;
+ var autoIncrement = speedSummary.getAutoIncrementFunction(data.length);
+
+ if (data.length > sizeLimitation) {
+ throw new RangeError(util.format(SR.EXCEEDED_SIZE_LIMITATION, sizeLimitation, data.length));
+ }
+
+ if (options.useTransactionalMD5) {
+ //calculate content md5 for the current uploading block data
+ var contentMD5 = azureutil.getContentMd5(data);
+ rangeOptions.transactionalContentMD5 = contentMD5;
+ }
+
+ var checkLengthLimit = function () {
+ if (!streamLength) return true;
+ if (range.start >= streamLength) {
+ self.logger.debug(util.format('Stop uploading data from %s bytes to %s bytes to blob %s because of limit %s', range.start, range.end, blob, streamLength));
+ chunkStream.stop();
+ return false;
+ } else if (range.end >= streamLength) {
+ self.logger.debug(util.format('Clip uploading data from %s bytes to %s bytes to blob %s because of limit %s', range.start, range.end, blob, streamLength));
+ range.end = streamLength - 1;
+ data = data.slice(0, streamLength - range.start);
+ if (options.useTransactionalMD5) {
+ rangeOptions.transactionalContentMD5 = azureutil.getContentMd5(data);
+ }
+ }
+ return true;
+ };
+
+ var uploadBlockBlobChunk = function () {
+ if (!checkLengthLimit()) return;
+ var blockId = self.getBlockId(blockIdPrefix, blockCount);
+ blockIds.push(blockId);
+
+ operation = new BatchOperation.RestOperation(self, apiName, blockId, container, blob, data, rangeOptions, function (error) {
+ if (!error) {
+ autoIncrement();
+ } else {
+ self.logger.debug(util.format('Stop uploading data as error happens. Error: %s', util.inspect(error)));
+ chunkStream.stop();
+ }
+ allocator.releaseBuffer(data);
+ data = null;
+ });
+
+ blockCount++;
+ };
+
+ var uploadPageBlobChunk = function () {
+ if (!checkLengthLimit()) return;
+
+ if (azureutil.isBufferAllZero(data)) {
+ self.logger.debug(util.format('Skip upload data from %s bytes to %s bytes to blob %s', range.start, range.end, blob));
+ speedSummary.increment(data.length);
+ } else {
+ self.logger.debug(util.format('Upload data from %s bytes to %s bytes to blob %s', range.start, range.end, blob));
+ operation = new BatchOperation.RestOperation(self, apiName, container, blob, data, null, range.start, range.end, rangeOptions, function (error) {
+ if (!error) {
+ autoIncrement();
+ } else {
+ self.logger.debug(util.format('Stop uploading data as error happens. Error: %s', util.inspect(error)));
+ chunkStream.stop();
+ }
+ allocator.releaseBuffer(data);
+ data = null;
+ });
+ }
+ };
+
+ var uploadAppendBlobChunk = function () {
+ if (!checkLengthLimit()) return;
+
+ rangeOptions.appendPosition = Number(rangeOptions.initialAppendPosition) + Number(range.start);
+
+ // We cannot differentiate between max size condition failing only in the retry versus failing in the first attempt and retry.
+ // So we will eliminate the latter and handle the former in the append operation callback.
+ if (options.maxBlobSize && rangeOptions.appendPosition + data.length > options.maxBlobSize) {
+ throw new Error(SR.MAX_BLOB_SIZE_CONDITION_NOT_MEET);
+ }
+
+ operation = new BatchOperation.RestOperation(self, apiName, container, blob, data, rangeOptions, function (error, currentBlob) {
+ if (!error) {
+ autoIncrement();
+ } else {
+ self.logger.debug(util.format('Stop uploading data as error happens. Error: %s', util.inspect(error)));
+ chunkStream.stop();
+ }
+ blobResult = currentBlob;
+ allocator.releaseBuffer(data);
+ data = null;
+ });
+ };
+
+ if (isBlockBlobUpload) {
+ uploadBlockBlobChunk();
+ } else if (isAppendBlobUpload) {
+ uploadAppendBlobChunk();
+ } else if (isPageBlobUpload) {
+ uploadPageBlobChunk();
+ }
+
+ if (operation) {
+ full = batchOperations.addOperation(operation);
+ operation = null;
+
+ if (full) {
+ self.logger.debug('File stream paused');
+ chunkStream.pause();
+ }
+ }
+ });
+
+ chunkStream.on('end', function () {
+ self.logger.debug(util.format('File read stream ended for blob %s', blob));
+ batchOperations.enableComplete();
+ });
+
+ batchOperations.on('drain', function () {
+ self.logger.debug('file stream resume');
+ chunkStream.resume();
+ });
+
+ batchOperations.on('end', function (error) {
+ self.logger.debug('batch operations commited');
+
+ speedSummary = null;
+ if (error) {
+ callback(error);
+ return;
+ }
+
+ if (originalContentMD5) {
+ options.contentSettings.contentMD5 = originalContentMD5;
+ } else if (options.storeBlobContentMD5) {
+ var contentMD5 = chunkStream.getContentMd5('base64');
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], contentMD5);
+ }
+
+ if (isBlockBlobUpload) {
+ //commit block list
+ var blockList = { 'UncommittedBlocks': blockIds };
+ self.commitBlocks(container, blob, blockList, options, function (error, blockList, response) {
+ self.logger.debug(util.format('Blob %s committed', blob));
+
+ if (error) {
+ chunkStream.finish();
+
+ callback(error);
+ } else {
+ blobResult['commmittedBlocks'] = blockIds;
+
+ chunkStream.finish();
+ callback(error, blobResult, response);
+ }
+ });
+ } else {
+ // upload page blob or append blob completely
+ var blobProperties = options.contentSettings;
+ self.setBlobProperties(container, blob, blobProperties, function (error, blob, response) {
+ chunkStream.finish();
+ blob = extend(false, blob, blobResult);
+ callback(error, blob, response);
+ });
+ }
+ });
+
+ return speedSummary;
+};
+
+/**
+* Checks whether or not a container exists on the service.
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the container information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._doesContainerExist = function (container, primaryOnly, options, callback) {
+ var webResource = WebResource.head(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ if (primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = new ContainerResult(container);
+ if (!responseObject.error) {
+ responseObject.containerResult.exists = true;
+ responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.containerResult.exists = false;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.containerResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks whether or not a blob exists on the service.
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the blob information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._doesBlobExist = function (container, blob, primaryOnly, options, callback) {
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.head(resourceName)
+ .withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId)
+ .withHeader(HeaderConstants.LEASE_ID, options.leaseId);
+
+ if (primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ if (!responseObject.error) {
+ responseObject.blobResult.exists = true;
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.blobResult.exists = false;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* @ignore
+*/
+BlobService.prototype._setBlobPropertiesHelper = function (settings) {
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(settings.container, settings.blob);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ settings.callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(settings.webResource, null, settings.options, processResponseCallback);
+};
+
+/**
+* @ignore
+*/
+BlobService.prototype._validateLengthAndMD5 = function (options, responseObject) {
+ var storedMD5 = responseObject.response.headers[Constants.HeaderConstants.CONTENT_MD5];
+ var contentLength;
+
+ if (!azureutil.objectIsNull(responseObject.response.headers[Constants.HeaderConstants.CONTENT_LENGTH])) {
+ contentLength = parseInt(responseObject.response.headers[Constants.HeaderConstants.CONTENT_LENGTH], 10);
+ }
+
+ // If the user has not specified this option, the default value should be false.
+ if (azureutil.objectIsNull(options.disableContentMD5Validation)) {
+ options.disableContentMD5Validation = false;
+ }
+
+ // None of the below cases should be retried. So set the error in every case so the retry policy filter handle knows that it shouldn't be retried.
+ if (options.disableContentMD5Validation === false && options.useTransactionalMD5 === true && azureutil.objectIsNull(storedMD5)) {
+ responseObject.error = new StorageError(SR.MD5_NOT_PRESENT_ERROR);
+ responseObject.retryable = false;
+ }
+
+ // Validate length and if required, MD5.
+ // If getBlobToText called this method, then the responseObject.length and responseObject.contentMD5 are not set. Calculate them first using responseObject.response.body and then validate.
+ if (azureutil.objectIsNull(responseObject.length)) {
+ if (typeof responseObject.response.body == 'string') {
+ responseObject.length = Buffer.byteLength(responseObject.response.body);
+ } else if (Buffer.isBuffer(responseObject.response.body)) {
+ responseObject.length = responseObject.response.body.length;
+ }
+ }
+
+ if (!azureutil.objectIsNull(contentLength) && responseObject.length !== contentLength) {
+ responseObject.error = new Error(SR.CONTENT_LENGTH_MISMATCH);
+ responseObject.retryable = false;
+ }
+
+ if (options.disableContentMD5Validation === false && azureutil.objectIsNull(responseObject.contentMD5)) {
+ responseObject.contentMD5 = azureutil.getContentMd5(responseObject.response.body);
+ }
+
+ if (options.disableContentMD5Validation === false && !azureutil.objectIsNull(storedMD5) && storedMD5 !== responseObject.contentMD5) {
+ responseObject.error = new Error(util.format(SR.HASH_MISMATCH, storedMD5, responseObject.contentMD5));
+ responseObject.retryable = false;
+ }
+};
+
+/**
+* @ignore
+*/
+BlobService.prototype._setRangeContentMD5Header = function (webResource, options) {
+ if (!azureutil.objectIsNull(options.rangeStart) && options.useTransactionalMD5) {
+ if (azureutil.objectIsNull(options.rangeEnd)) {
+ throw new ArgumentNullError('options.rangeEndHeader', util.format(SR.ARGUMENT_NULL_OR_EMPTY, options.rangeEndHeader));
+ }
+
+ var size = parseInt(options.rangeEnd, 10) - parseInt(options.rangeStart, 10) + 1;
+ if (size > BlobConstants.MAX_RANGE_GET_SIZE_WITH_MD5) {
+ throw new ArgumentError('options', SR.INVALID_RANGE_FOR_MD5);
+ } else {
+ webResource.withHeader(HeaderConstants.RANGE_GET_CONTENT_MD5, 'true');
+ }
+ }
+};
+
+/**
+* Downloads a blockblob, pageblob or appendblob into a range stream.
+* @ignore
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} blobType The type of blob to download: block blob, page blob or append blob.
+* @param {Writable} writeStream The Node.js Writable stream.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype._getBlobToRangeStream = function (container, blob, blobType, writeStream, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ validate.validateArgs('_getBlobToRangeStream', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.blobNameIsValid(container, blob);
+ v.blobTypeIsValid(blobType);
+ v.callback(callback);
+ });
+
+ var rangeStream = null;
+ var isPageBlobDownload = true;
+
+ if (blobType == BlobConstants.BlobTypes.PAGE) {
+ rangeStream = new PageRangeStream(this, container, blob, options);
+ } else if (blobType == BlobConstants.BlobTypes.APPEND) {
+ rangeStream = new RangeStream(this, container, blob, options);
+ isPageBlobDownload = false;
+ } else if (blobType == BlobConstants.BlobTypes.BLOCK) {
+ rangeStream = new BlockRangeStream(this, container, blob, options);
+ isPageBlobDownload = false;
+ }
+
+ if (!options.speedSummary) {
+ options.speedSummary = new SpeedSummary(blob);
+ }
+
+ var speedSummary = options.speedSummary;
+ var parallelOperationThreadCount = options.parallelOperationThreadCount || this.parallelOperationThreadCount;
+ var batchOperations = new BatchOperation('getBlobInRanges', { callbackInOrder: true, logger: this.logger, enableReuseSocket: this.defaultEnableReuseSocket });
+ batchOperations.setConcurrency(parallelOperationThreadCount);
+
+ var self = this;
+ var checkMD5sum = !options.disableContentMD5Validation;
+ var md5Hash = null;
+ if (checkMD5sum) {
+ md5Hash = new Md5Wrapper().createMd5Hash();
+ }
+
+ var savedBlobResult = null;
+ var savedBlobResponse = null;
+
+ rangeStream.on('range', function (range) {
+ if (!speedSummary.totalSize) {
+ speedSummary.totalSize = rangeStream.rangeSize;
+ }
+
+ var requestOptions = {
+ rangeStart: range.start,
+ rangeEnd: range.end,
+ responseEncoding: null //Use Buffer to store the response data
+ };
+
+ var rangeSize = range.size;
+ requestOptions.timeoutIntervalInMs = options.timeoutIntervalInMs;
+ requestOptions.clientRequestTimeoutInMs = options.clientRequestTimeoutInMs;
+ requestOptions.useTransactionalMD5 = options.useTransactionalMD5;
+ requestOptions.snapshotId = options.snapshotId;
+
+ if (range.dataSize === 0) {
+ if (isPageBlobDownload) {
+ var autoIncrement = speedSummary.getAutoIncrementFunction(rangeSize);
+ //No operation to do and only wait for write zero to file in callback
+ var writeZeroOperation = new BatchOperation.CommonOperation(BatchOperation.noOperation, function (error) {
+ if (error) return;
+ var bufferAvailable = azureutil.writeZerosToStream(writeStream, rangeSize, md5Hash, autoIncrement);
+ //There is no need to pause the rangestream since we can perform http request and write disk at the same time
+ self.logger.debug(util.format('Write %s bytes Zero from %s to %s', rangeSize, range.start, range.end));
+ if (!bufferAvailable) {
+ self.logger.debug('Write stream is full and pause batch operation');
+ batchOperations.pause();
+ }
+ });
+ batchOperations.addOperation(writeZeroOperation);
+ } else {
+ self.logger.debug(util.format('Can not read %s bytes to %s bytes of blob %s', range.start, range.end, blob));
+ }
+ return;
+ }
+
+ if (range.start > range.end) {
+ return;
+ }
+
+ var operation = new BatchOperation.RestOperation(self, 'getBlobToText', container, blob, requestOptions, function (error, content, blobResult, response) {
+ if (!error) {
+ if (rangeSize !== content.length) {
+ self.logger.warn(util.format('Request %s bytes, but server returns %s bytes', rangeSize, content.length));
+ }
+ //Save one of the succeeded callback parameters and use them at the final callback
+ if (!savedBlobResult) {
+ savedBlobResult = blobResult;
+ }
+ if (!savedBlobResponse) {
+ savedBlobResponse = response;
+ }
+ var autoIncrement = speedSummary.getAutoIncrementFunction(content.length);
+ var bufferAvailable = writeStream.write(content, autoIncrement);
+ if (!bufferAvailable) {
+ self.logger.debug('Write stream is full and pause batch operation');
+ batchOperations.pause();
+ }
+ if (md5Hash) {
+ md5Hash.update(content);
+ }
+ content = null;
+ } else {
+ self.logger.debug(util.format('Stop downloading data as error happens. Error: %s', util.inspect(error)));
+ rangeStream.stop();
+ }
+ });
+
+ var full = batchOperations.addOperation(operation);
+ if (full) {
+ self.logger.debug('Pause range stream');
+ rangeStream.pause();
+ }
+ });
+
+ rangeStream.on('end', function () {
+ self.logger.debug('Range stream has ended.');
+ batchOperations.enableComplete();
+ });
+
+ batchOperations.on('drain', function () {
+ self.logger.debug('Resume range stream');
+ rangeStream.resume();
+ });
+
+ writeStream.on('drain', function () {
+ self.logger.debug('Resume batch operations');
+ batchOperations.resume();
+ });
+
+ batchOperations.on('end', function (error) {
+ self.logger.debug('Download completed!');
+ if (error) {
+ callback(error);
+ return;
+ } else {
+ writeStream.end(function () {
+ self.logger.debug('Write stream has ended');
+ if (!savedBlobResult) {
+ savedBlobResult = {};
+ }
+
+ azureutil.setObjectInnerPropertyValue(savedBlobResult, ['contentSettings', 'contentMD5'], azureutil.tryGetValueChain(options, ['contentSettings', 'contentMD5'], null));
+ savedBlobResult.clientSideContentMD5 = null;
+ if (md5Hash) {
+ savedBlobResult.clientSideContentMD5 = md5Hash.digest('base64');
+ }
+ callback(error, savedBlobResult, savedBlobResponse);
+ });
+ }
+ });
+
+ var listOptions = {
+ timeoutIntervalInMs: options.timeoutIntervalInMs,
+ clientRequestTimeoutInMs: options.clientRequestTimeoutInMs,
+ snapshotId: options.snapshotId,
+ leaseId: options.leaseId,
+ blockListFilter: BlobUtilities.BlockListFilter.COMMITTED
+ };
+
+ rangeStream.list(listOptions, function (error) {
+ callback(error);
+ });
+
+ return speedSummary;
+};
+
+/**
+* Downloads a blockblob or pageblob into a stream.
+* @ignore
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {Writable} writeStream The Node.js Writable stream.
+* @param {object} [options] The request options.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the blob information.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._getBlobToStream = function (container, blob, writeStream, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ var resourceName = createResourceName(container, blob);
+ var webResource = WebResource.get(resourceName).withRawResponse();
+
+ var options = extend(true, {}, userOptions);
+ webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId);
+
+ BlobResult.setHeadersFromBlob(webResource, options);
+
+ this._setRangeContentMD5Header(webResource, options);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.blobResult = null;
+
+ if (!responseObject.error) {
+ responseObject.blobResult = new BlobResult(container, blob);
+ responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ self._validateLengthAndMD5(options, responseObject);
+
+ if (options.speedSummary) {
+ options.speedSummary.increment(responseObject.length);
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.blobResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequestInputStream(webResource, null, writeStream, options, processResponseCallback);
+};
+
+/**
+* Lists a segment containing a collection of blob items whose names begin with the specified prefix in the container.
+* @ignore
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} prefix The prefix of the blob name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {ListBlobTypes} listBlobType Specifies the item type of the results.
+* @param {object} [options] The request options.
+* @param {int} [options.maxResults] Specifies the maximum number of blobs to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {string} [options.include] Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs', 'copy', 'deleted').
+* Please find these values in BlobUtilities.BlobListingDetails. Multiple values can be added separated with a comma (,).
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the entries of blobs and the continuation token for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+BlobService.prototype._listBlobsOrDircotriesSegmentedWithPrefix = function (container, prefix, currentToken, listBlobType, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listBlobsSegmented', function (v) {
+ v.string(container, 'container');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(container)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'container')
+ .withQueryOption(QueryStringConstants.COMP, 'list')
+ .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults)
+ .withQueryOptions(options,
+ QueryStringConstants.DELIMITER,
+ QueryStringConstants.INCLUDE);
+
+ if (!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker);
+ }
+
+ webResource.withQueryOption(QueryStringConstants.PREFIX, prefix);
+
+ options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.listBlobsResult = null;
+ if (!responseObject.error) {
+ responseObject.listBlobsResult = {
+ entries: null,
+ continuationToken: null
+ };
+
+ responseObject.listBlobsResult.entries = [];
+ var results = [];
+
+ if (listBlobType == BlobConstants.ListBlobTypes.Directory && responseObject.response.body.EnumerationResults.Blobs.BlobPrefix) {
+ results = responseObject.response.body.EnumerationResults.Blobs.BlobPrefix;
+ if (!_.isArray(results)) {
+ results = [results];
+ }
+ } else if (listBlobType == BlobConstants.ListBlobTypes.Blob && responseObject.response.body.EnumerationResults.Blobs.Blob) {
+ results = responseObject.response.body.EnumerationResults.Blobs.Blob;
+ if (!_.isArray(results)) {
+ results = [results];
+ }
+ }
+
+ results.forEach(function (currentBlob) {
+ var blobResult = BlobResult.parse(currentBlob);
+ responseObject.listBlobsResult.entries.push(blobResult);
+ });
+
+ if (responseObject.response.body.EnumerationResults.NextMarker) {
+ responseObject.listBlobsResult.continuationToken = {
+ nextMarker: null,
+ targetLocation: null
+ };
+
+ responseObject.listBlobsResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker;
+ responseObject.listBlobsResult.continuationToken.targetLocation = responseObject.targetLocation;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.listBlobsResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Create a new blob.
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param {int} size The blob size.
+* @param {object} [options] The request options.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {errorOrResult} callback The callback which operates on the specific blob.
+*/
+BlobService.prototype._createBlob = function (container, blob, blobType, size, options, creationCallback) {
+ if (blobType == BlobConstants.BlobTypes.APPEND) {
+ this.createOrReplaceAppendBlob(container, blob, options, function (createError, createResponse) {
+ creationCallback(createError, null, createResponse);
+ });
+ } else if (blobType == BlobConstants.BlobTypes.PAGE) {
+ this.createPageBlob(container, blob, size, options, function (createError) {
+ creationCallback(createError);
+ });
+ } else if (blobType == BlobConstants.BlobTypes.BLOCK) {
+ creationCallback();
+ }
+};
+
+/**
+* The callback for {BlobService~getBlobToText}.
+* @typedef {function} BlobService~blobToText
+* @param {object} error If an error occurs, the error information.
+* @param {string} text The text returned from the blob.
+* @param {object} blockBlob Information about the blob.
+* @param {object} response Information related to this operation.
+*/
+
+BlobService.SpeedSummary = SpeedSummary;
+
+module.exports = BlobService;
diff --git a/src/node_modules/azure-storage/lib/services/blob/blobservice.node.js b/src/node_modules/azure-storage/lib/services/blob/blobservice.node.js
new file mode 100644
index 0000000..32a43fb
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/blobservice.node.js
@@ -0,0 +1,475 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../common/common.node');
+var BlobService = require('./blobservice.core');
+var extend = require('extend');
+var fs = require('fs');
+var mime = require('browserify-mime');
+
+var azureutil = azureCommon.util;
+var Constants = azureCommon.Constants;
+var FileReadStream = azureCommon.FileReadStream;
+var SpeedSummary = azureCommon.SpeedSummary;
+var validate = azureCommon.validate;
+var BlobConstants = Constants.BlobConstants;
+
+/**
+* Downloads a blob into a file.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} localFileName The local path to the file to be downloaded.
+* @param {object} [options] The request options.
+* @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download.
+* Set the option to true for small blobs.
+* Parallel download and speed summary won't work with this option on.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link BlobResult}` will contain the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*
+* @example
+* var azure = require('azure-storage');
+* var blobService = azure.createBlobService();
+* blobService.getBlobToLocalFile('taskcontainer', 'task1', 'task1-download.txt', function(error, serverBlob) {
+* if(!error) {
+* // Blob available in serverBlob.blob variable
+* }
+*/
+BlobService.prototype.getBlobToLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+
+ validate.validateArgs('getBlobToLocalFile', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.string(localFileName, 'localFileName');
+ v.containerNameIsValid(container);
+ v.callback(callback);
+ });
+
+ return this._getBlobToLocalFile(container, blob, localFileName, options, callback);
+};
+
+/**
+* Uploads a page blob from file. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} localFileName The local path to the file to be uploaded.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+* The default value is false for page blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createPageBlobFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) {
+ return this._createBlobFromLocalFile(container, blob, BlobConstants.BlobTypes.PAGE, localFileName, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new block blob. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} localFileName The local path to the file to be uploaded.
+* @param {object} [options] The request options.
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createBlockBlobFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) {
+ return this._createBlobFromLocalFile(container, blob, BlobConstants.BlobTypes.BLOCK, localFileName, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new append blob from a local file. If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* If you want to append data to an already existing blob, please look at appendFromLocalFile.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} localFileName The local path to the file to be uploaded.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 ahash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.createAppendBlobFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) {
+ return this._createBlobFromLocalFile(container, blob, BlobConstants.BlobTypes.APPEND, localFileName, optionsOrCallback, callback);
+};
+
+/**
+* Appends to an append blob from a local file. Assumes the blob already exists on the service.
+* This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+* If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} localFileName The local path to the file to be uploaded.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+* the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+BlobService.prototype.appendFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('appendFromLocalFile', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.string(localFileName, 'localFileName');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+
+ var self = this;
+ fs.stat(localFileName, function (error, stat) {
+ if (error) {
+ callback(error);
+ } else {
+ var stream = new FileReadStream(localFileName, { calcContentMd5: options.storeBlobContentMD5 });
+ var streamCallback = function (appendError, blob, response) {
+ if (azureutil.objectIsFunction(stream.destroy)) {
+ stream.destroy();
+ }
+ callback(appendError, blob, response);
+ };
+
+ try {
+ self._uploadBlobFromStream(false, container, blob, BlobConstants.BlobTypes.APPEND, stream, stat.size, options, streamCallback);
+ } catch (err) {
+ callback(err);
+ }
+ }
+ });
+
+ return options.speedSummary;
+};
+
+// Private methods
+
+/**
+* Creates a new blob (Block/Page/Append). If the blob already exists on the service, it will be overwritten.
+* To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+*
+* @ignore
+*
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {BlobType} blobType The blob type.
+* @param {string} localFileName The local path to the file to be uploaded.
+* @param {object} [options] The request options.
+* @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only)
+* @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+* @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only)
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+* @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+* @param {object} [options.contentSettings] The content settings of the blob.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The MD5 hash of the blob content.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback The callback function.
+*
+* @return {SpeedSummary}
+*
+*/
+BlobService.prototype._createBlobFromLocalFile = function (container, blob, blobType, localFileName, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_createBlobFromLocalFile', function (v) {
+ v.string(container, 'container');
+ v.string(blob, 'blob');
+ v.containerNameIsValid(container);
+ v.blobTypeIsValid(blobType);
+ v.string(localFileName, 'localFileName');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+
+ var self = this;
+ var size = 0;
+
+ var creationCallback = function (createError, createBlob, createResponse) {
+ if (createError) {
+ callback(createError, createBlob, createResponse);
+ } else {
+ // Automatically detect the mime type
+ if(azureutil.tryGetValueChain(options, ['contentSettings','contentType'], undefined) === undefined) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings','contentType'], mime.lookup(localFileName));
+ }
+
+ var stream = new FileReadStream(localFileName, { calcContentMd5: options.storeBlobContentMD5 });
+ var streamCallback = function (createError, createBlob, createResponse) {
+ if (azureutil.objectIsFunction(stream.destroy)) {
+ stream.destroy();
+ }
+ callback(createError, createBlob, createResponse);
+ };
+ self._uploadBlobFromStream(true, container, blob, blobType, stream, size, options, streamCallback);
+ }
+ };
+
+ // Check the file size to determine the upload method: single request or chunks
+ fs.stat(localFileName, function (error, stat) {
+ if (error) {
+ callback(error);
+ } else {
+ size = stat.size;
+ try {
+ self._createBlob(container, blob, blobType, size, options, creationCallback);
+ } catch (err) {
+ callback(err);
+ }
+ }
+ });
+
+ return options.speedSummary;
+};
+
+/**
+* Downloads a blob into a file.
+* @ignore
+* @this {BlobService}
+* @param {string} container The container name.
+* @param {string} blob The blob name.
+* @param {string} localFileName The local path to the file to be downloaded.
+* @param {object} [options] The request options.
+* @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download.
+* Set the option to true for small blobs.
+* Parallel download and speed summary won't work with this option on.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.snapshotId] The snapshot identifier.
+* @param {string} [options.leaseId] The lease identifier.
+* @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the blob information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*
+*/
+BlobService.prototype._getBlobToLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) {
+ var options;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; });
+ options.speedSummary = options.speedSummary || new SpeedSummary(blob);
+
+ var writeStream = fs.createWriteStream(localFileName, { 'highWaterMark': BlobConstants.MAX_QUEUED_WRITE_DISK_BUFFER_SIZE });
+ writeStream.on('error', function (error) {
+ callback(error);
+ });
+
+ this.getBlobToStream(container, blob, writeStream, options, function (error, responseBlob, response) {
+ if (error) {
+ var onErrorCallback = function() {
+ // If the download failed from the beginning, remove the file.
+ if (fs.existsSync(localFileName) && writeStream.bytesWritten === 0) {
+ fs.unlinkSync(localFileName);
+ }
+ callback(error, responseBlob, response);
+ };
+ if (!writeStream.closed) {
+ writeStream.end(onErrorCallback);
+ } else {
+ onErrorCallback();
+ }
+ } else {
+ callback(error, responseBlob, response);
+ }
+ });
+
+ return options.speedSummary;
+};
+
+module.exports = BlobService;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/blob/blobutilities.js b/src/node_modules/azure-storage/lib/services/blob/blobutilities.js
new file mode 100644
index 0000000..9b3f9e6
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/blobutilities.js
@@ -0,0 +1,136 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'BlobUtilities'.
+exports = module.exports;
+
+/**
+* Defines constants, enums, and utility functions for use with the Blob service.
+* @namespace BlobUtilities
+*/
+var BlobUtilities = {
+ /**
+ * Permission types
+ *
+ * @const
+ * @enum {string}
+ */
+ SharedAccessPermissions: {
+ READ: 'r',
+ ADD: 'a',
+ CREATE: 'c',
+ WRITE: 'w',
+ DELETE: 'd',
+ LIST: 'l'
+ },
+
+ /**
+ * Blob listing details.
+ *
+ * @const
+ * @enum {string}
+ */
+ BlobListingDetails: {
+ SNAPSHOTS: 'snapshots',
+ METADATA: 'metadata',
+ UNCOMMITTED_BLOBS: 'uncommittedblobs',
+ COPY: 'copy',
+ DELETED: 'deleted'
+ },
+
+ /**
+ * Deletion options for blob snapshots
+ *
+ * @const
+ * @enum {string}
+ */
+ SnapshotDeleteOptions: {
+ SNAPSHOTS_ONLY: 'only',
+ BLOB_AND_SNAPSHOTS: 'include'
+ },
+
+ /**
+ * Type of block list to retrieve
+ *
+ * @const
+ * @enum {string}
+ */
+ BlockListFilter: {
+ ALL: 'all',
+ COMMITTED: 'committed',
+ UNCOMMITTED: 'uncommitted'
+ },
+
+ /**
+ * Blobs and container public access types.
+ *
+ * @const
+ * @enum {string}
+ */
+ BlobContainerPublicAccessType: {
+ OFF: null,
+ CONTAINER: 'container',
+ BLOB: 'blob'
+ },
+
+ /**
+ * Describes actions that can be performed on a page blob sequence number.
+ * @const
+ * @enum {string}
+ */
+ SequenceNumberAction: {
+ MAX: 'max',
+ UPDATE: 'update',
+ INCREMENT: 'increment'
+ },
+
+ /**
+ * Candidate values for blob tiers.
+ *
+ * @property {object} PremiumPageBlobTier Candidate values for premium pageblob tiers.
+ * @property {string} PremiumPageBlobTier.P4
+ * @property {string} PremiumPageBlobTier.P6
+ * @property {string} PremiumPageBlobTier.P10
+ * @property {string} PremiumPageBlobTier.P20
+ * @property {string} PremiumPageBlobTier.P30
+ * @property {string} PremiumPageBlobTier.P40
+ * @property {string} PremiumPageBlobTier.P50
+ * @property {string} PremiumPageBlobTier.P60
+ * @property {object} StandardBlobTier Candidate values for standard blobs tiers.
+ * @property {string} StandardBlobTier.HOT
+ * @property {string} StandardBlobTier.COOL
+ * @property {string} StandardBlobTier.ARCHIVE
+ */
+ BlobTier: {
+ PremiumPageBlobTier: {
+ P4: 'P4',
+ P6: 'P6',
+ P10: 'P10',
+ P20: 'P20',
+ P30: 'P30',
+ P40: 'P40',
+ P50: 'P50',
+ P60: 'P60'
+ },
+ StandardBlobTier: {
+ HOT: 'Hot',
+ COOL: 'Cool',
+ ARCHIVE: 'Archive'
+ }
+ }
+};
+
+module.exports = BlobUtilities;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/blob/internal/blockrangestream.js b/src/node_modules/azure-storage/lib/services/blob/internal/blockrangestream.js
new file mode 100644
index 0000000..f94a2fd
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/internal/blockrangestream.js
@@ -0,0 +1,203 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var Constants = require('./../../../common/util/constants');
+var EventEmitter = require('events').EventEmitter;
+var BlobUtilities = require('./../blobutilities');
+
+/**
+* BlockBlob block range stream
+*/
+function BlockRangeStream(blobServiceClient, container, blob, options) {
+ this.blobServiceClient = blobServiceClient;
+ this.container = container;
+ this.blob = blob;
+ this._emitter = new EventEmitter();
+ this._paused = false;
+ this._emittedAll = false;
+ this._emittedRangeType = null;
+ this._emittedRangeIndex = null;
+ this._offset = 0;
+ this._rangelist = [];
+ this._isEmitting = false;
+ if (options.rangeStart) {
+ this._startOffset = options.rangeStart;
+ } else {
+ this._startOffset = 0;
+ }
+ if (options.rangeEnd) {
+ this._endOffset = options.rangeEnd;
+ } else {
+ this._endOffset = Number.MAX_VALUE;
+ }
+}
+
+/**
+* Add event listener
+*/
+BlockRangeStream.prototype.on = function (event, listener) {
+ this._emitter.on(event, listener);
+};
+
+/**
+* Get block list
+*/
+BlockRangeStream.prototype.list = function (options, callback) {
+ if (!options) {
+ options = {};
+ }
+
+ if (!options.blockListFilter) {
+ options.blockListFilter = BlobUtilities.BlockListFilter.ALL;
+ }
+
+ var self = this;
+ this.blobServiceClient.listBlocks(this.container, this.blob, options.blockListFilter, options, function (error, blocklist, response) {
+ if (error) {
+ callback(error);
+ } else {
+ var totalSize = parseInt(response.headers[Constants.HeaderConstants.BLOB_CONTENT_LENGTH], 10);
+ if (!blocklist.CommittedBlocks) {
+ //Convert single block blob to block blob range
+ var name = 'NODESDK_BLOCKBLOB_RANGESTREAM';
+ blocklist.CommittedBlocks = [{ Name : name, Size : totalSize }];
+ }
+
+ self._rangelist = blocklist;
+ self._emitBlockList();
+ self = blocklist = null;
+ }
+ });
+};
+
+/**
+* Emit block ranges
+*/
+BlockRangeStream.prototype._emitBlockList = function () {
+ if (this._paused || this._emittedAll || this._isEmitting) return;
+
+ var self = this;
+ this._getTypeList(function () {
+ self._rangelist = null;
+ self._emittedAll = true;
+ self._emitter.emit('end');
+ });
+};
+
+/**
+* Get the block type list
+*/
+BlockRangeStream.prototype._getTypeList = function (callback) {
+ this._isEmitting = true;
+ try {
+ var typeStart = false;
+ if (this._rangelist) {
+ for (var blockType in this._rangelist) {
+ if (this._rangelist.hasOwnProperty(blockType)) {
+ if (this._emittedRangeType === null || typeStart || this._emittedRangeType == blockType) {
+ this._emittedRangeType = blockType;
+ typeStart = true;
+ } else if (this._emittedRangeType !== blockType) {
+ continue;
+ }
+
+ if (this._paused) {
+ return;
+ }
+
+ this._emitBlockRange (blockType, callback);
+ }
+ }
+ }
+ } finally {
+ this._isEmitting = false;
+ }
+};
+
+/**
+* Get the block list
+*/
+BlockRangeStream.prototype._emitBlockRange = function (blockType, callback) {
+ var blockList = this._rangelist[blockType];
+ var indexStart = false;
+ for (var blockIndex = 0; blockIndex < blockList.length; blockIndex++) {
+ if (this._emittedRangeIndex === null || indexStart || this._emittedRangeIndex === blockIndex) {
+ this._emittedRangeIndex = blockIndex;
+ indexStart = true;
+ } else if (this._emittedRangeIndex !== blockIndex) {
+ continue;
+ }
+
+ if (this._paused) {
+ return;
+ }
+
+ var range = blockList[blockIndex];
+ // follow the same naming convention of page ranges and json
+ range.name = range.Name;
+ range.type = blockType;
+ range.start = this._offset;
+ this._offset += parseInt(range.Size, 10);
+ range.end = this._offset - 1;
+ delete range.Name;
+ delete range.Size;
+
+ if (range.start > this._endOffset) {
+ break;
+ } else if (range.end < this._startOffset) {
+ continue;
+ } else {
+ range.start = Math.max(range.start, this._startOffset);
+ range.end = Math.min(range.end, this._endOffset);
+ range.size = range.end - range.start + 1;
+ range.dataSize = range.size;
+ this._emitter.emit('range', range);
+ }
+ }
+
+ // remove the used range and avoid memory leak
+ this._rangelist[blockType] = null;
+
+ callback();
+};
+
+/**
+* Pause the stream
+*/
+BlockRangeStream.prototype.pause = function () {
+ this._paused = true;
+};
+
+/**
+* Resume the stream
+*/
+BlockRangeStream.prototype.resume = function () {
+ this._paused = false;
+ if (!this._isEmitting) {
+ this._emitBlockList();
+ }
+};
+
+/**
+* Stop the stream
+*/
+BlockRangeStream.prototype.stop = function () {
+ this.pause();
+ this._emittedAll = true;
+ this._emitter.emit('end');
+};
+
+module.exports = BlockRangeStream;
diff --git a/src/node_modules/azure-storage/lib/services/blob/internal/pagerangestream.js b/src/node_modules/azure-storage/lib/services/blob/internal/pagerangestream.js
new file mode 100644
index 0000000..1943712
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/internal/pagerangestream.js
@@ -0,0 +1,43 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var util = require('util');
+var RangeStream = require('./../../../common/streams/rangestream');
+var Constants = require('./../../../common/util/constants');
+
+/**
+* PageBlob page range stream
+*/
+function PageRangeStream(blobServiceClient, container, blob, options) {
+ PageRangeStream['super_'].call(this, blobServiceClient, container, blob, options);
+
+ if (options.minRangeSize) {
+ this._minRangeSize = options.minRangeSize;
+ } else {
+ this._minRangeSize = Constants.BlobConstants.MIN_WRITE_PAGE_SIZE_IN_BYTES;
+ }
+ if (options.maxRangeSize) {
+ this._maxRangeSize = options.maxRangeSize;
+ } else {
+ this._maxRangeSize = Constants.BlobConstants.DEFAULT_WRITE_PAGE_SIZE_IN_BYTES;
+ }
+ this._lengthHeader = Constants.HeaderConstants.BLOB_CONTENT_LENGTH;
+ this._listFunc = blobServiceClient.listPageRanges;
+}
+
+util.inherits(PageRangeStream, RangeStream);
+
+module.exports = PageRangeStream;
diff --git a/src/node_modules/azure-storage/lib/services/blob/models/blobresult.js b/src/node_modules/azure-storage/lib/services/blob/models/blobresult.js
new file mode 100644
index 0000000..eb12b51
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/models/blobresult.js
@@ -0,0 +1,316 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var Constants = azureCommon.Constants;
+var HeaderConstants = Constants.HeaderConstants;
+
+/**
+* Creates a new BlobResult object.
+* @class
+* The BlobResult class is used to store the blob information.
+*
+ * @property {string} container The container name.
+ * @property {string} name The blob name.
+ * @property {object} metadata The metadata key/value pair.
+ * @property {string} etag The etag.
+ * @property {string} lastModified The date/time that the blob was last modified.
+ * @property {string} contentLength The size of the blob in bytes.
+ * @property {string} blobType The blob type.
+ * @property {boolean} isIncrementalCopy If the blob is incremental copy blob.
+ * @property {string} requestId The request id.
+ * @property {string} sequenceNumber The current sequence number for a page blob.
+ * @property {string} contentRange The content range.
+ * @property {string} committedBlockCount The committed block count.
+ * @property {string} serverEncrypted If the blob data and application metadata are completely encrypted using the specified algorithm. true/false.
+ * @property {object} contentSettings The content settings.
+ * @property {string} contentSettings.contentType The content type.
+ * @property {string} contentSettings.contentEncoding The content encoding.
+ * @property {string} contentSettings.contentLanguage The content language.
+ * @property {string} contentSettings.cacheControl The cache control.
+ * @property {string} contentSettings.contentDisposition The content disposition.
+ * @property {string} contentSettings.contentMD5 The content MD5 hash.
+ * @property {object} lease The lease information.
+ * @property {string} lease.id The lease id.
+ * @property {string} lease.status The lease status.
+ * @property {string} lease.state The lease state.
+ * @property {string} lease.duration The lease duration.
+ * @property {object} copy The copy information.
+ * @property {string} copy.id The copy id.
+ * @property {string} copy.status The copy status.
+ * @property {string} copy.completionTime The copy completion time.
+ * @property {string} copy.statusDescription The copy status description.
+ * @property {string} copy.destinationSnapshot The snapshot time of the last successful incremental copy snapshot for this blob.
+ * @property {string} copy.progress The copy progress.
+ * @property {string} copy.source The copy source.
+ *
+* @constructor
+* @param {string} [container] The container name.
+* @param {string} [name] The blob name.
+*/
+function BlobResult(container, name) {
+ if (container) {
+ this.container = container;
+ }
+
+ if (name) {
+ this.name = name;
+ }
+}
+
+BlobResult.parse = function (blobXml) {
+ var blobResult = new BlobResult();
+
+ for (var propertyName in blobXml) {
+ if (blobXml.hasOwnProperty(propertyName)) {
+ if (propertyName === 'Properties') {
+ // Lift out the properties onto the main object to keep consistent across all APIs like: getBlobProperties
+ azureutil.setPropertyValueFromXML(blobResult, blobXml[propertyName], true);
+ } else if (propertyName === 'Metadata') {
+ var resultPropertyName = azureutil.normalizePropertyNameFromXML(propertyName);
+ blobResult[resultPropertyName] = {};
+ azureutil.setPropertyValueFromXML(blobResult[resultPropertyName], blobXml[propertyName], false);
+ } else {
+ blobResult[propertyName.toLowerCase()] = blobXml[propertyName];
+ }
+ }
+ }
+
+ if (blobResult.isIncrementalCopy !== undefined) {
+ blobResult.isIncrementalCopy = (blobResult.isIncrementalCopy === 'true');
+ }
+
+ // convert accessTierInferred to boolean type
+ if (blobResult.accessTierInferred !== undefined) {
+ blobResult.accessTierInferred = (blobResult.accessTierInferred === 'true');
+ }
+
+ if (blobResult.deleted !== undefined) {
+ blobResult.deleted = (blobResult.deleted == 'true');
+ }
+
+ if (blobResult.remainingRetentionDays !== undefined) {
+ blobResult.remainingRetentionDays = parseInt(blobResult.remainingRetentionDays);
+ }
+
+ return blobResult;
+};
+
+var headersForProperties = {
+ 'lastModified': 'LAST_MODIFIED',
+ 'creationTime': 'CREATION_TIME',
+ 'etag': 'ETAG',
+ 'sequenceNumber': 'SEQUENCE_NUMBER',
+ 'blobType': 'BLOB_TYPE',
+ 'contentLength': 'CONTENT_LENGTH',
+ 'blobContentLength': 'BLOB_CONTENT_LENGTH',
+ 'contentRange': 'CONTENT_RANGE',
+ 'committedBlockCount': 'BLOB_COMMITTED_BLOCK_COUNT',
+ 'serverEncrypted': 'SERVER_ENCRYPTED',
+ 'requestId': 'REQUEST_ID',
+
+ 'range': 'RANGE',
+ 'blobRange': 'STORAGE_RANGE',
+ 'getContentMd5': 'RANGE_GET_CONTENT_MD5',
+ 'acceptRanges': 'ACCEPT_RANGES',
+ 'appendOffset': 'BLOB_APPEND_OFFSET',
+
+ 'accessTier': 'ACCESS_TIER',
+ 'accessTierChangeTime': 'ACCESS_TIER_CHANGE_TIME',
+ 'accessTierInferred': 'ACCESS_TIER_INFERRED',
+ 'archiveStatus': 'ARCHIVE_STATUS',
+
+ 'isIncrementalCopy': 'INCREMENTAL_COPY',
+
+ // ContentSettings
+ 'contentSettings.contentType': 'CONTENT_TYPE',
+ 'contentSettings.contentEncoding': 'CONTENT_ENCODING',
+ 'contentSettings.contentLanguage': 'CONTENT_LANGUAGE',
+ 'contentSettings.cacheControl': 'CACHE_CONTROL',
+ 'contentSettings.contentDisposition': 'CONTENT_DISPOSITION',
+ 'contentSettings.contentMD5': 'CONTENT_MD5',
+
+ // Lease
+ 'lease.id': 'LEASE_ID',
+ 'lease.status': 'LEASE_STATUS',
+ 'lease.duration': 'LEASE_DURATION',
+ 'lease.state': 'LEASE_STATE',
+
+ // Copy
+ 'copy.id': 'COPY_ID',
+ 'copy.status': 'COPY_STATUS',
+ 'copy.source': 'COPY_SOURCE',
+ 'copy.progress': 'COPY_PROGRESS',
+ 'copy.completionTime': 'COPY_COMPLETION_TIME',
+ 'copy.statusDescription': 'COPY_STATUS_DESCRIPTION',
+ 'copy.destinationSnapshot': 'COPY_DESTINATION_SNAPSHOT'
+};
+
+BlobResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ var setBlobPropertyFromHeaders = function (blobProperty, headerProperty) {
+ if (!azureutil.tryGetValueChain(self, blobProperty.split('.'), null) && headers[headerProperty.toLowerCase()]) {
+ azureutil.setObjectInnerPropertyValue(self, blobProperty.split('.'), headers[headerProperty.toLowerCase()]);
+
+ if (blobProperty === 'copy.progress') {
+ var info = azureutil.parseCopyProgress(self.copy.progress);
+ self.copy.bytesCopied = parseInt(info.bytesCopied);
+ self.copy.totalBytes = parseInt(info.totalBytes);
+ }
+ }
+ };
+
+ // For range get, 'x-ms-blob-content-md5' indicate the overall MD5 of the blob. Try to set the contentMD5 using this header if it presents
+ setBlobPropertyFromHeaders('contentSettings.contentMD5', HeaderConstants.BLOB_CONTENT_MD5);
+
+ _.chain(headersForProperties).pairs().each(function (pair) {
+ var property = pair[0];
+ var header = HeaderConstants[pair[1]];
+ setBlobPropertyFromHeaders(property, header);
+ });
+
+ // convert isIncrementalCopy to boolean type
+ if (self.isIncrementalCopy !== undefined) {
+ self.isIncrementalCopy = (self.isIncrementalCopy === 'true');
+ }
+
+ // convert accessTierInferred to boolean type
+ if (self.accessTierInferred !== undefined) {
+ self.accessTierInferred = (self.accessTierInferred == 'true');
+ }
+};
+
+/**
+* This method sets the HTTP headers and is used by all methods except setBlobProperties and commitBlocks. Those 2 methods will set the x-ms-* headers using setPropertiesFromBlob.
+* @ignore
+*/
+BlobResult.setHeadersFromBlob = function (webResource, blob) {
+ var setHeaderPropertyFromBlob = function (headerProperty, blobProperty) {
+ var blobPropertyValue = azureutil.tryGetValueChain(blob, blobProperty.split('.'), null);
+ if (blobPropertyValue) {
+ webResource.withHeader(headerProperty, blobPropertyValue);
+ }
+ };
+
+ if (blob) {
+ // Content-Type
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_TYPE, 'contentSettings.contentType');
+
+ // Content-Encoding
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_ENCODING, 'contentSettings.contentEncoding');
+
+ // Content-Language
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_LANGUAGE, 'contentSettings.contentLanguage');
+
+ // Content-Disposition
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_DISPOSITION, 'contentSettings.contentDisposition');
+
+ // Cache-Control
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CACHE_CONTROL, 'contentSettings.cacheControl');
+
+ // Blob's Content-MD5
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_MD5, 'contentSettings.contentMD5');
+
+ // Content-Length
+ setHeaderPropertyFromBlob(HeaderConstants.CONTENT_LENGTH, 'contentLength');
+
+ // transactional Content-MD5
+ setHeaderPropertyFromBlob(HeaderConstants.CONTENT_MD5, 'transactionalContentMD5');
+
+ // Range
+ if (!azureutil.objectIsNull(blob.rangeStart)) {
+ var range = 'bytes=' + blob.rangeStart + '-';
+
+ if (!azureutil.objectIsNull(blob.rangeEnd)) {
+ range += blob.rangeEnd;
+ }
+
+ webResource.withHeader(HeaderConstants.RANGE, range);
+ }
+
+ // Source Range
+ if (!azureutil.objectIsNull(blob.sourceRangeStart)) {
+ var sourceRange = 'bytes=' + blob.sourceRangeStart + '-';
+
+ if (!azureutil.objectIsNull(blob.sourceRangeEnd)) {
+ sourceRange += blob.sourceRangeEnd;
+ }
+
+ webResource.withHeader(HeaderConstants.SOURCE_RANGE, sourceRange);
+ }
+
+ // Blob Type
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_TYPE, 'blobType');
+
+ // Lease id
+ setHeaderPropertyFromBlob(HeaderConstants.LEASE_ID, 'leaseId');
+
+ // Sequence number
+ setHeaderPropertyFromBlob(HeaderConstants.SEQUENCE_NUMBER, 'sequenceNumber');
+ setHeaderPropertyFromBlob(HeaderConstants.SEQUENCE_NUMBER_ACTION, 'sequenceNumberAction');
+
+ if (blob.metadata) {
+ webResource.addOptionalMetadataHeaders(blob.metadata);
+ }
+ }
+};
+
+/**
+* This method sets the x-ms-* headers and is used by setBlobProperties and commitBlocks. All other methods will set the regular HTTP headers using setHeadersFromBlob.
+* @ignore
+*/
+BlobResult.setPropertiesFromBlob = function (webResource, blob) {
+ var setHeaderPropertyFromBlob = function (headerProperty, blobProperty) {
+ var propertyValue = azureutil.tryGetValueChain(blob, blobProperty.split('.'), null);
+ if (propertyValue) {
+ webResource.withHeader(headerProperty, propertyValue);
+ }
+ };
+
+ if (blob) {
+ // Content-Type
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_TYPE, 'contentSettings.contentType');
+
+ // Content-Encoding
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_ENCODING, 'contentSettings.contentEncoding');
+
+ // Content-Language
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_LANGUAGE, 'contentSettings.contentLanguage');
+
+ // Content-Disposition
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_DISPOSITION, 'contentSettings.contentDisposition');
+
+ // Cache-Control
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CACHE_CONTROL, 'contentSettings.cacheControl');
+
+ // Content-MD5
+ setHeaderPropertyFromBlob(HeaderConstants.BLOB_CONTENT_MD5, 'contentSettings.contentMD5');
+
+ // Lease id
+ setHeaderPropertyFromBlob(HeaderConstants.LEASE_ID, 'leaseId');
+
+ if (blob.metadata) {
+ webResource.addOptionalMetadataHeaders(blob.metadata);
+ }
+ }
+};
+
+module.exports = BlobResult;
diff --git a/src/node_modules/azure-storage/lib/services/blob/models/blocklistresult.js b/src/node_modules/azure-storage/lib/services/blob/models/blocklistresult.js
new file mode 100644
index 0000000..044be41
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/models/blocklistresult.js
@@ -0,0 +1,84 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+
+var azureCommon = require('./../../../common/common.core');
+var xmlbuilder = azureCommon.xmlbuilder;
+var Constants = azureCommon.Constants;
+
+/**
+* Builds an XML representation for a block list.
+*
+* @param {array} The block list.
+* @return {string} The XML block list.
+*/
+exports.serialize = function (blockListJs) {
+ var blockListDoc = xmlbuilder.create(Constants.BlobConstants.BLOCK_LIST_ELEMENT, { version: '1.0', encoding: 'utf-8' });
+
+ if (_.isArray(blockListJs.LatestBlocks)) {
+ blockListJs.LatestBlocks.forEach(function (block) {
+ blockListDoc = blockListDoc.ele(Constants.BlobConstants.LATEST_ELEMENT)
+ .txt(Buffer.from(block).toString('base64'))
+ .up();
+ });
+ }
+
+ if (_.isArray(blockListJs.CommittedBlocks)) {
+ blockListJs.CommittedBlocks.forEach(function (block) {
+ blockListDoc = blockListDoc.ele(Constants.BlobConstants.COMMITTED_ELEMENT)
+ .txt(Buffer.from(block).toString('base64'))
+ .up();
+ });
+ }
+
+ if (_.isArray(blockListJs.UncommittedBlocks)) {
+ blockListJs.UncommittedBlocks.forEach(function (block) {
+ blockListDoc = blockListDoc.ele(Constants.BlobConstants.UNCOMMITTED_ELEMENT)
+ .txt(Buffer.from(block).toString('base64'))
+ .up();
+ });
+ }
+
+ return blockListDoc.doc().toString();
+};
+
+exports.parse = function (blockListXml) {
+ var blockListResult = {};
+
+ if (blockListXml.CommittedBlocks && blockListXml.CommittedBlocks.Block) {
+ blockListResult.CommittedBlocks = blockListXml.CommittedBlocks.Block;
+ if (!_.isArray(blockListResult.CommittedBlocks)) {
+ blockListResult.CommittedBlocks = [blockListResult.CommittedBlocks];
+ }
+ blockListResult.CommittedBlocks.forEach(function(block) {
+ block.Name = Buffer.from(block.Name, 'base64').toString();
+ });
+ }
+
+ if (blockListXml.UncommittedBlocks && blockListXml.UncommittedBlocks.Block) {
+ blockListResult.UncommittedBlocks = blockListXml.UncommittedBlocks.Block;
+ if (!_.isArray(blockListResult.UncommittedBlocks)) {
+ blockListResult.UncommittedBlocks = [blockListResult.UncommittedBlocks];
+ }
+ blockListResult.UncommittedBlocks.forEach(function(block) {
+ block.Name = Buffer.from(block.Name, 'base64').toString();
+ });
+ }
+
+ return blockListResult;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/blob/models/containerresult.js b/src/node_modules/azure-storage/lib/services/blob/models/containerresult.js
new file mode 100644
index 0000000..b2a04b7
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/models/containerresult.js
@@ -0,0 +1,138 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var Constants = azureCommon.Constants;
+
+var HeaderConstants = Constants.HeaderConstants;
+var BlobUtilities = require('../blobutilities');
+
+/**
+* Creates a new ContainerResult object.
+* @class
+* The ContainerResult class is used to store the container information.
+*
+ * @property {string} name The container name.
+ * @property {string} publicAccessLevel The public access level.
+ * @property {object} metadata The metadata key/value pair.
+ * @property {string} etag The etag.
+ * @property {string} lastModified The date/time that the container was last modified.
+ * @property {string} requestId The request id.
+ * @property {object} lease The lease information.
+ * @property {string} lease.status The lease status.
+ * @property {string} lease.state The lease state.
+ * @property {string} lease.duration The lease duration.
+ *
+* @constructor
+* @param {string} [container] The container name.
+* @param {string} [publicAccessLevel] The public access level.
+*/
+function ContainerResult(name, publicAccessLevel) {
+ if (name) {
+ this.name = name;
+ }
+
+ if (publicAccessLevel) {
+ this.publicAccessLevel = publicAccessLevel;
+ }
+}
+
+ContainerResult.parse = function (containerXml) {
+ var containerResult = new ContainerResult();
+
+ for (var propertyName in containerXml) {
+ if (containerXml.hasOwnProperty(propertyName)) {
+ if (propertyName === 'Properties') {
+ // Lift out the properties onto the main object to keep consistent across all APIs like: getContainerProperties
+ azureutil.setPropertyValueFromXML(containerResult, containerXml[propertyName], true);
+ } else if (propertyName === 'Metadata') {
+ var resultPropertyName = azureutil.normalizePropertyNameFromXML(propertyName);
+ containerResult[resultPropertyName] = {};
+ azureutil.setPropertyValueFromXML(containerResult[resultPropertyName], containerXml[propertyName], false);
+ } else {
+ containerResult[propertyName.toLowerCase()] = containerXml[propertyName];
+ }
+ }
+ }
+
+ if (!containerResult.publicAccessLevel) {
+ containerResult.publicAccessLevel = BlobUtilities.BlobContainerPublicAccessType.OFF;
+ }
+
+ // convert hasImmutabilityPolicy to boolean type
+ if (containerResult.hasImmutabilityPolicy !== undefined) {
+ containerResult.hasImmutabilityPolicy = (containerResult.hasImmutabilityPolicy === 'true');
+ }
+
+ // convert hasLegalHold to boolean type
+ if (containerResult.hasLegalHold !== undefined) {
+ containerResult.hasLegalHold = (containerResult.hasLegalHold === 'true');
+ }
+
+ return containerResult;
+};
+
+ContainerResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ var setContainerPropertyFromHeaders = function (containerProperty, headerProperty) {
+ if (!azureutil.tryGetValueChain(self, containerProperty.split('.'), null) && headers[headerProperty.toLowerCase()]) {
+ azureutil.setObjectInnerPropertyValue(self, containerProperty.split('.'), headers[headerProperty.toLowerCase()]);
+ }
+ };
+
+ setContainerPropertyFromHeaders('etag', HeaderConstants.ETAG);
+ setContainerPropertyFromHeaders('lastModified', HeaderConstants.LAST_MODIFIED);
+ setContainerPropertyFromHeaders('lease.status', HeaderConstants.LEASE_STATUS);
+ setContainerPropertyFromHeaders('lease.state', HeaderConstants.LEASE_STATE);
+ setContainerPropertyFromHeaders('lease.duration', HeaderConstants.LEASE_DURATION);
+ setContainerPropertyFromHeaders('requestId', HeaderConstants.REQUEST_ID);
+ setContainerPropertyFromHeaders('hasImmutabilityPolicy', HeaderConstants.HAS_IMMUTABILITY_POLICY);
+ setContainerPropertyFromHeaders('hasLegalHold', HeaderConstants.HAS_LEGAL_HOLD);
+
+ // convert hasImmutabilityPolicy to boolean type
+ if (self.hasImmutabilityPolicy !== undefined) {
+ self.hasImmutabilityPolicy = (self.hasImmutabilityPolicy === 'true');
+ }
+
+ // convert hasLegalHold to boolean type
+ if (self.hasLegalHold !== undefined) {
+ self.hasLegalHold = (self.hasLegalHold === 'true');
+ }
+
+ if (!self.publicAccessLevel) {
+ self.publicAccessLevel = BlobUtilities.BlobContainerPublicAccessType.OFF;
+ if (headers[HeaderConstants.BLOB_PUBLIC_ACCESS]) {
+ self.publicAccessLevel = headers[HeaderConstants.BLOB_PUBLIC_ACCESS];
+ }
+ }
+
+ if (self.publicAccessLevel === 'true') {
+ // The container was marked for full public read access using a version prior to 2009-09-19.
+ self.publicAccessLevel = BlobUtilities.BlobContainerPublicAccessType.CONTAINER;
+ }
+};
+
+/**
+* The container ACL settings.
+* @typedef {object} ContainerAclResult
+* @extends {ContainerResult}
+* @property {Object.} signedIdentifiers The container ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+*/
+
+module.exports = ContainerResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/blob/models/leaseresult.js b/src/node_modules/azure-storage/lib/services/blob/models/leaseresult.js
new file mode 100644
index 0000000..8d39caa
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/blob/models/leaseresult.js
@@ -0,0 +1,73 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var Constants = require('./../../../common/common.core').Constants;
+var HeaderConstants = Constants.HeaderConstants;
+
+
+/**
+* Creates a new LeaseResult object.
+* @class
+* The LeaseResult class is used to store the lease information.
+*
+ * @property {string} container The container name.
+ * @property {string} blob The blob name.
+ * @property {string} id The lease id.
+ * @property {string} time Approximate time remaining in the lease period, in seconds.
+ * @property {string} etag The etag.
+ * @property {string} lastModified The date/time that the lease was last modified.
+ *
+* @constructor
+* @param {string} [container] The container name.
+* @param {string} [blob] The blob name.
+* @param {string} [id] The lease id.
+* @param {string} [time] Approximate time remaining in the lease period, in seconds.
+*/
+function LeaseResult(container, blob, id, time) {
+ if (container) {
+ this.container = container;
+ }
+
+ if (blob) {
+ this.blob = blob;
+ }
+
+ if (id) {
+ this.id = id;
+ }
+
+ if (time) {
+ this.time = time;
+ }
+}
+
+LeaseResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ if (!self['id'] && headers[HeaderConstants.LEASE_ID]) {
+ self['id'] = headers[HeaderConstants.LEASE_ID];
+ }
+
+ if (!self['time'] && headers[HeaderConstants.LEASE_TIME]) {
+ self['time'] = parseInt(headers[HeaderConstants.LEASE_TIME], 10);
+ }
+
+ self['etag'] = headers[HeaderConstants.ETAG];
+ self['lastModified'] = headers[HeaderConstants.LAST_MODIFIED.toLowerCase()];
+};
+
+module.exports = LeaseResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/file/fileservice.browser.js b/src/node_modules/azure-storage/lib/services/file/fileservice.browser.js
new file mode 100644
index 0000000..12c784b
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/fileservice.browser.js
@@ -0,0 +1,95 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var FileService = require('./fileservice.core');
+var azureCommon = require('./../../common/common.browser');
+var extend = require('extend');
+
+var azureutil = azureCommon.util;
+var BrowserFileReadStream = azureCommon.BrowserFileReadStream;
+var SpeedSummary = azureCommon.SpeedSummary;
+var validate = azureCommon.validate;
+var ChunkStreamWithStream = azureCommon.ChunkStreamWithStream;
+
+/**
+* Uploads a file to storage from an HTML File object. If the file already exists on the service, it will be overwritten.
+* (Only available in the JavaScript Client Library for Browsers)
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {File} browserFile The File object to be uploaded created by HTML File API.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* The default value is false for files.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+FileService.prototype.createFileFromBrowserFile = function (share, directory, file, browserFile, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createFileFromBrowserFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.browserFileIsValid(browserFile);
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(file);
+
+ var self = this;
+ this.createFile(share, directory, file, browserFile.size, options, function (error) {
+ if (error) {
+ callback(error);
+ } else {
+ var stream = new BrowserFileReadStream(browserFile);
+ var chunkStream = new ChunkStreamWithStream(stream, { calcContentMd5: options.storeFileContentMD5 });
+ self._createFileFromChunkStream(share, directory, file, chunkStream, browserFile.size, options, callback);
+ }
+ });
+
+ return options.speedSummary;
+};
+
+module.exports = FileService;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/file/fileservice.core.js b/src/node_modules/azure-storage/lib/services/file/fileservice.core.js
new file mode 100644
index 0000000..b1112cf
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/fileservice.core.js
@@ -0,0 +1,3941 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var qs = require('querystring');
+var url = require('url');
+var util = require('util');
+var _ = require('underscore');
+var extend = require('extend');
+var path = require('path');
+
+var azureCommon = require('./../../common/common.core');
+var Md5Wrapper = require('./../../common/md5-wrapper');
+var azureutil = azureCommon.util;
+var SR = azureCommon.SR;
+var validate = azureCommon.validate;
+var SpeedSummary = azureCommon.SpeedSummary;
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var WebResource = azureCommon.WebResource;
+
+// Constants
+var Constants = azureCommon.Constants;
+var FileConstants = Constants.FileConstants;
+var HeaderConstants = Constants.HeaderConstants;
+var HttpConstants = Constants.HttpConstants;
+var QueryStringConstants = Constants.QueryStringConstants;
+
+// Streams
+var BatchOperation = azureCommon.BatchOperation;
+var SpeedSummary = azureCommon.SpeedSummary;
+var ChunkAllocator = azureCommon.ChunkAllocator;
+var ChunkStream = azureCommon.ChunkStream;
+var ChunkStreamWithStream = azureCommon.ChunkStreamWithStream;
+var FileRangeStream = require('./internal/filerangestream');
+
+// Models requires
+var ShareResult = require('./models/shareresult');
+var DirectoryResult = require('./models/directoryresult');
+var FileResult = require('./models/fileresult');
+var AclResult = azureCommon.AclResult;
+
+// Errors requires
+var errors = require('../../common/errors/errors');
+var ArgumentNullError = errors.ArgumentNullError;
+var ArgumentError = errors.ArgumentError;
+
+/**
+* Creates a new FileService object.
+* If no connection string or storageaccount and storageaccesskey are provided,
+* the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
+* @class
+* The FileService class is used to perform operations on the Microsoft Azure File Service.
+* The File Service provides storage for binary large objects, and provides functions for working with data stored in files.
+*
+* For more information on the File Service, as well as task focused information on using it in a Node.js application, see
+* [How to Use the File Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-file-storage/).
+* The following defaults can be set on the file service.
+* defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the file service.
+* defaultEnableReuseSocket The default boolean value to enable socket reuse when uploading local files or streams.
+* If the Node.js version is lower than 0.10.x, socket reuse will always be turned off.
+* defaultClientRequestTimeoutInMs The default timeout of client requests, in milliseconds, to use for the request made via the file service.
+* defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the file service.
+* defaultLocationMode The default location mode for requests made via the file service.
+* parallelOperationThreadCount The number of parallel operations that may be performed when uploading a file.
+* useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the file service; true to use the
+* Nagle algorithm; otherwise, false. The default value is false.
+* enableGlobalHttpAgent Determines whether global HTTP(s) agent is enabled; true to use Global HTTP(s) agent; otherwise, false to use
+* http(s).Agent({keepAlive:true}).
+* @constructor
+* @extends {StorageServiceClient}
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} [sasToken] The Shared Access Signature token.
+* @param {string} [endpointSuffix] The endpoint suffix.
+*/
+function FileService(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) {
+ var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix);
+
+ FileService['super_'].call(this,
+ storageServiceSettings._name,
+ storageServiceSettings._key,
+ storageServiceSettings._fileEndpoint,
+ storageServiceSettings._usePathStyleUri,
+ storageServiceSettings._sasToken);
+
+ this.defaultEnableReuseSocket = Constants.DEFAULT_ENABLE_REUSE_SOCKET;
+ this.singleFileThresholdInBytes = FileConstants.DEFAULT_SINGLE_FILE_GET_THRESHOLD_IN_BYTES;
+ this.parallelOperationThreadCount = Constants.DEFAULT_PARALLEL_OPERATION_THREAD_COUNT;
+}
+
+util.inherits(FileService, StorageServiceClient);
+
+// Utility methods
+
+/**
+* Create resource name
+* @ignore
+*
+* @param {string} share Share name
+* @param {string} [directory] Directory name
+* @param {string} [file] File name
+* @return {string} The encoded resource name.
+*/
+function createResourceName(share, directory, file, forSAS) {
+ var encode = function(name) {
+ if (name && !forSAS) {
+ name = encodeURIComponent(name);
+ name = name.replace(/%2F/g, '/');
+ name = name.replace(/%5C/g, '/');
+ name = name.replace(/\+/g, '%20');
+ }
+ return name;
+ };
+
+ var name = share;
+
+ if (directory) {
+ // if directory does not start with '/', add it
+ if (directory[0] !== '/') {
+ name += ('/');
+ }
+
+ name += encode(directory);
+ }
+
+ if (file) {
+ // if the current path does not end with '/', add it
+ if (name[name.length - 1] !== '/') {
+ name += ('/');
+ }
+
+ name += encode(file);
+ }
+
+ return path.normalize(name).replace(/\\/g, '/');
+}
+
+// File service methods
+
+/**
+* Gets the properties of a storage account's File service, including Azure Storage Analytics.
+*
+* @this {FileService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `[result]{@link ServiceProperties}` will contain the properties
+* and `response` will contain information related to this operation.
+*/
+FileService.prototype.getServiceProperties = function (optionsOrCallback, callback) {
+ return this.getAccountServiceProperties(optionsOrCallback, callback);
+};
+
+/**
+* Sets the properties of a storage account's File service, including Azure Storage Analytics.
+* You can also use this operation to set the default request version for all incoming requests that do not have a version specified.
+*
+* @this {FileService}
+* @param {object} serviceProperties The service properties.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise, `response`
+* will contain information related to this operation.
+*/
+FileService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) {
+ return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback);
+};
+
+// Share methods
+
+/**
+* Lists a segment containing a collection of share items under the specified account.
+*
+* @this {FileService}
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.maxResults] Specifies the maximum number of shares to return per call to Azure storage.
+* @param {string} [options.include] Include this parameter to specify that the share's metadata be returned as part of the response body. (allowed values: '', 'metadata', 'snapshots' or any combination of them)
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[shares]{@link ShareResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.listSharesSegmented = function (currentToken, optionsOrCallback, callback) {
+ this.listSharesSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of share items whose names begin with the specified prefix under the specified account.
+*
+* @this {FileService}
+* @param {string} prefix The prefix of the share name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {string} [options.prefix] Filters the results to return only shares whose name begins with the specified prefix.
+* @param {int} [options.maxResults] Specifies the maximum number of shares to return per call to Azure storage.
+* @param {string} [options.include] Include this parameter to specify that the share's metadata be returned as part of the response body. (allowed values: '', 'metadata', 'snapshots' or any combination of them)
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[shares]{@link ShareResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.listSharesSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listShares', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get()
+ .withQueryOption(QueryStringConstants.COMP, 'list')
+ .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults)
+ .withQueryOption(QueryStringConstants.INCLUDE, options.include);
+
+ if (!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker);
+ }
+
+ webResource.withQueryOption(QueryStringConstants.PREFIX, prefix);
+
+ //options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.listSharesResult = null;
+
+ if (!responseObject.error) {
+ responseObject.listSharesResult = {
+ entries: null,
+ continuationToken: null
+ };
+ responseObject.listSharesResult.entries = [];
+
+ var shares = [];
+
+ if (responseObject.response.body.EnumerationResults.Shares && responseObject.response.body.EnumerationResults.Shares.Share) {
+ shares = responseObject.response.body.EnumerationResults.Shares.Share;
+ if (!_.isArray(shares)) {
+ shares = [shares];
+ }
+ }
+
+ shares.forEach(function (currentShare) {
+ var shareResult = ShareResult.parse(currentShare);
+ responseObject.listSharesResult.entries.push(shareResult);
+ });
+
+ if (responseObject.response.body.EnumerationResults.NextMarker) {
+ responseObject.listSharesResult.continuationToken = {
+ nextMarker: null,
+ targetLocation: null
+ };
+
+ responseObject.listSharesResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker;
+ responseObject.listSharesResult.continuationToken.targetLocation = responseObject.targetLocation;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.listSharesResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks whether or not a share exists on the service.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareResult}` will contain
+* the share information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.doesShareExist = function (share, optionsOrCallback, callback) {
+ this._doesShareExist(share, false, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new share under the specified account.
+* If a share with the same name already exists, the operation fails.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {int} [options.quota] Specifies the maximum size of the share, in gigabytes.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareResult}` will contain
+* the share information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.createShare = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createShare', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.shareQuotaIsValid(userOptions.quota);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withHeader(HeaderConstants.SHARE_QUOTA, options.quota);
+
+ webResource.addOptionalMetadataHeaders(options.metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ if (options.metadata) {
+ responseObject.shareResult.metadata = options.metadata;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Creates a share snapshot.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the ID of the snapshot.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.createShareSnapshot = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createShareSnapshot', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, QueryStringConstants.SNAPSHOT);
+ webResource.addOptionalMetadataHeaders(options.metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.snapshotId = null;
+ if (!responseObject.error) {
+ responseObject.snapshotId = responseObject.response.headers[HeaderConstants.SNAPSHOT];
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.snapshotId, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Creates a new share under the specified account if the share does not exists.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareResult}` will contain
+* the share information including `created` boolean member.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var FileService = azure.createFileService();
+* FileService.createShareIfNotExists('taskshare', function(error) {
+* if(!error) {
+* // Share created or already existed
+* }
+* });
+*/
+FileService.prototype.createShareIfNotExists = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createShareIfNotExists', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ delete options.shareSnapshotId;
+
+ var self = this;
+ self._doesShareExist(share, true, options, function(error, result, response) {
+ var exists = result.exists;
+ result.created = false;
+ delete result.exists;
+
+ if(error){
+ callback(error, result, response);
+ } else if (exists) {
+ response.isSuccessful = true;
+ callback(error, result, response);
+ } else {
+ self.createShare(share, options, function (createError, responseShare, createResponse) {
+ if(!createError){
+ responseShare.created = true;
+ }
+ else if (createError && createError.statusCode === HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.FileErrorCodeStrings.SHARE_ALREADY_EXISTS) {
+ // If it was created before, there was no actual error.
+ createError = null;
+ createResponse.isSuccessful = true;
+ }
+
+ callback(createError, responseShare, createResponse);
+ });
+ }
+ });
+};
+
+/**
+* Retrieves a share and its properties from a specified account.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+
+
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareResult}` will contain
+* information for the share.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getShareProperties = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getShareProperties', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ //options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets the properties for the specified share.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [properties] The share properties to set.
+* @param {string|int} [properties.quota] Specifies the maximum size of the share, in gigabytes.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[share]{@link ShareResult}` will contain
+* information about the share.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.setShareProperties = function (share, properties, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setShareProperties', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.shareQuotaIsValid(userOptions.quota);
+ v.callback(callback);
+ });
+
+ var options = extend(true, properties, userOptions);
+ var resourceName = createResourceName(share);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, 'properties')
+ .withHeader(HeaderConstants.SHARE_QUOTA, options.quota);
+
+ FileResult.setProperties(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets the share statistics for a share.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `[result]{@link ServiceStats}` will contain the stats and
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getShareStats = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getShareStats', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, 'stats');
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = ShareResult.parse(responseObject.response.body, share);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ // function to be called after all filters
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ // call the first filter
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+
+/**
+* Returns all user-defined metadata for the share.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareResult}` will contain
+* information for the share.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getShareMetadata = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getShareMetadata', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, 'metadata')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets the share's metadata.
+*
+* Calling the Set Share Metadata operation overwrites all existing metadata that is associated with the share.
+* It's not possible to modify an individual name/value pair.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} metadata The metadata key/value pairs.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.setShareMetadata = function (share, metadata, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setShareMetadata', function (v) {
+ v.string(share, 'share');
+ v.object(metadata, 'metadata');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, 'metadata');
+
+ webResource.addOptionalMetadataHeaders(metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets the share's ACL.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareAclResult}` will contain
+* information for the share.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getShareAcl = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getShareAcl', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, 'acl');
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ responseObject.shareResult.signedIdentifiers = AclResult.parse(responseObject.response.body);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Updates the share's ACL.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {Object.} signedIdentifiers The share ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link ShareAclResult}` will contain
+* information for the share.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.setShareAcl = function (share, signedIdentifiers, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setShareAcl', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var policies = null;
+ if (signedIdentifiers) {
+ if(_.isArray(signedIdentifiers)) {
+ throw new TypeError(SR.INVALID_SIGNED_IDENTIFIERS);
+ }
+ policies = AclResult.serialize(signedIdentifiers);
+ }
+
+ var webResource = WebResource.put(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.COMP, 'acl')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0)
+ .withBody(policies);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.shareResult = null;
+ if (!responseObject.error) {
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+ if (signedIdentifiers) {
+ responseObject.shareResult.signedIdentifiers = signedIdentifiers;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Marks the specified share for deletion.
+* The share and any files contained within it are later deleted during garbage collection.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.FileUtilities.ShareSnapshotDeleteOptions.*.
+* @param {string} [options.shareSnapshotId] The share snapshot identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.deleteShare = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteShare', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ if (!azureutil.objectIsNull(options.shareSnapshotId) && !azureutil.objectIsNull(options.deleteSnapshots)) {
+ throw new ArgumentError('options', SR.INVALID_DELETE_SNAPSHOT_OPTION);
+ }
+
+ var webResource = WebResource.del(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId)
+ .withHeader(HeaderConstants.DELETE_SNAPSHOT, options.deleteSnapshots);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified share for deletion if it exists.
+* The share and any files contained within it are later deleted during garbage collection.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {object} [options] The request options.
+* @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.FileUtilities.ShareSnapshotDeleteOptions.*.
+* @param {string} [options.shareSnapshotId] The share snapshot identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will
+* be true if the share exists and was deleted, or false if the share
+* did not exist.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.deleteShareIfExists = function (share, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteShareIfExists', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var self = this;
+ self._doesShareExist(share, true, options, function (error, result, response) {
+ if(error){
+ callback(error, result.exists, response);
+ } else if (!result.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteShare(share, options, function (deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError){
+ deleted = true;
+ } else if (deleteError && deleteError.statuscode === HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.FileErrorCodeStrings.SHARE_NOT_FOUND) {
+ // If it was deleted already, there was no actual error.
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+// Directory methods
+
+/**
+* Checks whether or not a directory exists on the service.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The share snapshot identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link DirectoryResult}` will contain
+* the directory information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.doesDirectoryExist = function (share, directory, optionsOrCallback, callback) {
+ this._doesDirectoryExist(share, directory, false, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new directory under the specified account.
+* If a directory with the same name already exists, the operation fails.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link DirectoryResult}` will contain
+* the directory information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.createDirectory = function (share, directory, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createDirectory', function (v) {
+ v.string(share, 'share');
+ v.string(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(createResourceName(share, directory))
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory');
+
+ webResource.addOptionalMetadataHeaders(options.metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.directoryResult = null;
+ if (!responseObject.error) {
+ responseObject.directoryResult = new DirectoryResult(directory);
+ responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.directoryResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Creates a new directory under the specified account if the directory does not exists.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link DirectoryResult}` will contain
+* the directory information including `created` boolean member.
+* already exists.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var FileService = azure.createFileService();
+* FileService.createDirectoryIfNotExists('taskshare', taskdirectory', function(error) {
+* if(!error) {
+* // Directory created or already existed
+* }
+* });
+*/
+FileService.prototype.createDirectoryIfNotExists = function (share, directory, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createDirectoryIfNotExists', function (v) {
+ v.string(share, 'share');
+ v.string(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ delete options.shareSnapshotId;
+
+ var self = this;
+ self._doesDirectoryExist(share, directory, true, options, function(error, result, response) {
+ var exists = result.exists;
+ result.created = false;
+ delete result.exists;
+
+ if(error){
+ callback(error, result, response);
+ } else if (exists) {
+ response.isSuccessful = true;
+ callback(error, result, response);
+ } else {
+ self.createDirectory(share, directory, options, function (createError, responseDirectory, createResponse) {
+ if(!createError){
+ responseDirectory.created = true;
+ }
+ else if (createError && createError.statusCode === HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.StorageErrorCodeStrings.RESOURCE_ALREADY_EXISTS) {
+ // If it was created before, there was no actual error.
+ createError = null;
+ createResponse.isSuccessful = true;
+ }
+
+ callback(createError, responseDirectory, createResponse);
+ });
+ }
+ });
+};
+
+/**
+* Retrieves a directory and its properties from a specified account.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link DirectoryResult}` will contain
+* information for the directory.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getDirectoryProperties = function (share, directory, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getDirectoryProperties', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(createResourceName(share, directory))
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.directoryResult = null;
+ if (!responseObject.error) {
+ responseObject.directoryResult = new DirectoryResult(directory);
+ responseObject.directoryResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.directoryResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified directory for deletion. The directory must be empty before it can be deleted.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.deleteDirectory = function (share, directory, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteDirectory', function (v) {
+ v.string(share, 'share');
+ v.string(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.del(createResourceName(share, directory))
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory');
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified directory for deletion if it exists. The directory must be empty before it can be deleted.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will
+* be true if the directory exists and was deleted, or false if the directory
+* did not exist.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.deleteDirectoryIfExists = function (share, directory, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteDirectoryIfExists', function (v) {
+ v.string(share, 'share');
+ v.string(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ delete options.shareSnapshotId;
+
+ var self = this;
+ self._doesDirectoryExist(share, directory, true, options, function(error, result, response) {
+ if(error){
+ callback(error, result.exists, response);
+ } else if (!result.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteDirectory(share, directory, options, function (deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError){
+ deleted = true;
+ } else if (deleteError && deleteError.statuscode === HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.StorageErrorCodeStrings.RESOURCE_NOT_FOUND) {
+ // If it was deleted already, there was no actual error.
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+/**
+* Lists a segment containing a collection of file items in the directory.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {int} [options.maxResults] Specifies the maximum number of files to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* entries.files which contains a list of `[files]{@link FileResult}`, entries.directories which contains a list of `[directories]{@link DirectoryResult}` and the continuationToken for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.listFilesAndDirectoriesSegmented = function (share, directory, currentToken, optionsOrCallback, callback) {
+ this.listFilesAndDirectoriesSegmentedWithPrefix(share, directory, null /*prefix*/, currentToken, optionsOrCallback, callback);
+};
+
+
+/**
+* Lists a segment containing a collection of file items in the directory.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} prefix The prefix of the directory/files name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {int} [options.maxResults] Specifies the maximum number of files to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* entries.files which contains a list of `[files]{@link FileResult}`, entries.directories which contains a list of `[directories]{@link DirectoryResult}` and the continuationToken for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.listFilesAndDirectoriesSegmentedWithPrefix = function (share, directory, prefix, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listFilesSegmented', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(createResourceName(share, directory))
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory')
+ .withQueryOption(QueryStringConstants.COMP, 'list')
+ .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults)
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ if (!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker);
+ }
+
+ webResource.withQueryOption(QueryStringConstants.PREFIX, prefix);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.listResult = null;
+ if (!responseObject.error) {
+ responseObject.listResult = {
+ entries: null,
+ continuationToken: null
+ };
+
+ responseObject.listResult.entries = {};
+ responseObject.listResult.entries.files = [];
+ responseObject.listResult.entries.directories = [];
+ var files = [];
+ var directories = [];
+
+ // parse files
+ if (responseObject.response.body.EnumerationResults.Entries.File) {
+ files = responseObject.response.body.EnumerationResults.Entries.File;
+ if (!_.isArray(files)) {
+ files = [ files ];
+ }
+ }
+
+ files.forEach(function (currentFile) {
+ var fileResult = FileResult.parse(currentFile);
+ responseObject.listResult.entries.files.push(fileResult);
+ });
+
+ // parse directories
+ if (responseObject.response.body.EnumerationResults.Entries.Directory) {
+ directories = responseObject.response.body.EnumerationResults.Entries.Directory;
+ if (!_.isArray(directories)) {
+ directories = [ directories ];
+ }
+ }
+
+ directories.forEach(function (currentDirectory) {
+ var directoryResult = DirectoryResult.parse(currentDirectory);
+ responseObject.listResult.entries.directories.push(directoryResult);
+ });
+
+ // parse continuation token
+ if(responseObject.response.body.EnumerationResults.NextMarker) {
+ responseObject.listResult.continuationToken = {
+ nextMarker: null,
+ targetLocation: null
+ };
+
+ responseObject.listResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker;
+ responseObject.listResult.continuationToken.targetLocation = responseObject.targetLocation;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.listResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Returns all user-defined metadata for the specified directory.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link DirectoryResult}` will contain
+* information about the directory.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getDirectoryMetadata = function (share, directory, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getDirectoryMetadata', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory);
+ var webResource = WebResource.head(resourceName)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory')
+ .withQueryOption(QueryStringConstants.COMP, 'metadata')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.directoryResult = null;
+ if (!responseObject.error) {
+ responseObject.directoryResult = new DirectoryResult(directory);
+ responseObject.directoryResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.directoryResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets user-defined metadata for the specified directory as one or more name-value pairs
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {object} metadata The metadata key/value pairs.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link DirectoryResult}` will contain
+* information on the directory.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.setDirectoryMetadata = function (share, directory, metadata, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setDirectoryMetadata', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.object(metadata, 'metadata');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory')
+ .withQueryOption(QueryStringConstants.COMP, 'metadata');
+
+ webResource.addOptionalMetadataHeaders(metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.directoryResult = null;
+ if (!responseObject.error) {
+ responseObject.directoryResult = new DirectoryResult(directory);
+ responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.directoryResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+// File methods
+
+/**
+* Retrieves a shared access signature token.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} [directory] The directory name. Use '' to refer to the base directory.
+* @param {string} [file] The file name.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {string} [sharedAccessPolicy.Id] The signed identifier.
+* @param {object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used).
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired (The UTC value will be used).
+* @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} [sharedAccessPolicy.AccessPolicy.Protocols] The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* @param {object} [headers] The optional header values to set for a file returned wth this SAS.
+* @param {string} [headers.cacheControl] The optional value of the Cache-Control response header to be returned when this SAS is used.
+* @param {string} [headers.contentType] The optional value of the Content-Type response header to be returned when this SAS is used.
+* @param {string} [headers.contentEncoding] The optional value of the Content-Encoding response header to be returned when this SAS is used.
+* @param {string} [headers.contentLanguage] The optional value of the Content-Language response header to be returned when this SAS is used.
+* @param {string} [headers.contentDisposition] The optional value of the Content-Disposition response header to be returned when this SAS is used.
+* @return {string} The shared access signature query string. Note this string does not contain the leading "?".
+*/
+FileService.prototype.generateSharedAccessSignature = function (share, directory, file, sharedAccessPolicy, headers) {
+ // check if the FileService is able to generate a shared access signature
+ if (!this.storageCredentials || !this.storageCredentials.generateSignedQueryString) {
+ throw new Error(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
+ }
+
+ // Validate share name. File name is optional.
+ validate.validateArgs('generateSharedAccessSignature', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.object(sharedAccessPolicy, 'sharedAccessPolicy');
+ });
+
+ var resourceType = FileConstants.ResourceTypes.SHARE;
+ if (file) {
+ validate.validateArgs('generateSharedAccessSignature', function (v) {
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ });
+ resourceType = FileConstants.ResourceTypes.FILE;
+ } else {
+ directory = ''; // If file is not set, directory is not a part of the string to sign.
+ }
+
+ if (sharedAccessPolicy.AccessPolicy) {
+ if (!azureutil.objectIsNull(sharedAccessPolicy.AccessPolicy.Start)) {
+ if (!_.isDate(sharedAccessPolicy.AccessPolicy.Start)) {
+ sharedAccessPolicy.AccessPolicy.Start = new Date(sharedAccessPolicy.AccessPolicy.Start);
+ }
+
+ sharedAccessPolicy.AccessPolicy.Start = azureutil.truncatedISO8061Date(sharedAccessPolicy.AccessPolicy.Start);
+ }
+
+ if (!azureutil.objectIsNull(sharedAccessPolicy.AccessPolicy.Expiry)) {
+ if (!_.isDate(sharedAccessPolicy.AccessPolicy.Expiry)) {
+ sharedAccessPolicy.AccessPolicy.Expiry = new Date(sharedAccessPolicy.AccessPolicy.Expiry);
+ }
+
+ sharedAccessPolicy.AccessPolicy.Expiry = azureutil.truncatedISO8061Date(sharedAccessPolicy.AccessPolicy.Expiry);
+ }
+ }
+
+ var resourceName = createResourceName(share, directory, file, true);
+ return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.File, resourceName, sharedAccessPolicy, null, { headers: headers, resourceType: resourceType });
+};
+
+/**
+* Retrieves a file or directory URL.
+*
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} [file] The file name. File names may not start or end with the delimiter '/'.
+* @param {string} [sasToken] The Shared Access Signature token.
+* @param {boolean} [primary] A boolean representing whether to use the primary or the secondary endpoint.
+* @param {string} [shareSnapshotId] The snapshot identifier of the share.
+* @return {string} The formatted URL string.
+* @example
+* var azure = require('azure-storage');
+* var fileService = azure.createFileService();
+* var sharedAccessPolicy = {
+* AccessPolicy: {
+* Permissions: azure.FileUtilities.SharedAccessPermissions.READ,
+* Start: startDate,
+* Expiry: expiryDate
+* },
+* };
+*
+* var sasToken = fileService.generateSharedAccessSignature(shareName, directoryName, fileName, sharedAccessPolicy);
+* var url = fileService.getUrl(shareName, directoryName, fileName, sasToken, true);
+*/
+FileService.prototype.getUrl = function (share, directory, file, sasToken, primary, shareSnapshotId) {
+ validate.validateArgs('getUrl', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.shareNameIsValid(share);
+ });
+
+ var host;
+ if(!azureutil.objectIsNull(primary) && primary === false) {
+ host = this.host.secondaryHost;
+ } else {
+ host = this.host.primaryHost;
+ }
+ host = azureutil.trimPortFromUri(host);
+ if(host && host.lastIndexOf('/') !== (host.length - 1)){
+ host = host + '/';
+ }
+
+ var name = createResourceName(share, directory, file);
+ var query = qs.parse(sasToken);
+ if(shareSnapshotId) {
+ query[QueryStringConstants.SHARE_SNAPSHOT] = shareSnapshotId;
+ }
+ return url.resolve(host, url.format({pathname: this._getPath(name), query: query}));
+};
+
+/**
+* Returns all user-defined metadata, standard HTTP properties, and system properties for the file.
+* It does not return or modify the content of the file.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* information about the file.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getFileProperties = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getFileProperties', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.head(resourceName)
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Returns all user-defined metadata for the specified file.
+* It does not modify or return the content of the file.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* information about the file.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getFileMetadata = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getFileMetadata', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.head(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'metadata')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets user-defined properties for the specified file.
+* It does not modify or return the content of the file.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [properties] The file properties to set.
+* @param {string} [properties.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [properties.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [properties.contentLanguage] The natural languages used by this resource.
+* @param {string} [properties.cacheControl] The file's cache control.
+* @param {string} [properties.contentDisposition] The file's content disposition.
+* @param {string} [properties.contentLength] Resizes a file to the specified size. If the specified byte value is less than the current size of the file,
+* then all ranges above the specified byte value are cleared.
+* @param {string} [properties.contentMD5] The file's MD5 hash.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* information about the file.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.setFileProperties = function (share, directory, file, properties, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setFileProperties', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {contentSettings: properties, contentLength: properties.contentLength }, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'properties');
+
+ FileResult.setProperties(webResource, options);
+
+ var processResponseCallback = function(responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function(returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets user-defined metadata for the specified file as one or more name-value pairs
+* It does not modify or return the content of the file.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} metadata The metadata key/value pairs.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* information on the file.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.setFileMetadata = function (share, directory, file, metadata, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setFileMetadata', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.object(metadata, 'metadata');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'metadata');
+
+ webResource.addOptionalMetadataHeaders(metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Resizes a file.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {String} size The size of the file, in bytes.
+* @param {object} [options] The request options.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* information about the file.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.resizeFile = function (share, directory, file, size, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('resizeFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.value(size);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'properties');
+
+ webResource.withHeader(HeaderConstants.FILE_CONTENT_LENGTH, size);
+
+ var processResponseCallback = function(responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function(returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks whether or not a file exists on the service.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* the file information including the `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.doesFileExist = function (share, directory, file, optionsOrCallback, callback) {
+ this._doesFileExist(share, directory, file, false, optionsOrCallback, callback);
+};
+
+/**
+* Creates a file of the specified length. If the file already exists on the service, it will be overwritten.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {int} length The length of the file in bytes.
+* @param {object} [options] The request options.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* the file information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.createFile = function (share, directory, file, length, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+ validate.validateArgs('createFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.value(length);
+ v.callback(callback);
+ });
+
+ var resourceName = createResourceName(share, directory, file);
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(resourceName)
+ .withHeader(HeaderConstants.TYPE, 'file')
+ .withHeader(HeaderConstants.FILE_CONTENT_LENGTH, length);
+
+ FileResult.setProperties(webResource, options);
+
+ var processResponseCallback = function(responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function(returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified file for deletion. The file is later deleted during garbage collection.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; `response` will contain information related to this operation.
+*/
+FileService.prototype.deleteFile = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.del(resourceName);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Marks the specified file for deletion if it exists. The file is later deleted during garbage collection.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will
+* be true if the file was deleted, or false if the file
+* does not exist.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.deleteFileIfExists = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteFileIfExists', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ delete options.shareSnapshotId;
+
+ var self = this;
+ self._doesFileExist(share, directory, file, true, options, function(error, result, response) {
+ if(error){
+ callback(error, result.exists, response);
+ } else if (!result.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteFile(share, directory, file, options, function (deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError){
+ deleted = true;
+ } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.FileErrorCodeStrings.FILE_NOT_FOUND) {
+ // If it was deleted already, there was no actual error.
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+/**
+* Downloads a file into a text string.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {int} [options.rangeStart] The range start.
+* @param {int} [options.rangeEnd] The range end.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {FileService~FileToText} callback `error` will contain information
+* if an error occurs; otherwise `text` will contain the file contents,
+* and `[file]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.getFileToText = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getFileToText', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId)
+ .withRawResponse();
+
+ FileResult.setHeaders(webResource, options);
+ this._setRangeContentMD5Header(webResource, options);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.text = null;
+ responseObject.fileResult = null;
+
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true);
+ responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.text = responseObject.response.body;
+
+ self._validateLengthAndMD5(options, responseObject);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.text, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Provides a stream to read from a file.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {string} [options.rangeStart] Return only the bytes of the file in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the file in the specified range.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {Readable} A Node.js Readable stream.
+* @example
+* var azure = require('azure-storage');
+* var fileService = azure.createFileService();
+* var writable = fs.createWriteStream(destinationFileNameTarget);
+* fileService.createReadStream(shareName, directoryName, fileName).pipe(writable);
+*/
+FileService.prototype.createReadStream = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createReadStream', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var readStream = new ChunkStream(options);
+ this.getFileToStream(share, directory, file, readStream, options, function (error, fileResponse, response) {
+ if(error) {
+ readStream.emit('error', error);
+ }
+
+ if(callback) {
+ callback(error, fileResponse, response);
+ }
+ });
+
+ return readStream;
+};
+
+/**
+* Downloads a file into a stream.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {Writable} writeStream The Node.js Writable stream.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download.
+* Set the option to true for small files.
+* Parallel download and speed summary won't work with this option on.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.rangeStart] Return only the bytes of the file in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the file in the specified range.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*
+*
+* @example
+* var azure = require('azure-storage');
+* var FileService = azure.createFileService();
+* FileService.getFileToStream('taskshare', taskdirectory', 'task1', fs.createWriteStream('task1-download.txt'), function(error, serverFile) {
+* if(!error) {
+* // file available in serverFile.file variable
+* }
+* });
+*/
+FileService.prototype.getFileToStream = function (share, directory, file, writeStream, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+ userOptions.speedSummary = userOptions.speedSummary || new SpeedSummary(file);
+
+ validate.validateArgs('getFileToStream', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.object(writeStream, 'writeStream');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var propertiesRequestOptions = {
+ timeoutIntervalInMs : options.timeoutIntervalInMs,
+ clientRequestTimeoutInMs : options.clientRequestTimeoutInMs,
+ accessConditions : options.accessConditions,
+ shareSnapshotId : options.shareSnapshotId
+ };
+
+ if (options.skipSizeCheck) {
+ this._getFileToStream(share, directory, file, writeStream, options, callback);
+ } else {
+ var self = this;
+ this.getFileProperties(share, directory, file, propertiesRequestOptions, function (error, properties) {
+ if (error) {
+ callback(error);
+ } else {
+ var size;
+ if (options.rangeStart) {
+ var endOffset = properties.contentLength - 1;
+ var end = options.rangeEnd ? Math.min(options.rangeEnd, endOffset) : endOffset;
+ size = end - options.rangeStart + 1;
+ } else {
+ size = properties.contentLength;
+ }
+ options.speedSummary.totalSize = size;
+
+ if (size > self.singleFileThresholdInBytes) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], azureutil.tryGetValueChain(properties, ['contentSettings', 'contentMD5'], null));
+ self._getFileToRangeStream(share, directory, file, writeStream, options, callback);
+ } else {
+ self._getFileToStream(share, directory, file, writeStream, options, callback);
+ }
+ }
+ });
+ }
+
+ return options.speedSummary;
+};
+
+/**
+* Lists file ranges. Lists all of the ranges by default, or only the ranges over a specific range of bytes if rangeStart and rangeEnd are specified.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {int} [options.rangeStart] The range start.
+* @param {int} [options.rangeEnd] The range end.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* the range information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.listRanges = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listRanges', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var resourceName = createResourceName(share, directory, file);
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'rangelist')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ FileResult.setHeaders(webResource, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.ranges = null;
+ if (!responseObject.error) {
+ responseObject.ranges = [];
+
+ var ranges = [];
+ if (responseObject.response.body.Ranges.Range) {
+ ranges = responseObject.response.body.Ranges.Range;
+
+ if (!_.isArray(ranges)) {
+ ranges = [ ranges ];
+ }
+ }
+
+ ranges.forEach(function (fileRange) {
+ var range = {
+ start: parseInt(fileRange.Start, 10),
+ end: parseInt(fileRange.End, 10)
+ };
+
+ responseObject.ranges.push(range);
+ });
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.ranges, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Clears a range. Clears all of the ranges by default, or only the ranges over a specific range of bytes if rangeStart and rangeEnd are specified.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {int} rangeStart The range start.
+* @param {int} rangeEnd The range end.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* the directory information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.clearRange = function (share, directory, file, rangeStart, rangeEnd, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('clearRange', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.value(rangeStart);
+ v.value(rangeEnd);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var request = this._updateFilesImpl(share, directory, file, rangeStart, rangeEnd, FileConstants.RangeWriteOptions.CLEAR, options);
+
+ var processResponseCallback = function(responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function(returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(request, null, options, processResponseCallback);
+};
+
+/**
+* Updates a range from a stream.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {Readable} readStream The Node.js Readable stream.
+* @param {int} rangeStart The range start.
+* @param {int} rangeEnd The range end.
+* @param {object} [options] The request options.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {string} [options.transactionalContentMD5] An optional hash value used to ensure transactional integrity for the page.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link FileResult}` will contain
+* the file information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.createRangesFromStream = function (share, directory, file, readStream, rangeStart, rangeEnd, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createRangesFromStream', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.object(readStream, 'readStream');
+ v.shareNameIsValid(share);
+ v.value(rangeStart);
+ v.value(rangeEnd);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var requiresContentMD5 = azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5 === true;
+
+ var length = (rangeEnd - rangeStart) + 1;
+ if(length > FileConstants.MAX_UPDATE_FILE_SIZE) {
+ throw new Error(SR.INVALID_FILE_RANGE_FOR_UPDATE);
+ }
+
+ var self = this;
+ if (requiresContentMD5) {
+ azureutil.calculateMD5(readStream, length, options, function(internalBuff, contentMD5) {
+ options.transactionalContentMD5 = contentMD5;
+ self._createRanges(share, directory, file, internalBuff, null /* stream */, rangeStart, rangeEnd, options, callback);
+ });
+ } else {
+ self._createRanges(share, directory, file, null /* text */, readStream, rangeStart, rangeEnd, options, callback);
+ }
+};
+
+/**
+* Uploads a file from a text string. If the file already exists on the service, it will be overwritten.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {string|object} text The file text, as a string or in a Buffer.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The upload tracker objects;
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* The default value is false for files.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {FileService~FileToText} callback `error` will contain information
+* if an error occurs; otherwise `text` will contain the file contents,
+* and `[file]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @example
+* var azure = require('azure-storage');
+* var fileService = azure.createFileService();
+*
+* var text = 'Hello World!';
+*
+* fileService.createFileFromText('taskshare', 'taskdirectory', 'taskfile', text, function(error, result, response) {
+* if (!error) {
+* // file created
+* }
+* });
+*/
+FileService.prototype.createFileFromText = function (share, directory, file, text, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createFileFromText', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var length = azureutil.objectIsNull(text) ? 0 : ((Buffer.isBuffer(text) ? text.length : Buffer.byteLength(text)));
+ if (length > FileConstants.MAX_UPDATE_FILE_SIZE) {
+ throw new Error(SR.INVALID_FILE_LENGTH);
+ }
+
+ if(options.storeFileContentMD5 && azureutil.objectIsNull(azureutil.tryGetValueChain(options, ['contentSettings', 'contentMD5'], null))) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], azureutil.getContentMd5(text));
+ }
+
+ var self = this;
+ this.createFile(share, directory, file, length, options, function(error, fileResult, response) {
+ if(error || length === 0) {
+ callback(error, fileResult, response);
+ }
+ else {
+ self._createRanges(share, directory, file, text, null, 0, length - 1, options, callback);
+ }
+ });
+};
+
+/**
+* Uploads a file from a stream. If the file already exists on the service, it will be overwritten.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* The default value is false for files.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+* @example
+* var stream = require('stream');
+* var azure = require('azure-storage');
+* var fileService = azure.createFileService();
+*
+* var fileStream = new stream.Readable();
+* fileStream.push(myFileBuffer);
+* fileStream.push(null);
+*
+* fileService.createFileFromStream('taskshare', 'taskdirectory', 'taskfile', fileStream, myFileBuffer.length, function(error, result, response) {
+* if (!error) {
+* // file uploaded
+* }
+* });
+*/
+FileService.prototype.createFileFromStream = function(share, directory, file, stream, streamLength, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createFileFromStream', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.object(stream, 'stream');
+ v.value(streamLength, 'streamLength');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(file);
+
+ stream.pause(); // Immediately pause the stream in order to compatible with Node v0.8
+
+ var self = this;
+ this.createFile(share, directory, file, streamLength, options, function(error) {
+ if(error) {
+ callback(error);
+ } else {
+ var chunkStream = new ChunkStreamWithStream(stream, {calcContentMd5: options.storeFileContentMD5});
+ self._createFileFromChunkStream(share, directory, file, chunkStream, streamLength, options, callback);
+ }
+ });
+
+ return options.speedSummary;
+};
+
+/**
+* Provides a stream to write to a file. Assumes that the file exists.
+* If it does not, please create the file using createFile before calling this method or use createWriteStreamNewFile.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* The default value is false for files.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var FileService = azure.createFileService();
+* FileService.createFile(shareName, directoryName, fileName, 1024, function (err) {
+* // Pipe file to a file
+* var stream = fs.createReadStream(fileNameTarget).pipe(FileService.createWriteStreamToExistingFile(shareName, directoryName, fileName));
+* });
+*/
+FileService.prototype.createWriteStreamToExistingFile = function (share, directory, file, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createWriteStreamToExistingFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var stream = new ChunkStream({calcContentMd5: options.storeFileContentMD5});
+ this._createFileFromChunkStream(share, directory, file, stream, null, options, function (error, file, response) {
+ if(error) {
+ stream.emit('error', error);
+ }
+
+ if (callback) {
+ callback(error, file, response);
+ }
+ });
+
+ return stream;
+};
+
+/**
+* Provides a stream to write to a file. Creates the file before writing data.
+* Please note the `Stream` returned by this API should be used with piping.
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {string} length The file length.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* The default value is false for files.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {Writable} A Node.js Writable stream.
+* @example
+* var azure = require('azure-storage');
+* var FileService = azure.createFileService();
+* var stream = fs.createReadStream(fileNameTarget).pipe(FileService.createWriteStreamToNewFile(shareName, directoryName, fileName));
+*/
+FileService.prototype.createWriteStreamToNewFile = function (share, directory, file, length, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createWriteStreamToNewFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.value(length, 'length');
+ v.shareNameIsValid(share);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var stream = new ChunkStream({calcContentMd5: options.storeFileContentMD5});
+ stream.pause();
+
+ var self = this;
+ this.createFile(share, directory, file, length, options, function(error) {
+ if(error) {
+ stream.emit('error', error);
+ callback(error);
+ }
+ else {
+ stream.resume();
+ self._createFileFromChunkStream(share, directory, file, stream, null, options, function (error, file, response) {
+ if(error) {
+ stream.emit('error', error);
+ }
+
+ if (callback) {
+ callback(error, file, response);
+ }
+ });
+ }
+ });
+
+ return stream;
+};
+
+/**
+* Starts to copy a file to a destination within the storage account.
+*
+* @this {FileService}
+* @param {string} sourceUri The source file or blob URI.
+* @param {string} targetShare The target share name.
+* @param {string} targetDirectory The target directory name.
+* @param {string} targetFile The target file name.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The target file metadata key/value pairs.
+* @param {AccessConditions} [options.accessConditions] The access conditions.
+* @param {AccessConditions} [options.sourceAccessConditions] The source access conditions.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.startCopyFile = function (sourceUri, targetShare, targetDirectory, targetFile, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('startCopyFile', function (v) {
+ v.string(targetShare, 'targetShare');
+ v.stringAllowEmpty(targetDirectory, 'targetDirectory');
+ v.string(targetFile, 'targetFile');
+ v.shareNameIsValid(targetShare);
+ v.callback(callback);
+ });
+
+ var targetResourceName = createResourceName(targetShare, targetDirectory, targetFile);
+
+ var options = extend(true, {}, userOptions);
+
+ var webResource = WebResource.put(targetResourceName)
+ .withHeader(HeaderConstants.COPY_SOURCE, sourceUri)
+ .addOptionalMetadataHeaders(options.metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(targetShare, targetDirectory, targetFile);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true);
+
+ if (options.metadata) {
+ responseObject.fileResult.metadata = options.metadata;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Abort a file copy operation.
+*
+* @this {FileService}
+* @param {string} share The destination share name.
+* @param {string} directory The destination directory name.
+* @param {string} file The destination file name.
+* @param {string} copyId The copy operation identifier.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype.abortCopyFile = function (share, directory, file, copyId, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('abortCopyFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var resourceName = createResourceName(share, directory, file);
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COPY_ID, copyId)
+ .withQueryOption(QueryStringConstants.COMP, 'copy')
+ .withHeader(HeaderConstants.COPY_ACTION, 'abort');
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+// Internal Methods
+
+/**
+* Updates a file from text.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {string} text The text string.
+* @param {Readable} readStream The Node.js Readable stream.
+* @param {int} rangeStart The range start.
+* @param {int} rangeEnd The range end.
+* @param {object} [options] The request options.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {bool} [options.transactionalContentMD5] An MD5 hash of the content. This hash is used to verify the integrity of the data during transport.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, file, response)} callback `error` will contain information
+* if an error occurs; otherwise `file` will contain
+* the file information.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype._createRanges = function (share, directory, file, text, readStream, rangeStart, rangeEnd, options, callback) {
+ var request = this._updateFilesImpl(share, directory, file, rangeStart, rangeEnd, FileConstants.RangeWriteOptions.UPDATE, options);
+
+ // At this point, we have already validated that the range is less than 4MB. Therefore, we just need to calculate the contentMD5 if required.
+ if(!azureutil.objectIsNull(text) && azureutil.objectIsNull(options.transactionalContentMD5) && options.useTransactionalMD5 === true) {
+ request.withHeader(HeaderConstants.CONTENT_MD5, azureutil.getContentMd5(text));
+ }
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = null;
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ if(!azureutil.objectIsNull(text)) {
+ this.performRequest(request, text, options, processResponseCallback);
+ } else {
+ this.performRequestOutputStream(request, readStream, options, processResponseCallback);
+ }
+};
+
+/**
+* Uploads a file from a stream.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param (Stream) stream Stream to the data to store.
+* @param {int} streamLength The length of the stream to upload.
+* @param {object|function} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The MD5 hash of the file content.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {function(error, null)} callback The callback function.
+* @return {SpeedSummary}
+*/
+FileService.prototype._createFileFromChunkStream = function(share, directory, file, chunkStream, streamLength, options, callback) {
+ this.logger.debug(util.format('_createFileFromChunkStream for file %s', file));
+
+ var apiName = '_createRanges';
+ var sizeLimitation = FileConstants.DEFAULT_WRITE_SIZE_IN_BYTES;
+ var originalContentMD5 = azureutil.tryGetValueChain(options, ['contentSettings', 'contentMD5'], null);
+
+ this._setOperationExpiryTime(options);
+
+ // initialize the speed summary
+ var speedSummary = options.speedSummary || new SpeedSummary();
+ speedSummary.totalSize = streamLength;
+
+ var parallelOperationThreadCount = options.parallelOperationThreadCount || this.parallelOperationThreadCount;
+
+ // initialize chunk allocator
+ var allocator = new ChunkAllocator(sizeLimitation, parallelOperationThreadCount, { logger: this.logger });
+
+ // if this is a FileReadStream, set the allocator on that stream
+ if (chunkStream._stream && chunkStream._stream.setMemoryAllocator) {
+ chunkStream._stream.setMemoryAllocator(allocator);
+ }
+
+ // initialize batch operations
+ var batchOperations = new BatchOperation(apiName, { logger : this.logger, enableReuseSocket : this.defaultEnableReuseSocket});
+ batchOperations.setConcurrency(parallelOperationThreadCount);
+
+ // initialize options
+ var rangeOptions = {
+ timeoutIntervalInMs: options.timeoutIntervalInMs,
+ clientRequestTimeoutInMs: options.clientRequestTimeoutInMs,
+ operationExpiryTime: options.operationExpiryTime
+ };
+
+ var self = this;
+ chunkStream.on('data', function (data, range) {
+ var operation = null;
+ var full = false;
+ var autoIncrement = speedSummary.getAutoIncrementFunction(data.length);
+
+ if(data.length > sizeLimitation) {
+ throw new Error(util.format(SR.EXCEEDED_SIZE_LIMITATION, sizeLimitation, data.length));
+ }
+
+ if (options.useTransactionalMD5) {
+ //calculate content md5 for the current uploading block data
+ var contentMD5 = azureutil.getContentMd5(data);
+ rangeOptions.transactionalContentMD5 = contentMD5;
+ }
+
+ if (azureutil.isBufferAllZero(data)) {
+ self.logger.debug(util.format('Skip upload data from %s bytes to %s bytes to file %s', range.start, range.end, file));
+ speedSummary.increment(data.length);
+ } else {
+ operation = new BatchOperation.RestOperation(self, apiName, share, directory, file, data, null, range.start, range.end, rangeOptions, function (error) {
+ if(!error) {
+ autoIncrement();
+ } else {
+ self.logger.debug(util.format('Stop downloading data as error happens. Error: %s', util.inspect(error)));
+ chunkStream.stop();
+ }
+
+ allocator.releaseBuffer(data);
+ data = null;
+ });
+ }
+
+ if (operation) {
+ full = batchOperations.addOperation(operation);
+ operation = null;
+
+ if(full) {
+ self.logger.debug('file stream paused');
+ chunkStream.pause();
+ }
+ }
+ });
+
+ chunkStream.on('end', function () {
+ self.logger.debug(util.format('File read stream ended for file %s', file));
+ batchOperations.enableComplete();
+ });
+
+ batchOperations.on('drain', function () {
+ self.logger.debug('File stream resume');
+ chunkStream.resume();
+ });
+
+ batchOperations.on('end', function (error) {
+ self.logger.debug('batch operations commited');
+
+ if (error) {
+ callback(error);
+ return;
+ }
+
+ if (originalContentMD5) {
+ options.contentSettings.contentMD5 = originalContentMD5;
+ } else if (options.storeFileContentMD5) {
+ azureutil.setObjectInnerPropertyValue(options, ['contentSettings', 'contentMD5'], chunkStream.getContentMd5('base64'));
+ }
+
+ // upload file completely
+ var fileProperties = extend(false, options.contentSettings, { contentLength: options.streamLength });
+ self.setFileProperties(share, directory, file, fileProperties, function (error, file, response) {
+ chunkStream.finish();
+ callback(error, file, response);
+ });
+ });
+
+ return speedSummary;
+};
+
+/**
+* Downloads a file into a stream.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {Writable} writeStream The Node.js Writable stream.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {string} [options.rangeStart] Return only the bytes of the file in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the file in the specified range.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the file information.
+* `response` will contain information related to this operation.
+*
+* @return {SpeedSummary}
+*/
+FileService.prototype._getFileToStream = function (share, directory, file, writeStream, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_getFileToStream', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.object(writeStream, 'writeStream');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.get(resourceName)
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId)
+ .withRawResponse();
+
+ FileResult.setHeaders(webResource, options);
+ this._setRangeContentMD5Header(webResource, options);
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = null;
+
+ if (!responseObject.error) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true);
+
+ self._validateLengthAndMD5(options, responseObject);
+
+ if (options.speedSummary) {
+ options.speedSummary.increment(responseObject.length);
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequestInputStream(webResource, null, writeStream, options, processResponseCallback);
+};
+
+/**
+* Downloads a file into a range stream.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {Writable} writeStream The Node.js Writable stream.
+* @param {object} [options] The request options.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.rangeStart] Return only the bytes of the file in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the file in the specified range.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the file information.
+* `response` will contain information related to this operation.
+*
+* @return {SpeedSummary}
+*/
+FileService.prototype._getFileToRangeStream = function (share, directory, file, writeStream, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_getFileToRangeStream', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.object(writeStream, 'writeStream');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var speedSummary = userOptions.speedSummary || new SpeedSummary(file);
+ var parallelOperationThreadCount = userOptions.parallelOperationThreadCount || this.parallelOperationThreadCount;
+ var batchOperations = new BatchOperation('getfile', { callbackInOrder: true, logger : this.logger, enableReuseSocket : this.defaultEnableReuseSocket });
+ batchOperations.setConcurrency(parallelOperationThreadCount);
+
+ var rangeStream = new FileRangeStream(this, share, directory, file, userOptions);
+
+ var self = this;
+ var checkMD5sum = !userOptions.disableContentMD5Validation;
+ var md5Hash = null;
+ if (checkMD5sum) {
+ md5Hash = new Md5Wrapper().createMd5Hash();
+ }
+
+ var savedFileResult = null;
+ var savedFileResponse = null;
+
+ rangeStream.on('range', function (range) {
+ if (!speedSummary.totalSize) {
+ speedSummary.totalSize = rangeStream.rangeSize;
+ }
+
+ var requestOptions = {
+ rangeStart : range.start,
+ rangeEnd : range.end,
+ responseEncoding : null //Use Buffer to store the response data
+ };
+
+ var rangeSize = range.size;
+ requestOptions.shareSnapshotId = userOptions.shareSnapshotId;
+ requestOptions.timeoutIntervalInMs = userOptions.timeoutIntervalInMs;
+ requestOptions.clientRequestTimeoutInMs = userOptions.clientRequestTimeoutInMs;
+ requestOptions.useTransactionalMD5 = userOptions.useTransactionalMD5;
+
+ if (range.dataSize === 0) {
+ var autoIncrement = speedSummary.getAutoIncrementFunction(rangeSize);
+ //No operation to do and only wait for write zero to file in callback
+ var writeZeroOperation = new BatchOperation.CommonOperation(BatchOperation.noOperation, function (error) {
+ if (error) return;
+ var bufferAvailable = azureutil.writeZerosToStream(writeStream, rangeSize, md5Hash, autoIncrement);
+ //There is no need to pause the rangestream since we can perform http request and write disk at the same time
+ self.logger.debug(util.format('Write %s bytes Zero from %s to %s', rangeSize, range.start, range.end));
+ if (!bufferAvailable) {
+ self.logger.debug('Write stream is full and pause batch operation');
+ batchOperations.pause();
+ }
+ });
+ batchOperations.addOperation(writeZeroOperation);
+ return;
+ }
+
+ if (range.start > range.end) {
+ return;
+ }
+
+ var operation = new BatchOperation.RestOperation(self, 'getFileToText', share, directory, file, requestOptions, function (error, content, fileResult, response) {
+ if (!error) {
+ if (rangeSize !== content.length) {
+ self.logger.warn(util.format('Request %s bytes, but server returns %s bytes', rangeSize, content.length));
+ }
+ //Save one of the succeeded callback parameters and use them at the final callback
+ if (!savedFileResult) {
+ savedFileResult = fileResult;
+ }
+ if (!savedFileResponse) {
+ savedFileResponse = response;
+ }
+ var autoIncrement = speedSummary.getAutoIncrementFunction(content.length);
+ var bufferAvailable = writeStream.write(content, autoIncrement);
+ if (!bufferAvailable) {
+ self.logger.debug('Write stream is full and pause batch operation');
+ batchOperations.pause();
+ }
+ if (md5Hash) {
+ md5Hash.update(content);
+ }
+ content = null;
+ } else {
+ self.logger.debug(util.format('Stop downloading data as error happens. Error: %s', util.inspect(error)));
+ rangeStream.stop();
+ }
+ });
+
+ var full = batchOperations.addOperation(operation);
+ if (full) {
+ self.logger.debug('Pause range stream');
+ rangeStream.pause();
+ }
+ });
+
+ rangeStream.on('end', function () {
+ self.logger.debug('Range stream has ended.');
+ batchOperations.enableComplete();
+ });
+
+ batchOperations.on('drain', function () {
+ self.logger.debug('Resume range stream');
+ rangeStream.resume();
+ });
+
+ writeStream.on('drain', function () {
+ self.logger.debug('Resume batch operations');
+ batchOperations.resume();
+ });
+
+ batchOperations.on('end', function (error) {
+ self.logger.debug('Download completed!');
+ if (error) {
+ callback(error);
+ } else {
+ writeStream.end(function () {
+ self.logger.debug('Write stream has ended');
+ if (!savedFileResult) {
+ savedFileResult = {};
+ }
+ azureutil.setObjectInnerPropertyValue(savedFileResult, ['contentSettings', 'contentMD5'], azureutil.tryGetValueChain(userOptions, ['contentSettings', 'contentMD5'], null));
+ savedFileResult.clientSideContentMD5 = null;
+ if (md5Hash) {
+ savedFileResult.clientSideContentMD5 = md5Hash.digest('base64');
+ }
+ callback(error, savedFileResult, savedFileResponse);
+ });
+ }
+ });
+
+ var listOptions = {
+ timeoutIntervalInMs : userOptions.timeoutIntervalInMs,
+ clientRequestTimeoutInMs : userOptions.clientRequestTimeoutInMs,
+ };
+
+ rangeStream.list(listOptions);
+ return speedSummary;
+};
+
+/**
+* @ignore
+*/
+FileService.prototype._setRangeContentMD5Header = function (webResource, options) {
+ if(!azureutil.objectIsNull(options.rangeStart) && options.useTransactionalMD5) {
+ if(azureutil.objectIsNull(options.rangeEnd)) {
+ throw new ArgumentNullError(util.format(SR.ARGUMENT_NULL_OR_EMPTY, options.rangeEndHeader));
+ }
+
+ var size = parseInt(options.rangeEnd, 10) - parseInt(options.rangeStart, 10) + 1;
+ if (size > FileConstants.MAX_RANGE_GET_SIZE_WITH_MD5) {
+ throw new Error(SR.INVALID_RANGE_FOR_MD5);
+ } else {
+ webResource.withHeader(HeaderConstants.RANGE_GET_CONTENT_MD5, 'true');
+ }
+ }
+};
+
+/**
+* @ignore
+*/
+FileService.prototype._updateFilesImpl = function (share, directory, file, rangeStart, rangeEnd, writeMethod, options) {
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.put(resourceName)
+ .withQueryOption(QueryStringConstants.COMP, 'range')
+ .withHeader(HeaderConstants.CONTENT_TYPE, 'application/octet-stream')
+ .withHeader(HeaderConstants.FILE_WRITE, writeMethod);
+
+ options.rangeStart = rangeStart;
+ options.rangeEnd = rangeEnd;
+
+ FileResult.setHeaders(webResource, options);
+
+ if(writeMethod === FileConstants.RangeWriteOptions.UPDATE) {
+ var size = (rangeEnd - rangeStart) + 1;
+ webResource.withHeader(HeaderConstants.CONTENT_LENGTH, size);
+ } else {
+ webResource.withHeader(HeaderConstants.CONTENT_LENGTH, 0);
+ }
+
+ return webResource;
+};
+
+/**
+* @ignore
+*/
+FileService.prototype._validateLengthAndMD5 = function (options, responseObject) {
+ var storedMD5 = responseObject.response.headers[Constants.HeaderConstants.CONTENT_MD5];
+ var contentLength;
+
+ if (!azureutil.objectIsNull(responseObject.response.headers[Constants.HeaderConstants.CONTENT_LENGTH])) {
+ contentLength = parseInt(responseObject.response.headers[Constants.HeaderConstants.CONTENT_LENGTH], 10);
+ }
+
+ // If the user has not specified this option, the default value should be false.
+ if(azureutil.objectIsNull(options.disableContentMD5Validation)) {
+ options.disableContentMD5Validation = false;
+ }
+
+ // None of the below cases should be retried. So set the error in every case so the retry policy filter handle knows that it shouldn't be retried.
+ if (options.disableContentMD5Validation === false && options.useTransactionalMD5 === true && azureutil.objectIsNull(storedMD5)) {
+ responseObject.error = new Error(SR.MD5_NOT_PRESENT_ERROR);
+ responseObject.retryable = false;
+ }
+
+ // Validate length and if required, MD5.
+ // If getFileToText called this method, then the responseObject.length and responseObject.contentMD5 are not set. Calculate them first using responseObject.response.body and then validate.
+ if(azureutil.objectIsNull(responseObject.length)) {
+ if (typeof responseObject.response.body == 'string') {
+ responseObject.length = Buffer.byteLength(responseObject.response.body);
+ } else if (Buffer.isBuffer(responseObject.response.body)) {
+ responseObject.length = responseObject.response.body.length;
+ }
+ }
+
+ if(!azureutil.objectIsNull(contentLength) && responseObject.length !== contentLength) {
+ responseObject.error = new Error(SR.CONTENT_LENGTH_MISMATCH);
+ responseObject.retryable = false;
+ }
+
+ if(options.disableContentMD5Validation === false && azureutil.objectIsNull(responseObject.contentMD5)) {
+ responseObject.contentMD5 = azureutil.getContentMd5(responseObject.response.body);
+ }
+
+ if (options.disableContentMD5Validation === false && !azureutil.objectIsNull(storedMD5) && storedMD5 !== responseObject.contentMD5) {
+ responseObject.error = new Error(util.format(SR.HASH_MISMATCH, storedMD5, responseObject.contentMD5));
+ responseObject.retryable = false;
+ }
+};
+
+/**
+* Checks whether or not a file exists on the service.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the file information including the `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype._doesFileExist = function (share, directory, file, primaryOnly, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('FileExists', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var resourceName = createResourceName(share, directory, file);
+ var webResource = WebResource.head(resourceName)
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ /*if(primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }*/
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.fileResult = new FileResult(share, directory, file);
+ if (!responseObject.error) {
+ responseObject.fileResult.exists = true;
+ responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.fileResult.exists = false;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.fileResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks whether or not a directory exists on the service.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The share snapshot identifier.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the directory information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype._doesDirectoryExist = function (share, directory, primaryOnly, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('directoryExists', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(createResourceName(share, directory))
+ .withQueryOption(QueryStringConstants.RESTYPE, 'directory')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ /*if(primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }*/
+
+ var self = this;
+ var processResponseCallback = function(responseObject, next){
+ responseObject.directoryResult = new DirectoryResult(directory);
+ responseObject.directoryResult.exists = false;
+
+ if (!responseObject.error) {
+ responseObject.directoryResult.exists = true;
+ responseObject.directoryResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.directoryResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks whether or not a share exists on the service.
+* @ignore
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} [options.shareSnapshotId] The share snapshot identifier.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* the share information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+FileService.prototype._doesShareExist = function (share, primaryOnly, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('shareExists', function (v) {
+ v.string(share, 'share');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(share)
+ .withQueryOption(QueryStringConstants.RESTYPE, 'share')
+ .withQueryOption(QueryStringConstants.SHARE_SNAPSHOT, options.shareSnapshotId);
+
+ /*if(primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }*/
+
+ var processResponseCallback = function(responseObject, next){
+ responseObject.shareResult = new ShareResult(share);
+ responseObject.shareResult.exists = false;
+
+ if (!responseObject.error) {
+ responseObject.shareResult.exists = true;
+ responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.shareResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* The callback for {FileService~getFileToText}.
+* @typedef {function} FileService~FileToText
+* @param {object} error If an error occurs, the error information.
+* @param {string} text The text returned from the file.
+* @param {object} file Information about the file.
+* @param {object} response Information related to this operation.
+*/
+
+FileService.SpeedSummary = SpeedSummary;
+
+module.exports = FileService;
diff --git a/src/node_modules/azure-storage/lib/services/file/fileservice.node.js b/src/node_modules/azure-storage/lib/services/file/fileservice.node.js
new file mode 100644
index 0000000..44af80e
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/fileservice.node.js
@@ -0,0 +1,182 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../common/common.node');
+var extend = require('extend');
+var fs = require('fs');
+var FileService = require('./fileservice.core');
+
+var azureutil = azureCommon.util;
+var FileReadStream = azureCommon.FileReadStream;
+var SpeedSummary = azureCommon.SpeedSummary;
+var validate = azureCommon.validate;
+
+/**
+* Downloads an Azure file into a file.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param {string} localFileName The local path to the file to be downloaded.
+* @param {object} [options] The request options.
+* @param {string} [options.shareSnapshotId] The snapshot identifier of the share.
+* @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download.
+* Set the option to true for small files.
+* Parallel download and speed summary won't work with this option on.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+* @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+* @param {string} [options.rangeStart] Return only the bytes of the file in the specified range.
+* @param {string} [options.rangeEnd] Return only the bytes of the file in the specified range.
+* @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+* @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*
+* @example
+* var azure = require('azure-storage');
+* var FileService = azure.createFileService();
+* FileService.getFileToLocalFile('taskshare', taskdirectory', 'task1', 'task1-download.txt', function(error, serverFile) {
+* if(!error) {
+* // file available in serverFile.file variable
+* }
+*/
+FileService.prototype.getFileToLocalFile = function (share, directory, file, localFileName, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+ userOptions.speedSummary = userOptions.speedSummary || new SpeedSummary(file);
+
+ validate.validateArgs('getFileToLocalFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.string(localFileName, 'localFileName');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var writeStream = fs.createWriteStream(localFileName);
+ writeStream.on('error', function (error) {
+ callback(error);
+ });
+
+ this.getFileToStream(share, directory, file, writeStream, options, function (error, responseFile, response) {
+ if (error) {
+ writeStream.end(function () {
+ // If the download failed from the beginning, remove the file.
+ if (fs.existsSync(localFileName) && writeStream.bytesWritten === 0) {
+ fs.unlinkSync(localFileName);
+ }
+ callback(error, responseFile, response);
+ });
+ } else {
+ callback(error, responseFile, response);
+ }
+ });
+
+ return options.speedSummary;
+};
+
+
+/**
+* Uploads a file to storage from a local file. If the file already exists on the service, it will be overwritten.
+* (Not available in the JavaScript Client Library for Browsers)
+*
+* @this {FileService}
+* @param {string} share The share name.
+* @param {string} directory The directory name. Use '' to refer to the base directory.
+* @param {string} file The file name. File names may not start or end with the delimiter '/'.
+* @param (string) localFileName The local path to the file to be uploaded.
+* @param {object} [options] The request options.
+* @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+* @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads.
+* The default value is false for files.
+* @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+* @param {object} [options.contentSettings] The file's content settings.
+* @param {string} [options.contentSettings.contentType] The MIME content type of the file. The default type is application/octet-stream.
+* @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the file.
+* @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+* @param {string} [options.contentSettings.cacheControl] The file service stores this value but does not use or modify it.
+* @param {string} [options.contentSettings.contentDisposition] The file's content disposition.
+* @param {string} [options.contentSettings.contentMD5] The file's MD5 hash.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link FileResult}` will contain the file information.
+* `response` will contain information related to this operation.
+* @return {SpeedSummary}
+*/
+FileService.prototype.createFileFromLocalFile = function (share, directory, file, localFileName, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createFileFromLocalFile', function (v) {
+ v.string(share, 'share');
+ v.stringAllowEmpty(directory, 'directory');
+ v.string(file, 'file');
+ v.string(localFileName, 'localFileName');
+ v.shareNameIsValid(share);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.speedSummary = options.speedSummary || new SpeedSummary(file);
+
+ var self = this;
+ fs.stat(localFileName, function(error, stat) {
+ if (error) {
+ callback(error);
+ } else {
+ self.createFile(share, directory, file, stat.size, options, function(error) {
+ if(error) {
+ callback(error);
+ } else {
+ var stream = new FileReadStream(localFileName, {calcContentMd5: options.storeFileContentMD5});
+ self._createFileFromChunkStream(share, directory, file, stream, stat.size, options, callback);
+ }
+ });
+ }
+ });
+
+ return options.speedSummary;
+};
+
+module.exports = FileService;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/file/fileutilities.js b/src/node_modules/azure-storage/lib/services/file/fileutilities.js
new file mode 100644
index 0000000..a4b9288
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/fileutilities.js
@@ -0,0 +1,72 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'FileUtilities'.
+exports = module.exports;
+
+/**
+* Defines constants, enums, and utility functions for use with the File service.
+* @namespace FileUtilities
+*/
+var FileUtilities = {
+ /**
+ * Permission types
+ *
+ * @const
+ * @enum {string}
+ */
+ SharedAccessPermissions: {
+ READ: 'r',
+ CREATE: 'c',
+ WRITE: 'w',
+ DELETE: 'd',
+ LIST: 'l'
+ },
+
+ /**
+ * Listing details.
+ *
+ * @const
+ * @enum {string}
+ */
+ ListingDetails: {
+ METADATA: 'metadata'
+ },
+
+ /**
+ * File and share public access types.
+ *
+ * @const
+ * @enum {string}
+ */
+ SharePublicAccessType: {
+ OFF: null,
+ SHARE: 'share',
+ FILE: 'file'
+ },
+
+ /**
+ * Deletion options for share snapshots
+ *
+ * @const
+ * @enum {string}
+ */
+ ShareSnapshotDeleteOptions: {
+ SHARE_AND_SNAPSHOTS: 'include'
+ },
+};
+
+module.exports = FileUtilities;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/file/internal/filerangestream.js b/src/node_modules/azure-storage/lib/services/file/internal/filerangestream.js
new file mode 100644
index 0000000..74788da
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/internal/filerangestream.js
@@ -0,0 +1,46 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var util = require('util');
+var RangeStream = require('./../../../common/streams/rangestream');
+var Constants = require('./../../../common/util/constants');
+
+/**
+* File range stream
+*/
+function FileRangeStream(fileServiceClient, share, directory, file, options) {
+ FileRangeStream['super_'].call(this, fileServiceClient, null, null, options);
+
+ this._lengthHeader = Constants.HeaderConstants.FILE_CONTENT_LENGTH;
+ if (options.minRangeSize) {
+ this._minRangeSize = options.minRangeSize;
+ } else {
+ this._minRangeSize = Constants.FileConstants.MIN_WRITE_FILE_SIZE_IN_BYTES;
+ }
+ if (options.maxRangeSize) {
+ this._maxRangeSize = options.maxRangeSize;
+ } else {
+ this._maxRangeSize = Constants.FileConstants.DEFAULT_WRITE_SIZE_IN_BYTES;
+ }
+ this._listFunc = fileServiceClient.listRanges;
+ this._resourcePath.push(share);
+ this._resourcePath.push(directory);
+ this._resourcePath.push(file);
+}
+
+util.inherits(FileRangeStream, RangeStream);
+
+module.exports = FileRangeStream;
diff --git a/src/node_modules/azure-storage/lib/services/file/models/directoryresult.js b/src/node_modules/azure-storage/lib/services/file/models/directoryresult.js
new file mode 100644
index 0000000..cefbc52
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/models/directoryresult.js
@@ -0,0 +1,58 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var HeaderConstants = require('./../../../common/common.core').Constants.HeaderConstants;
+
+/**
+* Creates a new DirectoryResult object.
+* @class
+* The DirectoryResult class is used to store the directory information.
+*
+ * @property {string} name The container name.
+ * @property {object} metadata The metadata key/value pair.
+ * @property {string} etag The etag.
+ * @property {string} lastModified The date/time that the directory was last modified.
+ * @property {string} requestId The request id.
+ * @property {string} serverEncrypted If the directory metadata is completely encrypted using the specified algorithm. true/false.
+ *
+* @constructor
+* @param {string} [name] The directory name.
+*/
+function DirectoryResult(name) {
+ this.name = name;
+}
+
+DirectoryResult.parse = function (dirXml) {
+ return new DirectoryResult(dirXml.Name);
+};
+
+DirectoryResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ var setDirectoryPropertyFromHeaders = function (directoryProperty, headerProperty) {
+ if (!self[directoryProperty] && headers[headerProperty.toLowerCase()]) {
+ self[directoryProperty] = headers[headerProperty.toLowerCase()];
+ }
+ };
+
+ setDirectoryPropertyFromHeaders('etag', HeaderConstants.ETAG);
+ setDirectoryPropertyFromHeaders('lastModified', HeaderConstants.LAST_MODIFIED);
+ setDirectoryPropertyFromHeaders('requestId', HeaderConstants.REQUEST_ID);
+ setDirectoryPropertyFromHeaders('serverEncrypted', HeaderConstants.SERVER_ENCRYPTED);
+};
+
+module.exports = DirectoryResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/file/models/fileresult.js b/src/node_modules/azure-storage/lib/services/file/models/fileresult.js
new file mode 100644
index 0000000..e527b26
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/models/fileresult.js
@@ -0,0 +1,207 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var Constants = azureCommon.Constants;
+var HeaderConstants = Constants.HeaderConstants;
+
+/**
+* Creates a new FileResult object.
+* @class
+* The FileResult class is used to store the file information.
+*
+ * @property {string} share The share name.
+ * @property {string} directory The directory name.
+ * @property {string} name The file name.
+ * @property {object} metadata The metadata key/value pair.
+ * @property {string} etag The etag.
+ * @property {string} lastModified The date/time that the file was last modified.
+ * @property {string} requestId The request id.
+ * @property {string} acceptRanges The accept ranges.
+ * @property {string} serverEncrypted If the file data and application metadata are completely encrypted using the specified algorithm. true/false.
+ * @property {string} contentRange The content range
+ * @property {string} contentLength The size of the file in bytes.
+ * @property {object} contentSettings The content settings.
+ * @property {string} contentSettings.contentType The content type.
+ * @property {string} contentSettings.contentEncoding The content encoding.
+ * @property {string} contentSettings.contentLanguage The content language.
+ * @property {string} contentSettings.cacheControl The cache control.
+ * @property {string} contentSettings.contentDisposition The content disposition.
+ * @property {string} contentSettings.contentMD5 The content MD5 hash.
+ * @property {object} copy The copy information.
+ * @property {string} copy.id The copy id.
+ * @property {string} copy.status The copy status.
+ * @property {string} copy.completionTime The copy completion time.
+ * @property {string} copy.statusDescription The copy status description.
+ * @property {string} copy.progress The copy progress.
+ * @property {string} copy.source The copy source.
+ *
+* @constructor
+* @param {string} [share] The share name.
+* @param {string} [directory] The directory name.
+* @param {string} [name] The file name.
+*/
+function FileResult(share, directory, name) {
+ this.share = share;
+ this.directory = directory;
+ this.name = name;
+}
+
+FileResult.parse = function (entryXml) {
+ var listResult = new FileResult();
+ for (var propertyName in entryXml) {
+ if (propertyName === 'Properties') {
+ // Lift out the properties onto the main object to keep consistent across all APIs like: getFileProperties
+ azureutil.setPropertyValueFromXML(listResult, entryXml[propertyName], true);
+ } else {
+ listResult[propertyName.toLowerCase()] = entryXml[propertyName];
+ }
+ }
+
+ return listResult;
+};
+
+var responseHeaders = {
+ 'acceptRanges': 'ACCEPT_RANGES',
+ 'contentLength': 'CONTENT_LENGTH',
+ 'contentRange': 'CONTENT_RANGE',
+
+ 'contentSettings.contentType': 'CONTENT_TYPE',
+ 'contentSettings.contentEncoding': 'CONTENT_ENCODING',
+ 'contentSettings.contentLanguage': 'CONTENT_LANGUAGE',
+ 'contentSettings.cacheControl': 'CACHE_CONTROL',
+ 'contentSettings.contentDisposition': 'CONTENT_DISPOSITION',
+ 'contentSettings.contentMD5': 'CONTENT_MD5',
+ 'contentSettings.fileContentMD5': 'FILE_CONTENT_MD5',
+
+ 'copy.id': 'COPY_ID',
+ 'copy.status': 'COPY_STATUS',
+ 'copy.source': 'COPY_SOURCE',
+ 'copy.progress': 'COPY_PROGRESS',
+ 'copy.completionTime': 'COPY_COMPLETION_TIME',
+ 'copy.statusDescription': 'COPY_STATUS_DESCRIPTION'
+};
+
+FileResult.prototype.getPropertiesFromHeaders = function (headers, content) {
+ var self = this;
+
+ var setFilePropertyFromHeaders = function (fileProperty, headerProperty) {
+ if (!azureutil.tryGetValueChain(self, fileProperty.split('.'), null) && headers[headerProperty.toLowerCase()]) {
+ azureutil.setObjectInnerPropertyValue(self, fileProperty.split('.'), headers[headerProperty.toLowerCase()]);
+
+ if (fileProperty === 'copy.progress') {
+ var info = azureutil.parseCopyProgress(self.copy.progress);
+ self.copy.bytesCopied = parseInt(info.bytesCopied);
+ self.copy.totalBytes = parseInt(info.totalBytes);
+ }
+ }
+ };
+
+ // For range get, 'x-ms-content-md5' indicate the overall MD5 of the file. Try to set the contentMD5 using this header if it presents
+ setFilePropertyFromHeaders('contentSettings.contentMD5', HeaderConstants.FILE_CONTENT_MD5);
+
+ setFilePropertyFromHeaders('etag', HeaderConstants.ETAG);
+ setFilePropertyFromHeaders('lastModified', HeaderConstants.LAST_MODIFIED);
+ setFilePropertyFromHeaders('requestId', HeaderConstants.REQUEST_ID);
+ setFilePropertyFromHeaders('serverEncrypted', HeaderConstants.SERVER_ENCRYPTED);
+
+ if (content) {
+ _.chain(responseHeaders).pairs().each(function (pair) {
+ var property = pair[0];
+ var header = HeaderConstants[pair[1]];
+ setFilePropertyFromHeaders(property, header);
+ });
+
+ }
+};
+
+/**
+* This method sets the HTTP headers and is used by all methods except setFileProperties and createFile.
+* Those methods will set the x-ms-* headers using setProperties.
+*/
+FileResult.setHeaders = function (webResource, options) {
+ var setHeaderProperty = function (headerProperty, fileProperty) {
+ var propertyValue = azureutil.tryGetValueChain(options, fileProperty.split('.'), null);
+ if (propertyValue) {
+ webResource.withHeader(headerProperty, propertyValue);
+ }
+ };
+
+ if (options) {
+ // Content-MD5
+ setHeaderProperty(HeaderConstants.CONTENT_MD5, 'transactionalContentMD5');
+
+ // Content-Length
+ setHeaderProperty(HeaderConstants.CONTENT_LENGTH, 'contentLength');
+
+ // Range
+ if (!azureutil.objectIsNull(options.rangeStart)) {
+ var range = 'bytes=' + options.rangeStart + '-';
+
+ if (!azureutil.objectIsNull(options.rangeEnd)) {
+ range += options.rangeEnd;
+ }
+
+ webResource.withHeader(HeaderConstants.STORAGE_RANGE, range);
+ }
+ }
+};
+
+/**
+* This method sets the x-ms-* headers and is used by setFileProperties and createFile.
+* All other methods will set the regular HTTP headers using setHeaders.
+*/
+FileResult.setProperties = function (webResource, options) {
+ var setHeaderProperty = function (headerProperty, fileProperty) {
+ var propertyValue = azureutil.tryGetValueChain(options, fileProperty.split('.'), null);
+ if (propertyValue) {
+ webResource.withHeader(headerProperty, propertyValue);
+ }
+ };
+
+ if (options) {
+ // Content-Length
+ setHeaderProperty(HeaderConstants.FILE_CONTENT_LENGTH, 'contentLength');
+
+ // Content-Type
+ setHeaderProperty(HeaderConstants.FILE_CONTENT_TYPE, 'contentSettings.contentType');
+
+ // Content-Encoding
+ setHeaderProperty(HeaderConstants.FILE_CONTENT_ENCODING, 'contentSettings.contentEncoding');
+
+ // Content-Language
+ setHeaderProperty(HeaderConstants.FILE_CONTENT_LANGUAGE, 'contentSettings.contentLanguage');
+
+ // Content-Disposition
+ setHeaderProperty(HeaderConstants.FILE_CONTENT_DISPOSITION, 'contentSettings.contentDisposition');
+
+ // Cache-Control
+ setHeaderProperty(HeaderConstants.FILE_CACHE_CONTROL, 'contentSettings.cacheControl');
+
+ // Content-MD5
+ setHeaderProperty(HeaderConstants.FILE_CONTENT_MD5, 'contentSettings.contentMD5');
+
+ if (options.metadata) {
+ webResource.addOptionalMetadataHeaders(options.metadata);
+ }
+ }
+};
+
+module.exports = FileResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/file/models/shareresult.js b/src/node_modules/azure-storage/lib/services/file/models/shareresult.js
new file mode 100644
index 0000000..823af25
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/file/models/shareresult.js
@@ -0,0 +1,84 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var Constants = azureCommon.Constants;
+var HeaderConstants = Constants.HeaderConstants;
+
+/**
+* Creates a new ShareResult object.
+* @class
+* The ShareResult class is used to store the share information.
+*
+ * @property {string} name The share name.
+ * @property {object} metadata The metadata key/value pair.
+ * @property {string} etag The etag.
+ * @property {string} lastModified The date/time that the share was last modified.
+ * @property {string} requestId The request id.
+ * @property {string} quota The share quota.
+ *
+* @constructor
+* @param {string} [name] The share name.
+*/
+function ShareResult(name) {
+ this.name = name;
+}
+
+ShareResult.parse = function (shareXml, name) {
+ var shareResult = new ShareResult(name);
+ for (var propertyName in shareXml) {
+ if (shareXml.hasOwnProperty(propertyName)) {
+ if (propertyName === 'Properties') {
+ // Lift out the properties onto the main object to keep consistent across all APIs like: getShareProperties
+ azureutil.setPropertyValueFromXML(shareResult, shareXml[propertyName], true);
+ } else if (propertyName === 'Metadata' || propertyName === 'ShareStats') {
+ var resultPropertyName = azureutil.normalizePropertyNameFromXML(propertyName);
+ shareResult[resultPropertyName] = {};
+ azureutil.setPropertyValueFromXML(shareResult[resultPropertyName], shareXml[propertyName], propertyName === 'ShareStats');
+ } else {
+ shareResult[propertyName.toLowerCase()] = shareXml[propertyName];
+ }
+ }
+ }
+
+ return shareResult;
+};
+
+ShareResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ var setSharePropertyFromHeaders = function (shareProperty, headerProperty) {
+ if (!self[shareProperty] && headers[headerProperty.toLowerCase()]) {
+ self[shareProperty] = headers[headerProperty.toLowerCase()];
+ }
+ };
+
+ setSharePropertyFromHeaders('etag', HeaderConstants.ETAG);
+ setSharePropertyFromHeaders('lastModified', HeaderConstants.LAST_MODIFIED);
+ setSharePropertyFromHeaders('requestId', HeaderConstants.REQUEST_ID);
+ setSharePropertyFromHeaders('quota', HeaderConstants.SHARE_QUOTA);
+};
+
+/**
+* The share ACL settings.
+* @typedef {object} ShareAclResult
+* @extends {ShareAclResult}
+* @property {Object.} signedIdentifiers The container ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+*/
+
+module.exports = ShareResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/queue/models/queuemessageresult.js b/src/node_modules/azure-storage/lib/services/queue/models/queuemessageresult.js
new file mode 100644
index 0000000..94270ed
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/queue/models/queuemessageresult.js
@@ -0,0 +1,130 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var xmlbuilder = azureCommon.xmlbuilder;
+var Constants = azureCommon.Constants;
+
+var HeaderConstants = Constants.HeaderConstants;
+
+/**
+* Creates a new QueueMessageResult object.
+* @class
+* The QueueMessageResult class is used to store the queue message information.
+*
+* @property {string} queue The queue name.
+* @property {string} messageId The message id.
+* @property {string} popReceipt The pop receipt.
+* @property {string} messageText The message text.
+* @property {string} timeNextVisible The time next visible.
+* @property {string} insertionTime The insertion time.
+* @property {string} expirationTime The expiration time.
+* @property {number} dequeueCount The dequeue count.
+ *
+* @constructor
+* @param {string} [queue] The queue name.
+* @param {string} [messageId] The message id.
+* @param {string} [popReceipt] The pop receipt.
+*/
+function QueueMessageResult(queue, messageId, popReceipt) {
+ if (queue) {
+ this.queue = queue;
+ }
+
+ if (messageId) {
+ this.messageId = messageId;
+ }
+
+ if (popReceipt) {
+ this.popReceipt = popReceipt;
+ }
+}
+
+/**
+* Builds an XML representation for a queue message
+*
+* @param {string} messageJs The queue message.
+* @param {QueueMessageEncoder} The message encoder.
+* @return {string} The XML queue message.
+*/
+QueueMessageResult.serialize = function (messageJs, encoder) {
+ var doc = xmlbuilder.create(Constants.QueueConstants.QUEUE_MESSAGE_ELEMENT, { version: '1.0', encoding: 'utf-8' });
+
+ if (messageJs) {
+ var message;
+ if (encoder !== null && encoder !== undefined) {
+ message = encoder.encode(messageJs);
+ } else {
+ message = messageJs;
+ }
+
+ doc.ele(Constants.QueueConstants.MESSAGE_TEXT_ELEMENT)
+ .txt(message)
+ .up();
+ } else {
+ doc.ele(Constants.QueueConstants.MESSAGE_TEXT_ELEMENT).up();
+ }
+
+ return doc.doc().toString();
+};
+
+
+/**
+* Pase the XML representation of a queue message to a QueueMessageResult object.
+*
+* @param {Object} messageXml The XML representation of the queue message.
+* @param {QueueMessageEncoder} The message encoder.
+* @return {QueueMessageResult} The QueueMessageResult object.
+*/
+QueueMessageResult.parse = function (messageXml, encoder) {
+ var queueMessageResult = new QueueMessageResult();
+ for (var property in messageXml) {
+ if (property === Constants.QueueConstants.MESSAGE_TEXT_ELEMENT) {
+ if (encoder !== null && encoder !== undefined) {
+ queueMessageResult.messageText = encoder.decode(messageXml[property]);
+ } else {
+ queueMessageResult.messageText = messageXml[property];
+ }
+ } else {
+ var resultPropertyName = azureutil.normalizePropertyNameFromXML(property);
+ queueMessageResult[resultPropertyName] = messageXml[property];
+ }
+ }
+
+ // Convert dequeueCount to number
+ if (queueMessageResult.dequeueCount) {
+ queueMessageResult.dequeueCount = parseInt(queueMessageResult.dequeueCount);
+ }
+
+ return queueMessageResult;
+};
+
+QueueMessageResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ var setmessagePropertyFromHeaders = function (messageProperty, headerProperty) {
+ if (!self[messageProperty] && headers[headerProperty.toLowerCase()]) {
+ self[messageProperty] = headers[headerProperty.toLowerCase()];
+ }
+ };
+
+ setmessagePropertyFromHeaders('popReceipt', HeaderConstants.POP_RECEIPT);
+ setmessagePropertyFromHeaders('timeNextVisible', HeaderConstants.TIME_NEXT_VISIBLE);
+};
+
+module.exports = QueueMessageResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/queue/models/queueresult.js b/src/node_modules/azure-storage/lib/services/queue/models/queueresult.js
new file mode 100644
index 0000000..bf14244
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/queue/models/queueresult.js
@@ -0,0 +1,72 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var Constants = require('./../../../common/common.core').Constants;
+var HeaderConstants = Constants.HeaderConstants;
+
+/**
+* Creates a new QueueResult object.
+* @class
+* The QueueResult class is used to store the queue information.
+*
+* @property {string} name The queue name.
+* @property {object} metadata The metadata key/value pair.
+* @property {number} approximateMessageCount 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.
+* @property {Object.} signedIdentifiers The container ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+ *
+* @constructor
+* @param {string} [name] The queue name.
+* @param {string} [metadata] The metadata key/value pair.
+*/
+function QueueResult(name, metadata) {
+ if (name) {
+ this.name = name;
+ }
+
+ if (metadata) {
+ this.metadata = metadata;
+ }
+}
+
+QueueResult.parse = function (messageXml) {
+ var queueResult = new QueueResult();
+ for (var property in messageXml) {
+ if (messageXml.hasOwnProperty(property)) {
+ queueResult[property.toLowerCase()] = messageXml[property];
+ }
+ }
+
+ return queueResult;
+};
+
+QueueResult.prototype.getPropertiesFromHeaders = function (headers) {
+ var self = this;
+
+ var setPropertyFromHeaders = function (queueProperty, headerProperty, typeConverterFunc) {
+ if (!self[queueProperty] && headers[headerProperty.toLowerCase()]) {
+ if(typeConverterFunc) {
+ self[queueProperty] = typeConverterFunc(headers[headerProperty.toLowerCase()]);
+ } else{
+ self[queueProperty] = headers[headerProperty.toLowerCase()];
+ }
+ }
+ };
+
+ setPropertyFromHeaders('approximateMessageCount', HeaderConstants.APPROXIMATE_MESSAGES_COUNT, parseInt);
+};
+
+module.exports = QueueResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/queue/queuemessageencoder.js b/src/node_modules/azure-storage/lib/services/queue/queuemessageencoder.js
new file mode 100644
index 0000000..a3d22bf
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/queue/queuemessageencoder.js
@@ -0,0 +1,182 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+
+var util = require('util');
+
+/**
+ * The interface for classes that represent a encoder which can be used to specify how the queue service encodes and decodes queue messages.
+ *
+ * To specify how the queue service encodes and decodes queue messages, set `queueService.messageEncoder` to object of built-in encoder types
+ * `[TextBase64QueueMessageEncoder]{@link TextBase64QueueMessageEncoder}`, `[BinaryBase64QueueMessageEncoder]{@link BinaryBase64QueueMessageEncoder}`, `[TextXmlQueueMessageEncoder]{@link TextXmlQueueMessageEncoder}`,
+ * or custom implementation of the QueueMessageEncoder.
+ *
+ * @class
+ */
+function QueueMessageEncoder() {
+}
+
+/**
+ * Function to encode queue messages.
+ *
+ * @param {object} [input] The target to be encoded.
+ * @return {string}
+ */
+QueueMessageEncoder.prototype.encode = function(input){
+ return input;
+};
+
+/**
+ * Function to decode queue messages
+ *
+ * @param {string} [textToBeDecoded] The base64 string to be decoded.
+ * @returns {any}
+ */
+QueueMessageEncoder.prototype.decode = function(textToBeDecoded){
+ return textToBeDecoded;
+};
+
+
+/**
+ * Create a new TextBase64QueueMessageEncoder object
+ * @class
+ *
+ * Encode from utf-8 string to base64 string
+ * Decode from base64 string to utf-8 string.
+ *
+ * @constructor
+ * @extends {QueueMessageEncoder}
+ */
+function TextBase64QueueMessageEncoder(){
+}
+util.inherits(TextBase64QueueMessageEncoder, QueueMessageEncoder);
+
+/**
+ * Encode from utf-8 string to base64 string
+ * @this TextBase64QueueMessageEncoder
+ *
+ * @param {string} [input] The target to be encoded.
+ *
+ * @return {string}
+ */
+TextBase64QueueMessageEncoder.prototype.encode = function(input){
+ return Buffer.from(input, 'utf8').toString('base64');
+};
+
+/**
+ * Decode from base64 string to utf-8 string.
+ * @this TextBase64QueueMessageEncoder
+ *
+ * @param {string} [textToBeDecoded] The base64 string to be decoded.
+ *
+ * @return {string}
+ */
+TextBase64QueueMessageEncoder.prototype.decode = function(textToDecode){
+ return Buffer.from(textToDecode, 'base64').toString('utf8');
+};
+
+
+/**
+ * Create a new BinaryBase64QueueMessageEncoder object
+ * @class
+ *
+ * Encode from binary buffer to base64 string
+ * Decode from base64 string to binary buffer.
+ *
+ * @constructor
+ * @extends {QueueMessageEncoder}
+ */
+function BinaryBase64QueueMessageEncoder(){
+}
+util.inherits(BinaryBase64QueueMessageEncoder, QueueMessageEncoder);
+
+/**
+ * Encode from binary buffer string to base64 string
+ * @this BinaryBase64QueueMessageEncoder
+ *
+ * @param {Buffer} [input] The target to be encoded.
+ *
+ * @return {string}
+ */
+BinaryBase64QueueMessageEncoder.prototype.encode = function(input){
+ return input.toString('base64');
+};
+
+
+/**
+ * Decode from base64 string to binary buffer.
+ * @this BinaryBase64QueueMessageEncoder
+ *
+ * @param {string} [textToBeDecoded] The base64 string to be decoded.
+ *
+ * @return {Buffer}
+ */
+BinaryBase64QueueMessageEncoder.prototype.decode = function(textToDecode){
+ return Buffer.from(textToDecode, 'base64');
+};
+
+
+/**
+ * Create a new TextXmlQueueMessageEncoder object
+ * @class
+ *
+ * Encode utf-8 string by escaping the xml markup characters.
+ * Decode from utf-8 string by unescaping the xml markup characters.
+ *
+ * @constructor
+ * @extends {QueueMessageEncoder}
+ */
+function TextXmlQueueMessageEncoder(){
+}
+util.inherits(TextXmlQueueMessageEncoder, QueueMessageEncoder);
+
+/**
+ * Encode utf-8 string by escaping the xml markup characters.
+ * @this TextXmlQueueMessageEncoder
+ *
+ * @param {string} [input] The target to be encoded.
+ *
+ * @return {string}
+ */
+TextXmlQueueMessageEncoder.prototype.encode = function(input){
+ return input.replace(/&/gm, '&')
+ .replace(//gm, '>')
+ .replace(/"/gm, '"')
+ .replace(/'/gm, ''');
+};
+
+/**
+ * Decode from utf-8 string by unescaping the xml markup characters.
+ * @this TextXmlQueueMessageEncoder
+ *
+ * @param {string} [textToBeDecoded] The base64 string to be decoded.
+ *
+ * @return {string}
+ */
+TextXmlQueueMessageEncoder.prototype.decode = function(textToDecode){
+ return textToDecode.replace(/&/gm, '&')
+ .replace(/</gm, '<')
+ .replace(/>/gm, '>')
+ .replace(/"/gm, '"')
+ .replace(/'/gm, '\'');
+};
+
+module.exports = QueueMessageEncoder;
+module.exports.TextBase64QueueMessageEncoder = TextBase64QueueMessageEncoder;
+module.exports.BinaryBase64QueueMessageEncoder = BinaryBase64QueueMessageEncoder;
+module.exports.TextXmlQueueMessageEncoder = TextXmlQueueMessageEncoder;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/queue/queueservice.js b/src/node_modules/azure-storage/lib/services/queue/queueservice.js
new file mode 100644
index 0000000..a3b05e8
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/queue/queueservice.js
@@ -0,0 +1,1472 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var util = require('util');
+var _ = require('underscore');
+var extend = require('extend');
+
+var azureCommon = require('./../../common/common.core');
+var azureutil = azureCommon.util;
+var SR = azureCommon.SR;
+var validate = azureCommon.validate;
+
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var WebResource = azureCommon.WebResource;
+var Constants = azureCommon.Constants;
+var QueryStringConstants = Constants.QueryStringConstants;
+var HeaderConstants = Constants.HeaderConstants;
+var RequestLocationMode = Constants.RequestLocationMode;
+
+// Models requires
+var QueueResult = require('./models/queueresult');
+var AclResult = azureCommon.AclResult;
+var QueueMessageResult = require('./models/queuemessageresult');
+var QueueMessageEncoder = require('./queuemessageencoder');
+var ServiceStatsParser = azureCommon.ServiceStatsParser;
+
+/**
+* Creates a new QueueService object.
+* If no connection string or storageaccount and storageaccesskey are provided,
+* the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
+* @class
+* The QueueService class is used to perform operations on the Microsoft Azure Queue Service.
+*
+* For more information on using the Queue Service, as well as task focused information on using it from a Node.js application, see
+* [How to Use the Queue Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-queues/).
+* The following defaults can be set on the Queue service.
+* messageEncoder The message encoder to specify how QueueService encodes and decodes the queue message. Default is `[TextXmlQueueMessageEncoder]{@link TextXmlQueueMessageEncoder}`.
+* defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Queue service.
+* defaultClientRequestTimeoutInMs The default timeout of client requests, in milliseconds, to use for the request made via the Queue service.
+* defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Queue service.
+* defaultLocationMode The default location mode for requests made via the Queue service.
+* useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Queue service; true to use the
+* Nagle algorithm; otherwise, false. The default value is false.
+* enableGlobalHttpAgent Determines whether global HTTP(s) agent is enabled; true to use Global HTTP(s) agent; otherwise, false to use
+* http(s).Agent({keepAlive:true}).
+* @constructor
+* @augments {StorageServiceClient}
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} [sas] The Shared Access Signature string.
+* @param {string} [endpointSuffix] The endpoint suffix.
+* @param {TokenCredential} [token] The {@link TokenCredential} object.
+*/
+function QueueService(storageAccountOrConnectionString, storageAccessKey, host, sas, endpointSuffix, token) {
+ var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sas, endpointSuffix, token);
+
+ QueueService['super_'].call(this,
+ storageServiceSettings._name,
+ storageServiceSettings._key,
+ storageServiceSettings._queueEndpoint,
+ storageServiceSettings._usePathStyleUri,
+ storageServiceSettings._sasToken,
+ token);
+
+ if (this.anonymous) {
+ throw new Error(SR.ANONYMOUS_ACCESS_BLOBSERVICE_ONLY);
+ }
+
+ /**
+ * @property {boolean} QueueService#messageEncoder
+ * @defaultvalue {QueueMessageEncoder} `[TextXmlQueueMessageEncoder]{@link TextXmlQueueMessageEncoder}`.
+ * The message encoder to specify how QueueService encodes and decodes the queue message. Default is `[TextXmlQueueMessageEncoder]{@link TextXmlQueueMessageEncoder}`.
+ */
+ this.messageEncoder = new QueueMessageEncoder.TextXmlQueueMessageEncoder();
+}
+
+util.inherits(QueueService, StorageServiceClient);
+
+/**
+* Gets the service stats for a storage account’s Queue service.
+*
+* @this {QueueService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise, `[result]{@link ServiceStats}`
+* will contain the stats and `response`
+* will contain information related to this operation.
+*/
+QueueService.prototype.getServiceStats = function (optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getServiceStats', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get()
+ .withQueryOption(QueryStringConstants.COMP, 'stats')
+ .withQueryOption(QueryStringConstants.RESTYPE, 'service');
+
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.serviceStatsResult = null;
+ if (!responseObject.error) {
+ responseObject.serviceStatsResult = ServiceStatsParser.parse(responseObject.response.body.StorageServiceStats);
+ }
+
+ // function to be called after all filters
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.serviceStatsResult, returnObject.response);
+ };
+
+ // call the first filter
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets the properties of a storage account’s Queue service, including Microsoft Azure Storage Analytics.
+*
+* @this {QueueService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise, `[result]{@link ServiceProperties}`
+* will contain the properties and `response`
+* will contain information related to this operation.
+*/
+QueueService.prototype.getServiceProperties = function (optionsOrCallback, callback) {
+ return this.getAccountServiceProperties(optionsOrCallback, callback);
+};
+
+/**
+* Sets the properties of a storage account’s Queue service, including Microsoft Azure Storage Analytics.
+* You can also use this operation to set the default request version for all incoming requests that do not have a version specified.
+*
+* @this {QueueService}
+* @param {object} serviceProperties The service properties.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise, `response`
+* will contain information related to this operation.
+*/
+QueueService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) {
+ return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of queue items whose names begin with the specified prefix under the given account.
+*
+* @this {QueueService}
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {int} [options.maxResults] Specifies the maximum number of queues to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {string} [options.include] Include this parameter to specify that the queue's metadata be returned as part of the response body. (allowed values: '', 'metadata')
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[queues]{@link QueueResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.listQueuesSegmented = function (currentToken, optionsOrCallback, callback) {
+ this.listQueuesSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of queue items under the given account.
+*
+* @this {QueueService}
+* @param {string} prefix The prefix of the queue name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.* @param {string} [options.prefix] Filters the results to return only queues whose name begins with the specified prefix.
+* @param {object} [options] The request options.
+* @param {string} [options.marker] String value that identifies the portion of the list to be returned with the next list operation.
+* @param {int} [options.maxResults] Specifies the maximum number of queues to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
+* @param {string} [options.include] Include this parameter to specify that the queue's metadata be returned as part of the response body. (allowed values: '', 'metadata')
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of `[queues]{@link QueueResult}` and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.listQueuesSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listQueuesSegmentedWithPrefix', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get();
+ webResource.withQueryOption(QueryStringConstants.COMP, 'list')
+ .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults)
+ .withQueryOption(QueryStringConstants.INCLUDE, options.include)
+ .withQueryOption(QueryStringConstants.PREFIX, prefix);
+
+ if(!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker);
+ }
+
+ options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.listQueuesResult = null;
+
+ if (!responseObject.error) {
+ responseObject.listQueuesResult = {
+ entries: null,
+ continuationToken: null
+ };
+ responseObject.listQueuesResult.entries = [];
+ var queues = [];
+
+ if (responseObject.response.body.EnumerationResults.Queues && responseObject.response.body.EnumerationResults.Queues.Queue) {
+ queues = responseObject.response.body.EnumerationResults.Queues.Queue;
+
+ if (!_.isArray(queues)) {
+ queues = [ queues ];
+ }
+
+ queues.forEach(function (currentQueue) {
+ var queueResult = QueueResult.parse(currentQueue);
+ responseObject.listQueuesResult.entries.push(queueResult);
+ });
+
+ if(responseObject.response.body.EnumerationResults.NextMarker) {
+ responseObject.listQueuesResult.continuationToken = {
+ nextMarker: null,
+ targetLocation: null
+ };
+
+ responseObject.listQueuesResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker;
+ responseObject.listQueuesResult.continuationToken.targetLocation = responseObject.targetLocation;
+ }
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.listQueuesResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Checks to see if a queue exists.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise, `[result]{@link QueueResult}` will contain
+* the queue information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.doesQueueExist = function (queue, optionsOrCallback, callback) {
+ this._doesQueueExist(queue, false, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new queue under the given account.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueResult}` will contain
+* the queue information.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.createQueue = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createQueue', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(queue);
+ if (options) {
+ webResource.addOptionalMetadataHeaders(options.metadata);
+ }
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueResult = null;
+ if (!responseObject.error) {
+ responseObject.queueResult = new QueueResult(queue);
+ if (options && options.metadata) {
+ responseObject.queueResult.metadata = options.metadata;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Creates a new queue under the given account if it doesn't exist.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {object} [options.metadata] The metadata key/value pairs.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueResult}` will contain
+* the queue information including `created` boolean member and
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var queueService = azure.createQueueService();
+* queueService.createQueueIfNotExists('taskqueue', function(error) {
+* if(!error) {
+* // Queue created or exists
+* }
+* });
+*/
+QueueService.prototype.createQueueIfNotExists = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createQueueIfNotExists', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var self = this;
+ self._doesQueueExist(queue, true, options, function(error, result, response) {
+ var exists = result.exists;
+ result.created = false;
+ delete result.exists;
+
+ if (error) {
+ callback(error, result, response);
+ } else if (exists) {
+ response.isSuccessful = true;
+ callback(error, result, response);
+ } else {
+ self.createQueue(queue, options, function(createError, responseQueue, createResponse) {
+ if (!createError) {
+ responseQueue.created = true;
+ }
+ else if (createError && createError.statusCode === Constants.HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.QueueErrorCodeStrings.QUEUE_ALREADY_EXISTS) {
+ createError = null;
+ responseQueue.created = false;
+ createResponse.isSuccessful = true;
+ }
+
+ callback(createError, responseQueue, createResponse);
+ });
+ }
+ });
+};
+
+/**
+* Permanently deletes the specified queue.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information if an error occurs;
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.deleteQueue = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteQueue', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.del(queue);
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Permanently deletes the specified queue if it exists.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* 'true' if the queue was deleted and 'false' if the queue did not exist.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.deleteQueueIfExists = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteQueueIfExists', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var self = this;
+ self._doesQueueExist(queue, true, options, function existsCallback(error, existsResult, response) {
+ if (error) {
+ callback(error, existsResult.exists, response);
+ } else if (!existsResult.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteQueue(queue, options, function(deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError) {
+ deleted = true;
+ } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.QueueErrorCodeStrings.QUEUE_NOT_FOUND) {
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+/**
+* Returns queue properties, including user-defined metadata.
+* **Note** that all metadata names returned from the server will be converted to lower case by NodeJS itself as metadata is set via HTTP headers and HTTP header names are case insensitive.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueResult}` will contain
+* the queue information.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.getQueueMetadata = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getQueueMetadata', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(queue)
+ .withQueryOption(QueryStringConstants.COMP, 'metadata');
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var self = this;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueResult = null;
+ if (!responseObject.error) {
+ responseObject.queueResult = new QueueResult(queue);
+ responseObject.queueResult.metadata = self.parseMetadataHeaders(responseObject.response.headers);
+ responseObject.queueResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Sets user-defined metadata on the specified queue. Metadata is associated with the queue as name-value pairs.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} metadata The metadata key/value pairs.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueResult}` will contain
+* the queue information.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.setQueueMetadata = function (queue, metadata, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setQueueMetadata', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.put(queue)
+ .withQueryOption(QueryStringConstants.COMP, 'metadata')
+ .addOptionalMetadataHeaders(metadata);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueResult = null;
+ if (!responseObject.error) {
+ responseObject.queueResult = new QueueResult(queue, metadata);
+ responseObject.queueResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Adds a new message to the back of the message queue.
+* The encoded message can be up to 64KB in size for versions 2011-08-18 and newer, or 8KB in size for previous versions.
+* Unencoded messages must be in a format that can be included in an XML request with UTF-8 encoding.
+* Queue messages are encoded using the `[TextXmlQueueMessageEncoder]{@link TextXmlQueueMessageEncoder}`. See queueService.messageEncoder to set encoder defaults.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {string|Buffer} messageText The message text.
+* @param {object} [options] The request options.
+* @param {int} [options.messageTimeToLive] The time-to-live interval for the message, in seconds. The maximum time-to-live allowed is 7 days. If this parameter is omitted, the default time-to-live is 7 days
+* @param {int} [options.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. visibilitytimeout should be set to a value smaller than the time-to-live value.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueMessageResult}` will contain
+* the message.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var queueService = azure.createQueueService();
+* queueService.createMessage('taskqueue', 'Hello world!', function(error) {
+* if(!error) {
+* // Message inserted
+* }
+* });
+*/
+QueueService.prototype.createMessage = function (queue, messageText, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createMessage', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var xmlMessageDescriptor = QueueMessageResult.serialize(messageText, this.messageEncoder);
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.post(queue + '/messages')
+ .withHeader(HeaderConstants.CONTENT_TYPE, 'application/atom+xml;charset="utf-8"')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(xmlMessageDescriptor, 'utf8'))
+ .withQueryOption(QueryStringConstants.MESSAGE_TTL, options.messageTimeToLive)
+ .withQueryOption(QueryStringConstants.VISIBILITY_TIMEOUT, options.visibilityTimeout)
+ .withBody(xmlMessageDescriptor);
+
+ var messageEncoder = this.messageEncoder;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueMessageResults = [];
+
+ if (responseObject.response && responseObject.response.body && responseObject.response.body.QueueMessagesList && responseObject.response.body.QueueMessagesList.QueueMessage) {
+ var messages = responseObject.response.body.QueueMessagesList.QueueMessage;
+
+ if (!_.isArray(messages)) {
+ messages = [ messages ];
+ }
+
+ messages.forEach(function (message) {
+ var queueMessageResult = QueueMessageResult.parse(message, messageEncoder);
+ responseObject.queueMessageResults.push(queueMessageResult);
+ });
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, responseObject.queueMessageResults[0], returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Retrieve messages from the queue and makes them invisible to other consumers.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {int} [options.numOfMessages] A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
+* @param {int} [options.visibilityTimeout] Required if not peek only. 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 can be set to a value later than the expiry time.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* a list of `[messages]{@link QueueMessageResult}`.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var queueService = azure.createQueueService();
+* var queueName = 'taskqueue';
+* queueService.getMessages(queueName, function(error, serverMessages) {
+* if(!error) {
+* // Process the message in less than 30 seconds, the message
+* // text is available in serverMessages[0].messagetext
+* queueService.deleteMessage(queueName, serverMessages[0].messageId, serverMessages[0].popReceipt, function(error) {
+* if(!error){
+* // Message deleted
+* }
+* });
+* }
+* });
+*/
+QueueService.prototype.getMessages = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getMessages', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ delete options.peekOnly;
+
+ this._getOrPeekMessages(queue, options, callback);
+};
+
+/**
+* Retrieves a message from the queue and makes it invisible to other consumers.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {int} [options.visibilityTimeout] Required if not peek only. 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 can be set to a value later than the expiry time.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueMessageResult}` will contain
+* the message.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var queueService = azure.createQueueService();
+* var queueName = 'taskqueue';
+* queueService.getMessage(queueName, function(error, serverMessage) {
+* if(!error) {
+* // Process the message in less than 30 seconds, the message
+* // text is available in serverMessage.messagetext
+* queueService.deleteMessage(queueName, serverMessage.messageId, serverMessage.popReceipt, function(error) {
+* if(!error){
+* // Message deleted
+* }
+* });
+* }
+* });
+*/
+QueueService.prototype.getMessage = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getMessage', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.numOfMessages = 1;
+
+ var finalCallback = function(error, messages, response){
+ var message;
+ if(messages && messages.length > 0){
+ message = messages[0];
+ }
+
+ callback(error, message, response);
+ };
+
+ this.getMessages(queue, options, finalCallback);
+};
+
+/**
+* Retrieves messages from the front of the queue, without changing the messages visibility.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {int} [options.numOfMessages] A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `result` will contain
+* `[messages]{@link QueueMessageResult}`.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.peekMessages = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('peekMessages', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.peekOnly = true;
+ delete options.visibilityTimeout;
+
+ this._getOrPeekMessages(queue, options, callback);
+};
+
+/**
+* Retrieves a message from the front of the queue, without changing the message visibility.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueMessageResult}` will contain
+* the message.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.peekMessage = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('peekMessage', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.numOfMessages = 1;
+
+ var finalCallback = function(error, messages, response){
+ var message;
+ if(messages && messages.length > 0){
+ message = messages[0];
+ }
+
+ callback(error, message, response);
+ };
+
+ this.peekMessages(queue, options, finalCallback);
+};
+
+/**
+* Deletes a specified message from the queue.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {string} messageId The message identifier of the message to delete.
+* @param {string} popReceipt A valid pop receipt value returned from an earlier call to the Get Messages or Update Message operation
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information if an error occurs;
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.deleteMessage = function (queue, messageId, popReceipt, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteMessage', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ if (azureutil.objectIsNull(popReceipt)) {
+ throw new Error(SR.INVALID_POP_RECEIPT);
+ }
+
+ if (azureutil.objectIsNull(messageId)) {
+ throw new Error(SR.INVALID_MESSAGE_ID);
+ }
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.del(queue + '/messages/' + messageId)
+ .withQueryOption(QueryStringConstants.POP_RECEIPT, popReceipt, null, true);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Clears all messages from the queue.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information
+* if an error occurs; otherwise
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.clearMessages = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('clearMessages', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.del(queue + '/messages');
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* 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.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {string} messageId The message identifier of the message to update.
+* @param {string} popReceipt A valid pop receipt value returned from an earlier call to the Get Messages or Update Message operation
+* @param {int} 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 can be set to a value later than the expiry time.
+* @param {object} [options] The request options.
+* @param {object} [options.messageText] The new message text.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueMessageResult}` will contain
+* the message result information.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.updateMessage = function (queue, messageId, popReceipt, visibilityTimeout, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('updateMessage', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ if (azureutil.objectIsNull(popReceipt)) {
+ throw new Error(SR.INVALID_POP_RECEIPT);
+ }
+
+ if (azureutil.objectIsNull(messageId)) {
+ throw new Error(SR.INVALID_MESSAGE_ID);
+ }
+
+ var options = extend(true, {}, userOptions);
+ var content = null;
+ if (options.messageText) {
+ content = QueueMessageResult.serialize(options.messageText, this.messageEncoder);
+ }
+
+ var contentLength = content ? Buffer.byteLength(content, 'utf8') : 0;
+
+ var webResource = WebResource.put(queue + '/messages/' + messageId)
+ .withHeader(HeaderConstants.CONTENT_TYPE, 'application/atom+xml;charset="utf-8"')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, contentLength)
+ .withQueryOption(QueryStringConstants.POP_RECEIPT, popReceipt, null, true)
+ .withQueryOption(QueryStringConstants.VISIBILITY_TIMEOUT, visibilityTimeout)
+ .withBody(content);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueMessageResult = null;
+ if (!responseObject.error) {
+ responseObject.queueMessageResult = new QueueMessageResult(queue, messageId);
+ responseObject.queueMessageResult.getPropertiesFromHeaders(responseObject.response.headers);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueMessageResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Gets the queue's ACL.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueResult}` will contain
+* information for the queue.
+* `response` will contain information related to this operation.
+*/
+QueueService.prototype.getQueueAcl = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getQueueAcl', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.get(queue)
+ .withQueryOption(QueryStringConstants.COMP, 'acl');
+
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueResult = null;
+ if (!responseObject.error) {
+ responseObject.queueResult = new QueueResult(queue);
+ responseObject.queueResult.getPropertiesFromHeaders(responseObject.response.headers);
+ responseObject.queueResult.signedIdentifiers = AclResult.parse(responseObject.response.body);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Updates the queue's ACL.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @property {Object.} signedIdentifiers The container ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information
+* if an error occurs; otherwise `[result]{@link QueueResult}` will contain
+* information for the queue.
+* `response` will contain information related to this operation.
+* @example
+* var azure = require('azure-storage');
+* var SharedAccessPermissions = azure.QueueUtilities.SharedAccessPermissions;
+* var queueService = azure.createQueueService();
+* var sharedAccessPolicies = [
+* {AccessPolicy: {
+* Permissions: PROCESS,
+* Start: startDate,
+* Expiry: expiryDate
+* },
+* Id: processOnly,
+* },
+* {AccessPolicy: {
+* Permissions: SharedAccessPermissions.PROCESS + SharedAccessPermissions.DELETE,
+* Start: startDate,
+* Expiry: expiryDate
+* },
+* Id: processAndDelete,
+* }];
+*
+* queueService.setQueueAcl(queueName, sharedAccessPolicies, function(error, queueResult, response) {
+* // do whatever
+* });
+*/
+QueueService.prototype.setQueueAcl = function (queue, signedIdentifiers, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setQueueAcl', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var policies = null;
+ if (signedIdentifiers) {
+ if(_.isArray(signedIdentifiers)) {
+ throw new TypeError(SR.INVALID_SIGNED_IDENTIFIERS);
+ }
+ policies = AclResult.serialize(signedIdentifiers);
+ }
+
+ var webResource = WebResource.put(queue)
+ .withQueryOption(QueryStringConstants.COMP, 'acl')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0)
+ .withBody(policies);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.containerResult = null;
+ if (!responseObject.error) {
+ responseObject.queueResult = new QueueResult(queue);
+ responseObject.queueResult.getPropertiesFromHeaders(responseObject.response.headers);
+ if (signedIdentifiers) {
+ responseObject.queueResult.signedIdentifiers = signedIdentifiers;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Retrieves a shared access signature token.
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {string} [sharedAccessPolicy.Id] The signed identifier.
+* @param {object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used).
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired (The UTC value will be used).
+* @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} sharedAccessPolicy.AccessPolicy.Protocols The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* @return {string} The shared access signature query string. Note this string does not contain the leading "?".
+*/
+QueueService.prototype.generateSharedAccessSignature = function (queue, sharedAccessPolicy) {
+ // check if the QueueService is able to generate a shared access signature
+ if (!this.storageCredentials || !this.storageCredentials.generateSignedQueryString) {
+ throw new Error(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
+ }
+
+ validate.validateArgs('generateSharedAccessSignature', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.object(sharedAccessPolicy, 'sharedAccessPolicy');
+ });
+
+ return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.Queue, queue, sharedAccessPolicy, null);
+};
+
+/**
+* Checks to see if a queue exists.
+* @ignore
+*
+* @this {QueueService}
+* @param {string} queue The queue name.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information
+* if an error occurs; otherwise, `result` will contain
+* the queue information including `exists` boolean member
+* and `response` will contain information related to this operation.
+*
+*/
+QueueService.prototype._doesQueueExist = function (queue, primaryOnly, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('doesQueueExist', function(v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ var webResource = WebResource.head(queue)
+ .withQueryOption(QueryStringConstants.COMP, 'metadata');
+
+ if(primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }
+
+ var processResponseCallback = function(responseObject, next) {
+ responseObject.queueResult = new QueueResult(queue);
+ responseObject.queueResult.exists = false;
+
+ if (!responseObject.error) {
+ responseObject.queueResult.exists = true;
+ responseObject.queueResult.getPropertiesFromHeaders(responseObject.response.headers);
+
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.queueResult.exists = false;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+ * @ignore
+ */
+QueueService.prototype._getOrPeekMessages = function (queue, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('_getOrPeekMessages', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ if (!options.numOfMessages) {
+ options.numOfMessages = 1;
+ }
+
+ var webResource = WebResource.get(queue + '/messages')
+ .withQueryOption(QueryStringConstants.NUM_OF_MESSAGES, options.numOfMessages)
+ .withQueryOption(QueryStringConstants.VISIBILITY_TIMEOUT, options.visibilityTimeout)
+ .withQueryOption(QueryStringConstants.PEEK_ONLY, options.peekOnly);
+
+ if (options.peekOnly) {
+ // For peek message, it's a read-only action and can be performed against secondary endpoint.
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }
+
+
+ var messageEncoder = this.messageEncoder;
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queueMessageResults = null;
+
+ if (!responseObject.error) {
+ responseObject.queueMessageResults = [];
+
+ if (responseObject.response.body.QueueMessagesList && responseObject.response.body.QueueMessagesList.QueueMessage) {
+ var messages = responseObject.response.body.QueueMessagesList.QueueMessage;
+
+ if (!_.isArray(messages)) {
+ messages = [ messages ];
+ }
+
+ messages.forEach(function (message) {
+ var queueMessageResult = QueueMessageResult.parse(message, messageEncoder);
+ responseObject.queueMessageResults.push(queueMessageResult);
+ });
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queueMessageResults, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Retrieves a queue URL.
+*
+* @param {string} queue The queue name.
+* @param {string} [sasToken] The Shared Access Signature token.
+* @param {boolean} [primary] A boolean representing whether to use the primary or the secondary endpoint.
+* @return {string} The formatted URL string.
+* @example
+* var azure = require('azure-storage');
+* var queueService = azure.createQueueService();
+* var sharedAccessPolicy = {
+* AccessPolicy: {
+* Permissions: azure.QueueUtilities.SharedAccessPermissions.READ,
+* Start: startDate,
+* Expiry: expiryDate
+* },
+* };
+*
+* var sasToken = queueService.generateSharedAccessSignature(queue, sharedAccessPolicy);
+* var sasUrl = queueService.getUrl(queue, sasToken);
+*/
+QueueService.prototype.getUrl = function (queue, sasToken, primary) {
+ validate.validateArgs('getUrl', function (v) {
+ v.string(queue, 'queue');
+ v.queueNameIsValid(queue);
+ });
+
+ return this._getUrl(queue, sasToken, primary);
+};
+
+module.exports = QueueService;
diff --git a/src/node_modules/azure-storage/lib/services/queue/queueutilities.js b/src/node_modules/azure-storage/lib/services/queue/queueutilities.js
new file mode 100644
index 0000000..eca40a6
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/queue/queueutilities.js
@@ -0,0 +1,39 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'QueueUtilities'.
+exports = module.exports;
+
+/**
+* Defines enums for use with the Queue service.
+* @namespace QueueUtilities
+*/
+var QueueUtilities = {
+ /**
+ * Permission types.
+ *
+ * @const
+ * @enum {string}
+ */
+ SharedAccessPermissions: {
+ READ: 'r',
+ ADD: 'a',
+ UPDATE: 'u',
+ PROCESS: 'p'
+ }
+};
+
+module.exports = QueueUtilities;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/internal/edmhandler.js b/src/node_modules/azure-storage/lib/services/table/internal/edmhandler.js
new file mode 100644
index 0000000..0ea9e1d
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/internal/edmhandler.js
@@ -0,0 +1,197 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var _ = require('underscore');
+var util = require('util');
+var guid = require('uuid');
+
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var SR = azureCommon.SR;
+
+var TableUtilities = require('../tableutilities');
+var EdmType = TableUtilities.EdmType;
+
+/**
+* Get the Edm type of an object.
+*
+* @param {object} value A typed instance.
+* @return {string} The Edm type.
+*/
+exports.propertyType = function (value, guessNumberType) {
+ if (_.isNumber(value)) {
+ if (guessNumberType) {
+ if (azureutil.objectIsInt(value)) {
+ return 'Edm.Int32';
+ } else {
+ return 'Edm.Double';
+ }
+ } else {
+ return null;
+ }
+ } else if (_.isBoolean(value)) {
+ return 'Edm.Boolean';
+ } else if (_.isDate(value)) {
+ return 'Edm.DateTime';
+ } else {
+ return 'Edm.String';
+ }
+};
+
+/**
+* Convert a JSON value from over the wire into the correct EDM type.
+*
+* Note that Int64, is remaining a string. Converting it to a Number would lose precision.
+* Int32, Boolean, and Double should already be the correct non-string types
+*
+* @param {string} type The type of the value as it appears in the type attribute.
+* @param value The value in JSON format.
+* @return {object} The unserialized value.
+*/
+exports.deserializeValueFromJson = function (type, value) {
+ if (type) {
+ switch (type) {
+ case EdmType.BINARY:
+ return Buffer.from(value, 'base64');
+ case EdmType.DATETIME:
+ return new Date(value);
+ case EdmType.GUID:
+ return value;
+ case EdmType.DOUBLE:
+ // Account for Infinity and NaN:
+ if (typeof value !== 'number') {
+ return parseFloat(value);
+ }
+ return value;
+ case EdmType.INT32:
+ case EdmType.INT64:
+ case EdmType.STRING:
+ case EdmType.BOOLEAN:
+ return value;
+ default:
+ throw new Error(util.format(SR.TYPE_NOT_SUPPORTED, type));
+ }
+ } else {
+ return value;
+ }
+};
+
+/**
+* Convert a raw EdmType value into the JSON value expected to be sent over the wire.
+*
+* TODO: validate correct input types?
+* Expects Edm.Int64 and Edm.String to be string, Edm.Double and Edm.Int32 to be Number,
+* Edm.Guid to be an array or buffer compatible with Node.uuid, Edm.Binary to be a Node Buffer, Edm.DateTime to be a Date,
+* and Edm.Boolean to be a boolean.
+*
+* @param {string} type The type of the value as it will appear in the type attribute.
+* @param {string} value The value
+* @return {object} The serialized value.
+*/
+exports.serializeValue = function (type, value) {
+ switch (type) {
+ case EdmType.BINARY:
+ if (Buffer.isBuffer(value)) {
+ return value.toString('base64');
+ }
+ return value;
+ case EdmType.DATETIME:
+ if (_.isDate(value)) {
+ return value.toISOString();
+ }
+ return value;
+ case EdmType.GUID:
+ if (Buffer.isBuffer(value) || _.isArray(value)) {
+ return guid.unparse(value);
+ }
+ return value;
+ case EdmType.INT64:
+ case EdmType.DOUBLE:
+ return value.toString();
+ case EdmType.INT32:
+ if (value === Number.POSITIVE_INFINITY) {
+ return 'Infinity';
+ }
+ if (value === Number.NEGATIVE_INFINITY) {
+ return '-Infinity';
+ }
+ if (azureutil.objectIsNaN(value)) {
+ return 'NaN';
+ }
+ return value;
+ case EdmType.STRING:
+ case EdmType.BOOLEAN:
+ return value;
+ default:
+ throw new Error(SR.TYPE_NOT_SUPPORTED + type);
+ }
+};
+
+/*
+* Determines if a type annotation is required for the input type when sending JSON data to the service.
+*/
+exports.isTypeRequired = function(type, value) {
+ switch (type) {
+ case EdmType.BINARY:
+ case EdmType.INT64:
+ case EdmType.DATETIME:
+ case EdmType.GUID:
+ case EdmType.DOUBLE:
+ return true;
+ case EdmType.INT32:
+ if (typeof value !== 'number' || value === Number.POSITIVE_INFINITY || value === Number.NEGATIVE_INFINITY || (azureutil.objectIsNaN(value))) {
+ return true;
+ }
+ return false;
+ case EdmType.STRING:
+ case EdmType.BOOLEAN:
+ return false;
+ default:
+ throw new Error(util.format(SR.TYPE_NOT_SUPPORTED, type));
+ }
+};
+
+/**
+* Serializes value into proper value to be used in odata query value.
+*
+* @param {object} value The value to be serialized.
+* @return {string} The serialized value.
+*/
+exports.serializeQueryValue = function (value, type) {
+ var edmType = type || exports.propertyType(value, true);
+ switch (edmType) {
+ case EdmType.INT32:
+ return value.toString();
+ case EdmType.BOOLEAN:
+ return value ? 'true' : 'false';
+ case EdmType.DOUBLE:
+ return value.toString();
+ case EdmType.INT64:
+ return value.toString() + 'L';
+ case EdmType.DATETIME:
+ if(_.isDate(value)) {
+ var dateTimeString = value.toISOString();
+ return 'datetime\'' + dateTimeString + '\'';
+ }
+ throw new Error(util.format(SR.INVALID_EDM_TYPE, value, type));
+ case EdmType.GUID:
+ return 'guid\'' + value.toString() + '\'';
+ case EdmType.BINARY:
+ return 'X\'' + value.toString('hex') + '\'';
+ default:
+ return '\'' + value.toString().replace(/'/g, '\'\'') + '\'';
+ }
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/internal/odatahandler.js b/src/node_modules/azure-storage/lib/services/table/internal/odatahandler.js
new file mode 100644
index 0000000..0b64db0
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/internal/odatahandler.js
@@ -0,0 +1,217 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var util = require('util');
+
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var SR = azureCommon.SR;
+var Constants = azureCommon.Constants;
+var edmHandler = require('./edmhandler');
+
+var prefixLength = Constants.TableConstants.ODATA_PREFIX.length;
+var suffixLength = Constants.TableConstants.ODATA_TYPE_SUFFIX.length;
+
+exports = module.exports;
+
+/* Serialize an entity to an Odata (Json based) payload
+* Input must be in the following format:
+* { stringValue: { '$': 'Edm.String', '_': 'my string' }, myInt: { '$': 'Edm.Int32', '_': 3 } }
+*/
+exports.serializeJson = function (entity) {
+ function normalizeEntityProperty(property) {
+ if(azureutil.objectIsNull(property)) {
+ return { _: property };
+ }
+
+ if (typeof property === 'object' && property.hasOwnProperty(Constants.TableConstants.ODATA_VALUE_MARKER)) {
+ return property;
+ }
+
+ var result = { _: property };
+ result[Constants.TableConstants.ODATA_TYPE_MARKER] = edmHandler.propertyType(property, true);
+
+ return result;
+ }
+
+ var result = {};
+ for (var propName in entity) {
+ // ignore if .metadata or null or undefined
+ if (propName !== Constants.TableConstants.ODATA_METADATA_MARKER) {
+ var property = normalizeEntityProperty(entity[propName]);
+ if (!azureutil.objectIsNull(property[Constants.TableConstants.ODATA_VALUE_MARKER])) {
+ var value = property[Constants.TableConstants.ODATA_VALUE_MARKER];
+ var type = property[Constants.TableConstants.ODATA_TYPE_MARKER];
+
+ if (type === undefined) {
+ type = edmHandler.propertyType(value, true);
+ }
+
+ result[propName] = edmHandler.serializeValue(type, value);
+ if (edmHandler.isTypeRequired(type, value)) {
+ result[propName + Constants.TableConstants.ODATA_TYPE_SUFFIX] = type;
+ }
+ }
+ }
+ }
+
+ var replacer = function(key, value) {
+ if (value === Number.POSITIVE_INFINITY) {
+ return 'Infinity';
+ }
+ if (value === Number.NEGATIVE_INFINITY) {
+ return '-Infinity';
+ }
+ if (azureutil.objectIsNaN(value)) {
+ return 'NaN';
+ }
+ return value;
+ };
+
+ return JSON.stringify(result, replacer);
+};
+
+/*
+Input: The body of the HTTP response from the server from a table list as JSON (responseObject.response.body).
+
+Return:
+This will return an array in the following format:
+
+[
+ tableName1,
+ tableName2
+]
+
+For example,
+
+[
+ myTable1,
+ myTable2
+]
+
+*/
+exports.parseJsonTables = function (response) {
+ var result = [];
+
+ if (response.value) {
+ for (var i = 0; i < response.value.length; i++) {
+ var entity = response.value[i].TableName;
+ result.push(entity);
+ }
+ }
+
+ return result;
+};
+
+/*
+Input: The body of the HTTP response from the server from a table query as JSON (responseObject.response.body).
+
+Return:
+This will return an array in the following format:
+
+[
+ {{ '$': edmHandler1, '_': value1}, { '$': edmHandler2, '_': value2}, { '$': edmHandler3, '_': value3}},
+ {{ '$': edmHandler4, '_': value4}, { '$': edmHandler5, '_': value5}, { '$': edmHandler6, '_': value6}}
+]
+
+For example,
+
+[
+ {{ '$': Edm.Int32, '_': 42}, { '$': Edm.String, '_': 'sample string'}, { '$': Edm.Boolean, '_': false}},
+ {{ '$': Edm.Int64, '_': 42}, { '$': Edm.String, '_': 'sample string 2'}, { '$': Edm.Boolean, '_': true}}
+]
+
+*/
+exports.parseJsonEntities = function (response, autoResolveProperties, propertyResolver, entityResolver) {
+ if (!response.value) {
+ return [exports.parseJsonSingleEntity(response, autoResolveProperties, propertyResolver, entityResolver)];
+ } else {
+ var result = [];
+
+ for (var i = 0; i < response.value.length; i++) {
+ var rawEntity = response.value[i];
+ var entity = exports.parseJsonSingleEntity(rawEntity, autoResolveProperties, propertyResolver, entityResolver);
+ result.push(entity);
+ }
+
+ return result;
+ }
+};
+
+exports.parseJsonSingleEntity = function(rawEntity, autoResolveProperties, propertyResolver, entityResolver) {
+ var rawEntityProperties = {};
+ var entityPropertyTypes = {PartitionKey: 'Edm.String', RowKey: 'Edm.String', Timestamp: 'Edm.DateTime'};
+ var odataMetadata = {};
+
+ // parse properties
+ for (var entityPropertyName in rawEntity) {
+ if (azureutil.stringStartsWith(entityPropertyName, Constants.TableConstants.ODATA_PREFIX)) {
+ odataMetadata[entityPropertyName.slice(prefixLength)] = rawEntity[entityPropertyName];
+ } else if (azureutil.stringEndsWith(entityPropertyName, Constants.TableConstants.ODATA_TYPE_SUFFIX)) {
+ entityPropertyTypes[entityPropertyName.slice(0, entityPropertyName.length - suffixLength)] = rawEntity[entityPropertyName];
+ } else {
+ rawEntityProperties[entityPropertyName] = rawEntity[entityPropertyName];
+ }
+ }
+
+ // make sure etag is set
+ if (!odataMetadata.etag && rawEntityProperties.Timestamp) {
+ var timestampString = Buffer.from(rawEntityProperties.Timestamp).toString();
+ odataMetadata.etag = 'W/"datetime\'' + timestampString + '\'"';
+ }
+
+ var entity = {};
+ for (var entityPropertyName in rawEntityProperties) {
+ if (rawEntityProperties.hasOwnProperty(entityPropertyName)) {
+ // set the type, if given in the response
+ var entityPropertyType = entityPropertyTypes[entityPropertyName];
+ entity[entityPropertyName] = {};
+
+ // use the given property resolver if present, otherwise infer type if undefined
+ if (propertyResolver) {
+ // partition key, row key, name, value, type if present
+ entityPropertyType = propertyResolver(rawEntityProperties.PartitionKey, rawEntityProperties.RowKey, entityPropertyName, rawEntityProperties[entityPropertyName], entityPropertyType);
+ }
+ if (!entityPropertyType && autoResolveProperties) {
+ entityPropertyType = edmHandler.propertyType(rawEntityProperties[entityPropertyName], false);
+ }
+
+ if (entityPropertyType) {
+ entity[entityPropertyName][Constants.TableConstants.ODATA_TYPE_MARKER] = entityPropertyType;
+ }
+
+ try {
+ entity[entityPropertyName][Constants.TableConstants.ODATA_VALUE_MARKER] = edmHandler.deserializeValueFromJson(entityPropertyType, rawEntityProperties[entityPropertyName]);
+ } catch (err) {
+ if (propertyResolver) {
+ // if a property resolver was used and the type is invalid, throw an appropriate error
+ throw new Error(util.format(SR.INVALID_PROPERTY_RESOLVER, entityPropertyName, entityPropertyType, rawEntityProperties[entityPropertyName]));
+ } else {
+ throw err;
+ }
+ }
+ }
+ }
+
+ entity[Constants.TableConstants.ODATA_METADATA_MARKER] = odataMetadata;
+
+ if (entityResolver) {
+ entity = entityResolver(entity);
+ }
+
+ return entity;
+};
diff --git a/src/node_modules/azure-storage/lib/services/table/internal/requesthandler.js b/src/node_modules/azure-storage/lib/services/table/internal/requesthandler.js
new file mode 100644
index 0000000..1dc416e
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/internal/requesthandler.js
@@ -0,0 +1,135 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var util = require('util');
+var azureCommon = require('./../../../common/common.core');
+var WebResource = azureCommon.WebResource;
+var SR = azureCommon.SR;
+var Constants = azureCommon.Constants;
+var HeaderConstants = Constants.HeaderConstants;
+var TableConstants = Constants.TableConstants;
+var entityResult = require('../models/entityresult');
+
+exports = module.exports;
+
+/**
+* Retrieves the entity path from the table name and an entity descriptor.
+* @ignore
+*
+* @param {string} table The table name.
+* @param {object} entity The entity descriptor.
+* @return {string} The entity path.
+*/
+function getEntityPath (tableName, partitionKey, rowKey) {
+ var path = '/' + tableName;
+
+ if (typeof (partitionKey) === 'string' && typeof (rowKey) === 'string') {
+ // Escape single quotes according to OData Protocol Specification: "single quotes within string literals are represented as two consecutive single quotes".
+ partitionKey = partitionKey.replace(/'/g, '\'\'');
+ rowKey = rowKey.replace(/'/g, '\'\'');
+ path = path + '(PartitionKey=\'' + encodeURIComponent(partitionKey.toString('utf8')) + '\',RowKey=\'' + encodeURIComponent(rowKey.toString('utf8')) + '\')';
+ } else {
+ throw new Error(SR.INCORRECT_ENTITY_KEYS);
+ }
+
+ return path;
+}
+
+/**
+* Constructs the web resource for a table operation.
+*
+* @param {string} operation The operation to perform.
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The create options or callback function.
+* @param {boolean} [options.checkEtag] Boolean value indicating weather the etag should be matched or not.
+* @param {string} [options.echoContent] Whether or not to return the entity upon a successful insert. Default to false.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @return {webResource}
+*/
+exports.constructEntityWebResource = function (operation, table, entityDescriptor, options) {
+ var webResource = null;
+ if (operation === TableConstants.Operations.INSERT) {
+ webResource = WebResource.post(table)
+ .withHeader(HeaderConstants.PREFER, options.echoContent ? HeaderConstants.PREFER_CONTENT : HeaderConstants.PREFER_NO_CONTENT);
+ } else {
+ var partitionKey;
+ var rowKey;
+
+ if (typeof (entityDescriptor.PartitionKey) === 'string') {
+ partitionKey = entityDescriptor.PartitionKey;
+ } else {
+ partitionKey = entityDescriptor.PartitionKey[TableConstants.ODATA_VALUE_MARKER];
+ }
+
+ if (typeof (entityDescriptor.RowKey) === 'string') {
+ rowKey = entityDescriptor.RowKey;
+ } else {
+ rowKey = entityDescriptor.RowKey[TableConstants.ODATA_VALUE_MARKER];
+ }
+
+ var path = getEntityPath(table, partitionKey, rowKey);
+
+ if (operation === TableConstants.Operations.DELETE) {
+ webResource = WebResource.del(path);
+ } else if (operation === TableConstants.Operations.MERGE || operation === TableConstants.Operations.INSERT_OR_MERGE) {
+ webResource = WebResource.merge(path);
+ } else if (operation === TableConstants.Operations.REPLACE || operation === TableConstants.Operations.INSERT_OR_REPLACE) {
+ webResource = WebResource.put(path);
+ } else if (operation === TableConstants.Operations.RETRIEVE) {
+ webResource = WebResource.get(path);
+ } else {
+ throw new Error(util.format(SR.INVALID_TABLE_OPERATION, operation));
+ }
+ }
+
+ if (operation === TableConstants.Operations.DELETE || operation === TableConstants.Operations.REPLACE || operation === TableConstants.Operations.MERGE) {
+ webResource.withHeader(HeaderConstants.IF_MATCH, entityResult.getEtag(entityDescriptor) || '*');
+ }
+
+ var entitySerializedDescriptor;
+ if (!(operation === TableConstants.Operations.DELETE || operation === TableConstants.Operations.RETRIEVE)) {
+ entitySerializedDescriptor = entityResult.serialize(entityDescriptor);
+ }
+
+ exports.setTableRequestHeadersAndBody(webResource, entitySerializedDescriptor, options.payloadFormat);
+
+ return webResource;
+};
+
+/**
+* Sets the table request headers.
+*
+* @param {string} webResource The webResource to add headers to.
+* @param {object} [body] The body of the request.
+*/
+exports.setTableRequestHeadersAndBody = function (webResource, body, acceptType) {
+ if (body) {
+ webResource.withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(body, 'utf8'))
+ .withBody(body)
+ .withHeader(HeaderConstants.CONTENT_TYPE, HeaderConstants.JSON_CONTENT_TYPE_VALUE);
+ }
+
+ webResource.withHeader(HeaderConstants.ACCEPT, acceptType)
+ .withHeader(HeaderConstants.MAX_DATA_SERVICE_VERSION, TableConstants.DEFAULT_DATA_SERVICE_VERSION);
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/internal/sharedkeytable.js b/src/node_modules/azure-storage/lib/services/table/internal/sharedkeytable.js
new file mode 100644
index 0000000..e84dd9e
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/internal/sharedkeytable.js
@@ -0,0 +1,92 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var util = require('util');
+var azureCommon = require('./../../../common/common.core');
+var SharedKey = azureCommon.SharedKey;
+var azureutil = azureCommon.util;
+var Constants = azureCommon.Constants;
+var HeaderConstants = Constants.HeaderConstants;
+var QueryStringConstants = Constants.QueryStringConstants;
+
+/**
+* Creates a new SharedKeyTable object.
+*
+* @constructor
+* @param {string} storageAccount The storage account.
+* @param {string} storageAccessKey The storage account's access key.
+* @param {bool} usePathStyleUri Boolean value indicating if the path, or the hostname, should include the storage account.
+*/
+function SharedKeyTable(storageAccount, storageAccessKey, usePathStyleUri) {
+ SharedKeyTable['super_'].call(this,
+ storageAccount,
+ storageAccessKey,
+ usePathStyleUri);
+}
+
+util.inherits(SharedKeyTable, SharedKey);
+
+/**
+* Signs a request with the Authentication header.
+*
+* @param {WebResource} The webresource to be signed.
+* @param {function(error)} callback The callback function.
+*/
+SharedKeyTable.prototype.signRequest = function (webResource, callback) {
+ var getvalueToAppend = function (value) {
+ if (azureutil.objectIsNull(value)) {
+ return '\n';
+ } else {
+ return value + '\n';
+ }
+ };
+
+ var stringToSign =
+ webResource.method + '\n' +
+ getvalueToAppend(webResource.headers[HeaderConstants.CONTENT_MD5]) +
+ getvalueToAppend(webResource.headers[HeaderConstants.CONTENT_TYPE]) +
+ getvalueToAppend(webResource.headers[HeaderConstants.MS_DATE]) +
+ this._getCanonicalizedResource(webResource);
+
+ var signature = this.signer.sign(stringToSign);
+
+ webResource.withHeader(HeaderConstants.AUTHORIZATION, 'SharedKey ' + this.storageAccount + ':' + signature);
+ callback(null);
+};
+
+/*
+* Retrieves the webresource's canonicalized resource string.
+* @param {WebResource} webResource The webresource to get the canonicalized resource string from.
+* @return {string} The canonicalized resource string.
+*/
+SharedKeyTable.prototype._getCanonicalizedResource = function (webResource) {
+ var path = '/';
+ if (webResource.path) {
+ path = webResource.path;
+ }
+
+ var canonicalizedResource = '/' + this.storageAccount + path;
+
+ var queryStringValues = webResource.queryString;
+ if (queryStringValues[QueryStringConstants.COMP]) {
+ canonicalizedResource += '?comp=' + queryStringValues[QueryStringConstants.COMP];
+ }
+
+ return canonicalizedResource;
+};
+
+module.exports = SharedKeyTable;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/models/batchresult.js b/src/node_modules/azure-storage/lib/services/table/models/batchresult.js
new file mode 100644
index 0000000..88a5491
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/models/batchresult.js
@@ -0,0 +1,237 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../../common/common.core');
+var azureutil = azureCommon.util;
+var Md5Wrapper = require('./../../../common/md5-wrapper');
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var WebResource = azureCommon.WebResource;
+var Constants = azureCommon.Constants;
+var HeaderConstants = Constants.HeaderConstants;
+var TableConstants = Constants.TableConstants;
+
+var RequestHandler = require('../internal/requesthandler');
+var entityResult = require('./entityresult');
+
+/**
+* Creates a new BatchResult.
+*
+* @param {TableService} tableService The table service.
+* @param {string} table The table name.
+* @param {array} operations The array of batch operations.
+* @constructor
+* @ignore
+*/
+function BatchResult(tableService, table, operations) {
+ this.tableService = tableService;
+ this.table = table;
+ this.operations = operations;
+ this.batchBoundary = 'batch_' + BatchResult._getBoundary();
+ this.changesetBoundary = 'changeset_' + BatchResult._getBoundary();
+}
+
+/**
+* Gets a boundary string.
+*
+* @return {string} The boundary string.
+* @ignore
+*/
+BatchResult._getBoundary = function () {
+ return (new Md5Wrapper().createMd5Hash()).update('' + (new Date()).getTime()).digest('hex');
+};
+
+/**
+* Constructs the batch web request.
+*
+* @return {WebResource} The batch WebResource.
+* @ignore
+*/
+BatchResult.prototype.constructWebResource = function () {
+ var webResource = WebResource.post('$batch')
+ .withRawResponse(true);
+
+ webResource.withHeader(HeaderConstants.CONTENT_TYPE, 'multipart/mixed; charset="utf-8"; boundary=' + this.batchBoundary);
+ webResource.withHeader(HeaderConstants.DATA_SERVICE_VERSION, '3.0;');
+ webResource.withHeader(HeaderConstants.MAX_DATA_SERVICE_VERSION, '3.0;NetFx');
+
+ return webResource;
+};
+
+/**
+* Serializes the batch web body.
+*
+* @return {string} The serialized batch content.
+* @ignore
+*/
+BatchResult.prototype.serialize = function () {
+ var body = '--' + this.batchBoundary + '\n';
+
+ if (this.operations.length === 1 && this.operations[0].type === TableConstants.Operations.RETRIEVE) {
+ body += HeaderConstants.CONTENT_TYPE + ': application/http\n';
+ body += HeaderConstants.CONTENT_TRANSFER_ENCODING + ': binary\n\n';
+ body += this._serializeOperation(this.operations[0]);
+ } else {
+ body += HeaderConstants.CONTENT_TYPE + ': multipart/mixed;charset="utf-8";boundary=' + this.changesetBoundary + '\n\n';
+
+ for (var i = 0; i < this.operations.length; i++) {
+ body += '--' + this.changesetBoundary + '\n';
+ body += HeaderConstants.CONTENT_TYPE + ': application/http\n';
+ body += HeaderConstants.CONTENT_TRANSFER_ENCODING + ': binary\n\n';
+ body += this._serializeOperation(this.operations[i], i) + '\n';
+ }
+ body += '--' + this.changesetBoundary + '--\n';
+ }
+ body += '--' + this.batchBoundary + '--';
+
+ return body;
+};
+
+/**
+* Serializes a request within the batch.
+*
+* @param {object} The operation to serialize.
+* @param {number} The index of the operation in the operations arrray.
+* @return {string} The serialized operation content.
+* @ignore
+*/
+BatchResult.prototype._serializeOperation = function (operation, count) {
+ operation.options.payloadFormat = operation.options.payloadFormat || this.tableService.defaultPayloadFormat;
+ var webResource = RequestHandler.constructEntityWebResource(operation.type, this.table, operation.entity, operation.options);
+
+ if (count) {
+ webResource.headers[HeaderConstants.CONTENT_ID] = count;
+ }
+
+ var contentType = webResource.headers[HeaderConstants.CONTENT_TYPE];
+ if (contentType) {
+ if (!azureutil.stringEndsWith(contentType, ';')) {
+ webResource.headers[HeaderConstants.CONTENT_TYPE] += ';';
+ }
+ webResource.headers[HeaderConstants.CONTENT_TYPE] += 'type=entry';
+ }
+
+ this.tableService._setRequestUrl(webResource);
+
+ var content = webResource.method + ' ' + webResource.uri + ' HTTP/1.1\n';
+
+ Object.keys(webResource.headers).forEach(function (header) {
+ content += header + ': ' + webResource.headers[header] + '\n';
+ });
+
+ content += '\n';
+ content += webResource.body || '';
+
+ return content;
+};
+
+/**
+* Parses a batch response.
+*
+* @param {object} responseObject The response object for the batch request.
+* @return {array} An array with the processed / parsed responses.
+*/
+BatchResult.prototype.parse = function (responseObject) {
+ var responses = null;
+ if (responseObject && responseObject.response && responseObject.response.body &&
+ typeof responseObject.response.body === 'string') {
+ responses = [];
+ var rawResponses = responseObject.response.body.split(TableConstants.CHANGESET_DELIMITER);
+
+ if(rawResponses.length === 1) {
+ rawResponses = responseObject.response.body.split(TableConstants.BATCH_DELIMITER);
+ }
+
+ var self = this;
+ rawResponses.forEach(function (rawResponse) {
+ // Find HTTP/1.1 CODE line
+ var httpLocation = rawResponse.indexOf('HTTP/1.1');
+ if (httpLocation !== -1) {
+ rawResponse = rawResponse.substring(httpLocation);
+
+ // valid response
+ var response = self._parseOperation(rawResponse);
+ responses.push(response);
+ }
+ });
+ }
+
+ return responses;
+};
+
+/**
+* Parses a partial response.
+*
+* @param {string} rawResponse The raw, unparsed, http response from the server for the batch response.
+* @return {object} A response object.
+*/
+BatchResult.prototype._parseOperation = function (rawResponse) {
+ var responseObject = {
+ error: null,
+ response: { }
+ };
+
+ // Split into multiple lines and process them
+ var responseLines = rawResponse.split('\r\n');
+
+ if (responseLines.length > 0) {
+ // Retrieve response code
+ var headers = responseLines.shift().split(' ');
+ if (headers.length >= 2) {
+ responseObject.response.statusCode = parseInt(headers[1]);
+ responseObject.response.isSuccessful = WebResource.validResponse(responseObject.response.statusCode);
+ }
+
+ // Populate headers
+ responseObject.response.headers = { };
+ responseObject.response.body = '';
+
+ var isBody = false;
+ responseLines.forEach(function (line) {
+ if (line === '' && !isBody) {
+ isBody = true;
+ } else if (isBody) {
+ responseObject.response.body += line;
+ } else {
+ var headerSplit = line.indexOf(':');
+ if (headerSplit !== -1) {
+ responseObject.response.headers[line.substring(0, headerSplit).trim().toLowerCase()] = line.substring(headerSplit + 1).trim();
+ }
+ }
+ });
+
+ StorageServiceClient._parseResponse(responseObject.response, this.tableService.xml2jsSettings);
+ if (!responseObject.response.isSuccessful) {
+ responseObject.error = StorageServiceClient._normalizeError(responseObject.response.body, responseObject.response);
+ }
+
+ if (!responseObject.error) {
+ var index = responseObject.response.headers[HeaderConstants.CONTENT_ID] || 0;
+ var propertyResolver;
+ var entityResolver;
+ if (index && this.operations[index]) {
+ var options = this.operations[index].options;
+ propertyResolver = options.propertyResolver;
+ entityResolver = options.entityResolver;
+ }
+ responseObject.entity = entityResult.parseEntity(responseObject.response, propertyResolver, entityResolver);
+ }
+ }
+
+ return responseObject;
+};
+
+module.exports = BatchResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/models/entityresult.js b/src/node_modules/azure-storage/lib/services/table/models/entityresult.js
new file mode 100644
index 0000000..f703e1f
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/models/entityresult.js
@@ -0,0 +1,62 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var azureCommon = require('./../../../common/common.core');
+var Constants = azureCommon.Constants;
+var TableConstants = Constants.TableConstants;
+var HeaderConstants = Constants.HeaderConstants;
+var odataHandler = require('../internal/odatahandler');
+
+exports = module.exports;
+
+exports.serialize = function (entity) {
+ return odataHandler.serializeJson(entity);
+};
+
+exports.parseQuery = function (response, autoResolveProperties, propertyResolver, entityResolver) {
+ var result = {};
+ if (response.body) {
+ result = odataHandler.parseJsonEntities(response.body, autoResolveProperties, propertyResolver, entityResolver);
+ }
+
+ return result;
+};
+
+exports.parseEntity = function (response, autoResolveProperties, propertyResolver, entityResolver) {
+ var result = {};
+ if (response.body) {
+ result = odataHandler.parseJsonSingleEntity(response.body, autoResolveProperties, propertyResolver, entityResolver);
+ }
+
+ if (response.headers && response.headers[HeaderConstants.ETAG.toLowerCase()]) {
+ if (!result[TableConstants.ODATA_METADATA_MARKER]) {
+ result[TableConstants.ODATA_METADATA_MARKER] = {};
+ }
+
+ result[TableConstants.ODATA_METADATA_MARKER].etag = response.headers[HeaderConstants.ETAG.toLowerCase()];
+ }
+
+ return result;
+};
+
+exports.getEtag = function (entity) {
+ var etag;
+ if (entity && entity[TableConstants.ODATA_METADATA_MARKER]) {
+ etag = entity[TableConstants.ODATA_METADATA_MARKER].etag;
+ }
+ return etag;
+};
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/models/tableresult.js b/src/node_modules/azure-storage/lib/services/table/models/tableresult.js
new file mode 100644
index 0000000..46adb04
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/models/tableresult.js
@@ -0,0 +1,37 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var odataHandler = require('../internal/odatahandler');
+
+function TableResult(name) {
+ this.name = name;
+}
+
+TableResult.serialize = function (tableName) {
+ return JSON.stringify({ TableName: tableName });
+};
+
+TableResult.parse = function (response) {
+ var result = null;
+ if (response.body) {
+ result = odataHandler.parseJsonTables(response.body);
+ }
+
+ return result;
+};
+
+exports = module.exports = TableResult;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/lib/services/table/tablebatch.js b/src/node_modules/azure-storage/lib/services/table/tablebatch.js
new file mode 100644
index 0000000..64d0861
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/tablebatch.js
@@ -0,0 +1,209 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var extend = require('extend');
+
+var azureCommon = require('./../../common/common.core');
+var SR = azureCommon.SR;
+var validate = azureCommon.validate;
+var Constants = azureCommon.Constants;
+var TableConstants = Constants.TableConstants;
+
+/**
+* Creates a new TableBatch.
+*
+* @constructor
+*/
+function TableBatch() {
+ this.operations = [];
+ this.pk = null;
+ this.retrieve = false;
+}
+
+/**
+* Removes all of the operations from the batch.
+*/
+TableBatch.prototype.clear = function () {
+ this.operations = [];
+};
+
+/**
+* Returns a boolean value indicating weather there are operations in the batch.
+*
+* @return {Boolean} True if there are operations queued up; false otherwise.
+*/
+TableBatch.prototype.hasOperations = function () {
+ return this.operations.length > 0;
+};
+
+/**
+* Returns the number of operations in the batch.
+*
+* @return {number} The number of operations in the batch.
+*/
+TableBatch.prototype.size = function () {
+ return this.operations.length;
+};
+
+/**
+* Adds a retrieve operation to the batch. Note that this must be the only operation in the batch.
+*
+* @param {string} partitionKey The partition key.
+* @param {string} rowKey The row key.
+* @param {object} [options] The request options.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Given the partition key, row key, property name, property value,
+* and the property Edm type if given by the service, returns the Edm type of the property.
+* @param {Function(entity)} [options.entityResolver] The entity resolver. Given the single entity returned by the query, returns a modified object.
+*/
+TableBatch.prototype.retrieveEntity = function (partitionKey, rowKey, options) {
+ var entity = { PartitionKey: {_: partitionKey, $: 'Edm.String'},
+ RowKey: {_: rowKey, $: 'Edm.String'},
+ };
+ this.addOperation(TableConstants.Operations.RETRIEVE, entity, options);
+};
+
+/**
+* Adds an insert operation to the batch.
+*
+* @param {object} entity The entity.
+* @param {object} [options] The request options.
+* @param {string} [options.echoContent] Whether or not to return the entity upon a successful insert. Inserts only, default to false.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Only applied if echoContent is true. Given the partition key, row key, property name,
+* property value, and the property Edm type if given by the service, returns the Edm type of the property.
+* @param {Function(entity)} [options.entityResolver] The entity resolver. Only applied if echoContent is true. Given the single entity returned by the insert, returns
+* a modified object.
+*/
+TableBatch.prototype.insertEntity = function (entity, options) {
+ this.addOperation(TableConstants.Operations.INSERT, entity, options);
+};
+
+/**
+* Adds a delete operation to the batch.
+*
+* @param {object} entity The entity.
+*/
+TableBatch.prototype.deleteEntity = function (entity) {
+ this.addOperation(TableConstants.Operations.DELETE, entity);
+};
+
+/**
+* Adds a merge operation to the batch.
+*
+* @param {object} entity The entity.
+*/
+TableBatch.prototype.mergeEntity = function (entity) {
+ this.addOperation(TableConstants.Operations.MERGE, entity);
+};
+
+/**
+* Adds an replace operation to the batch.
+*
+* @param {object} entity The entity.
+*/
+TableBatch.prototype.replaceEntity = function (entity) {
+ this.addOperation(TableConstants.Operations.REPLACE, entity);
+};
+
+/**
+* Adds an insert or replace operation to the batch.
+*
+* @param {object} entity The entity.
+*/
+TableBatch.prototype.insertOrReplaceEntity = function (entity) {
+ this.addOperation(TableConstants.Operations.INSERT_OR_REPLACE, entity);
+};
+
+/**
+* Adds an insert or merge operation to the batch.
+*
+* @param {object} entity The entity.
+*/
+TableBatch.prototype.insertOrMergeEntity = function (entity) {
+ this.addOperation(TableConstants.Operations.INSERT_OR_MERGE, entity);
+};
+
+/**
+* Adds an operation to the batch after performing checks.
+*
+* @param {string} operationType The type of operation to perform. See Constants.TableConstants.Operations
+* @param {object} entity The entity.
+* @param {object} [options] The request options.
+*/
+TableBatch.prototype.addOperation = function (operationType, entity, options) {
+ validate.validateArgs('addOperation', function (v) {
+ v.object(entity, 'entity');
+ v.object(entity.PartitionKey, 'entity.PartitionKey');
+ v.object(entity.RowKey, 'entity.RowKey');
+ v.stringAllowEmpty(entity.PartitionKey._, 'entity.PartitionKey._');
+ v.stringAllowEmpty(entity.RowKey._, 'entity.RowKey._');
+ });
+
+ if(this.operations.length >= 100) {
+ throw new Error(SR.BATCH_TOO_LARGE);
+ }
+
+ if (operationType === TableConstants.Operations.RETRIEVE) {
+ if(this.hasOperations()) {
+ throw new Error(SR.BATCH_ONE_RETRIEVE);
+ } else {
+ this.retrieve = true;
+ }
+ } else if (this.retrieve) {
+ throw new Error(SR.BATCH_ONE_RETRIEVE);
+ }
+
+ if (!this.hasOperations()) {
+ this.pk = entity.PartitionKey._;
+ } else if (entity.PartitionKey._ !== this.pk) {
+ throw new Error(SR.BATCH_ONE_PARTITION_KEY);
+ }
+
+ var copiedOptions = extend(true, {}, options);
+ this.operations.push({type: operationType, entity: entity, options: copiedOptions});
+};
+
+/**
+* Gets an operation from the batch. Returns null if the index does not exist.
+*
+* @param {number} index The index in the operations array at which to remove an element.
+* @return {object} The removed operation.
+*/
+TableBatch.prototype.getOperation = function (index) {
+ return this.operations[index];
+};
+
+/**
+* Removes an operation from the batch. Returns null if the index does not exist.
+*
+* @param {number} index The index in the operations array at which to remove an element.
+* @return {object} The removed operation.
+*/
+TableBatch.prototype.removeOperation = function (index) {
+ var operation = this.operations.splice(index, 1)[0];
+
+ // if the array is empty, unlock the partition key
+ if (!this.hasOperations()) {
+ this.pk = null;
+ this.retrieve = false;
+ }
+
+ return operation;
+};
+
+module.exports = TableBatch;
diff --git a/src/node_modules/azure-storage/lib/services/table/tablequery.js b/src/node_modules/azure-storage/lib/services/table/tablequery.js
new file mode 100644
index 0000000..f24794e
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/tablequery.js
@@ -0,0 +1,419 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var _ = require('underscore');
+var util = require('util');
+
+var azureCommon = require('./../../common/common.core');
+var azureutil = azureCommon.util;
+var SR = azureCommon.SR;
+var QueryStringConstants = azureCommon.Constants.QueryStringConstants;
+
+var edmHandler = require('./internal/edmhandler');
+var TableUtilities = require('./tableutilities');
+var QueryComparisons = TableUtilities.QueryComparisons;
+var TableOperators = TableUtilities.TableOperators;
+var EdmType = TableUtilities.EdmType;
+
+/**
+ * Creates a new TableQuery object.
+ *
+ * @constructor
+ */
+function TableQuery() {
+ this._fields = [];
+ this._where = [];
+ this._top = null;
+}
+
+/**
+* Specifies the select clause. If no arguments are given, all fields will be selected.
+*
+* @param {array} fields The fields to be selected.
+* @return {TableQuery} A table query object with the select clause.
+* @example
+* var tableQuery = new TableQuery().select('field1', 'field2');
+*/
+TableQuery.prototype.select = function () {
+ var self = this;
+ if (arguments) {
+ _.each(arguments, function (argument) {
+ self._fields.push(argument);
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Specifies the top clause.
+ *
+ * @param {int} top The number of items to fetch.
+ * @return {TableQuery} A table query object with the top clause.
+ * @example
+ * var tableQuery = new TableQuery().top(10);
+ *
+ * // tasktable should already exist and have entities
+ * tableService.queryEntities('tasktable', tableQuery, null \/*currentToken*\/, function(error, result) {
+ * if(!error) {
+ * var entities = result.entities; // there will be 10 or less entities
+ * // do stuff with the returned entities if there are any
+ * // if result.continuationToken exists, to get the next 10 (or less) entities
+ * // call queryEntities as above, but with the returned token instead of null
+ * }
+ * });
+ */
+TableQuery.prototype.top = function (top) {
+ this._top = top;
+ return this;
+};
+
+/**
+ * Specifies the where clause.
+ *
+ * Valid type specifier strings include: ?string?, ?bool?, ?int32?, ?double?, ?date?, ?guid?, ?int64?, ?binary?
+ * A type must be specified for guid, int64, and binaries or the filter produced will be incorrect.
+ *
+ * @param {string} condition The condition string.
+ * @param {string|array} value Value(s) to insert in question mark (?) parameters.
+ * @return {TableQuery} A table query object with the where clause.
+ * @example
+ * var tableQuery = new TableQuery().where(TableQuery.guidFilter('GuidField', QueryComparisons.EQUAL, guidVal));
+ * OR
+ * var tableQuery = new TableQuery().where('Name == ? or Name <= ?', name1, name2);
+ * OR
+ * var tableQuery = new TableQuery().where('Name == ?string? && Value == ?int64?', name1, int64Val);
+ *
+ * // tasktable should already exist and have entities
+ * tableService.queryEntities('tasktable', tableQuery, null \/*currentToken*\/, function(error, result, response) {
+ * if(!error) {
+ * var entities = result.entities;
+ * // do stuff with the returned entities if there are any
+ * }
+ * });
+ */
+TableQuery.prototype.where = function (condition) {
+ this._where.push(TableQuery._encodeConditionString(condition, arguments));
+ return this;
+};
+
+/**
+ * Generates a property filter condition string for an 'int' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|int} value An 'int' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.int32Filter('IntField', QueryComparisons.EQUAL, 5);
+ */
+TableQuery.int32Filter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.INT32);
+};
+
+/**
+ * Generates a property filter condition string for a 'int64' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|int64} value An 'int64' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.int64Filter('Int64Field', QueryComparisons.EQUAL, 123);
+ */
+TableQuery.int64Filter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.INT64);
+};
+
+/**
+ * Generates a property filter condition string for a 'double' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|double}value A 'double' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.doubleFilter('DoubleField', QueryComparisons.EQUAL, 123.45);
+ */
+TableQuery.doubleFilter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.DOUBLE);
+};
+
+/**
+ * Generates a property filter condition string for a 'boolean' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|boolean} value A 'boolean' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.booleanFilter('BooleanField', QueryComparisons.EQUAL, false);
+ */
+TableQuery.booleanFilter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.BOOLEAN);
+};
+
+/**
+ * Generates a property filter condition string for a 'datetime' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|date} value A 'datetime' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.dateFilter('DateTimeField', QueryComparisons.EQUAL, new Date(Date.UTC(2001, 1, 3, 4, 5, 6)));
+ */
+TableQuery.dateFilter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.DATETIME);
+};
+
+/**
+ * Generates a property filter condition string for a 'guid' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|guid} value A 'guid' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.guidFilter('GuidField', QueryComparisons.EQUAL, guid.v1());
+ */
+TableQuery.guidFilter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.GUID);
+};
+
+/**
+ * Generates a property filter condition string for a 'binary' value.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string|buffer}value A 'buffer' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.binaryFilter('BinaryField', QueryComparisons.EQUAL, Buffer.from('hello'));
+ */
+TableQuery.binaryFilter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.BINARY);
+};
+
+/**
+ * Generates a property filter condition string.
+ *
+ * @param {string} propertyName A string containing the name of the property to compare.
+ * @param {string} operation A string containing the comparison operator to use.
+ * See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+ * @param {string} value A 'string' containing the value to compare with the property.
+ * @return {string} A string containing the formatted filter condition.
+ * @example
+ * var query = TableQuery.stringFilter('StringField', QueryComparisons.EQUAL, 'name');
+ */
+TableQuery.stringFilter = function (propertyName, operation, value) {
+ return TableQuery._concatFilterString(propertyName, operation, value, EdmType.STRING);
+};
+
+/**
+ * Creates a filter condition using the specified logical operator on two filter conditions.
+ *
+ * @param {string} filterA A string containing the first formatted filter condition.
+ * @param {string} operatorString A string containing the operator to use (AND, OR).
+ * @param {string} filterB A string containing the second formatted filter condition.
+ * @return {string} A string containing the combined filter expression.
+ * @example
+ * var filter1 = TableQuery.stringFilter('Name', QueryComparisons.EQUAL, 'Person');
+ * var filter2 = TableQuery.booleanFilter('Visible', QueryComparisons.EQUAL, true);
+ * var combinedFilter = TableQuery.combineFilters(filter1, TableUtilities.TableOperators.AND, filter2);
+ */
+TableQuery.combineFilters = function (filterA, operatorString, filterB) {
+ return filterA + ' ' + operatorString + ' ' + filterB;
+};
+
+/**
+ * Specifies an AND where condition.
+ *
+ * @param {string} condition The condition string.
+ * @param {array} arguments Any number of arguments to be replaced in the condition by the question mark (?).
+ * @return {TableQuery} A table query object with the and clause.
+ * @example
+ * var tableQuery = new TableQuery()
+ * .where('Name == ? or Name <= ?', 'Person1', 'Person2');
+ * .and('Age >= ?', 18);
+ */
+TableQuery.prototype.and = function (condition) {
+ if (this._where.length === 0) {
+ throw new Error(util.format(SR.QUERY_OPERATOR_REQUIRES_WHERE, 'AND'));
+ }
+
+ this._where.push(' and ' + TableQuery._encodeConditionString(condition, arguments));
+ return this;
+};
+
+/**
+ * Specifies an OR where condition.
+ *
+ * @param {string} condition The condition.
+ * @param {array} arguments Any number of arguments to be replaced in the condition by the question mark (?).
+ * @return {TableQuery} A table query object with the or clause.
+ * @example
+ * var tableQuery = new TableQuery()
+ * .where('Name == ? or Name <= ?', 'Person1', 'Person2');
+ * .or('Age >= ?', 18);
+ */
+TableQuery.prototype.or = function (condition) {
+ if (this._where.length === 0) {
+ throw new Error(util.format(SR.QUERY_OPERATOR_REQUIRES_WHERE, 'OR'));
+ }
+
+ this._where.push(' or ' + TableQuery._encodeConditionString(condition, arguments));
+ return this;
+};
+
+/**
+ * Returns the query string object for the query.
+ *
+ * @return {object} JSON object representing the query string arguments for the query.
+ */
+TableQuery.prototype.toQueryObject = function () {
+ var query = {};
+ if (this._fields.length > 0) {
+ query[QueryStringConstants.SELECT] = this._fields.join(',');
+ }
+
+ if (this._where.length > 0) {
+ query[QueryStringConstants.FILTER] = this._where.join('');
+ }
+
+ if (this._top) {
+ query[QueryStringConstants.TOP] = this._top;
+ }
+
+ return query;
+};
+
+// Functions
+
+/**
+* Concat the filter string parameters.
+*
+* @param {string} propertyName A string containing the name of the property to compare.
+* @param {string} operation A string containing the comparison operator to use.
+* See Constants.TableConstants.QueryComparisons for a list of allowed operations.
+* @param {object} value The value to compare with the property.
+* @param {string} type A string EdmType of the property to compare.
+* @return {string} A string containing the formatted filter condition.
+* @ignore
+*/
+TableQuery._concatFilterString = function (propertyName, operation, value, type) {
+ if (azureutil.objectIsNull(propertyName)) {
+ throw new Error(util.format(SR.ARGUMENT_NULL_OR_UNDEFINED, 'propertyName'));
+ }
+
+ if (azureutil.objectIsNull(operation)) {
+ throw new Error(util.format(SR.ARGUMENT_NULL_OR_UNDEFINED, 'operation'));
+ }
+
+ if (azureutil.objectIsNull(value)) {
+ throw new Error(util.format(SR.ARGUMENT_NULL_OR_UNDEFINED, 'value'));
+ }
+
+ var serializedValue = edmHandler.serializeQueryValue(value, type);
+ return propertyName + ' ' + operation + ' ' + serializedValue;
+};
+
+/**
+ * Encodes a condition string.
+ *
+ * @param {string} condition The condition.
+ * @param {array} arguments Any number of arguments to be replaced in the condition by the question mark (?).
+ * @return {TableQuery} A table query object with the or clause
+ * @ignore
+ */
+TableQuery._encodeConditionString = function (condition, args) {
+ var encodedCondition = TableQuery._replaceOperators(condition);
+ if (args.length > 1) {
+ var sections = encodedCondition.split(/(\?string\?|\?int32\?|\?int64\?|\?bool\?|\?double\?|\?date\?|\?binary\?|\?guid\?|\?)/);
+ var count = 1;
+ for (var i = 0; i < sections.length && count < args.length; i++) {
+ if (sections[i].indexOf('?') === 0) {
+ var type = TableQuery._getEdmType(sections[i]);
+ sections[i] = edmHandler.serializeQueryValue(args[count], type);
+ count++;
+ }
+ }
+ encodedCondition = sections.join('');
+ }
+
+ return encodedCondition;
+};
+
+/**
+ * Converts the query string type to an Edm type.
+ *
+ * @param {string} type The type included in the query string.
+ * @return {string} The EdmType.
+ * @ignore
+ */
+TableQuery._getEdmType = function (type) {
+ switch (type) {
+ case '?binary?':
+ return EdmType.BINARY;
+ case '?int64?':
+ return EdmType.INT64;
+ case '?date?':
+ return EdmType.DATETIME;
+ case '?guid?':
+ return EdmType.GUID;
+ case '?int32?':
+ return EdmType.INT32;
+ case '?double?':
+ return EdmType.DOUBLE;
+ case '?bool?':
+ return EdmType.BOOLEAN;
+ case '?string?':
+ return EdmType.STRING;
+ default:
+ return undefined;
+ }
+};
+
+/**
+ * Replace operators.
+ * @ignore
+ * @param {string} whereClause The text where to replace the operators.
+ * @return {string} The string with the replaced operators.
+ * @ignore
+ */
+TableQuery._replaceOperators = function (whereClause) {
+ var encodedWhereClause = whereClause.replace(/ == /g, ' ' + QueryComparisons.EQUAL + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ != /g, ' ' + QueryComparisons.NOT_EQUAL + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ >= /g, ' ' + QueryComparisons.GREATER_THAN_OR_EQUAL + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ > /g, ' ' + QueryComparisons.GREATER_THAN + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ <= /g, ' ' + QueryComparisons.LESS_THAN_OR_EQUAL + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ < /g, ' ' + QueryComparisons.LESS_THAN + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ \&\& /g, ' ' + TableOperators.AND + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/ \|\| /g, ' ' + TableOperators.OR + ' ');
+ encodedWhereClause = encodedWhereClause.replace(/!/g, TableOperators.NOT);
+
+ return encodedWhereClause;
+};
+
+module.exports = TableQuery;
diff --git a/src/node_modules/azure-storage/lib/services/table/tableservice.js b/src/node_modules/azure-storage/lib/services/table/tableservice.js
new file mode 100644
index 0000000..08e9c08
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/tableservice.js
@@ -0,0 +1,1393 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Module dependencies.
+var util = require('util');
+var extend = require('extend');
+var _ = require('underscore');
+
+var azureCommon = require('./../../common/common.core');
+var azureutil = azureCommon.util;
+var validate = azureCommon.validate;
+var SR = azureCommon.SR;
+var StorageServiceClient = azureCommon.StorageServiceClient;
+var SharedKeyTable = require('./internal/sharedkeytable');
+var RequestHandler = require('./internal/requesthandler');
+var TableQuery = require('./tablequery');
+var WebResource = azureCommon.WebResource;
+var Constants = azureCommon.Constants;
+var QueryStringConstants = Constants.QueryStringConstants;
+var HeaderConstants = Constants.HeaderConstants;
+var TableConstants = Constants.TableConstants;
+var RequestLocationMode = Constants.RequestLocationMode;
+
+// Models requires
+var TableResult = require('./models/tableresult');
+var entityResult = require('./models/entityresult');
+var BatchResult = require('./models/batchresult');
+var ServiceStatsParser = azureCommon.ServiceStatsParser;
+var AclResult = azureCommon.AclResult;
+var TableUtilities = require('./tableutilities');
+
+/**
+* Creates a new TableService object.
+* If no connection string or storageaccount and storageaccesskey are provided,
+* the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
+* @class
+* The TableService object allows you to peform management operations with the Microsoft Azure Table Service.
+* The Table Service stores data in rows of key-value pairs. A table is composed of multiple rows, and each row
+* contains key-value pairs. There is no schema, so each row in a table may store a different set of keys.
+*
+* For more information on the Table Service, as well as task focused information on using it from a Node.js application, see
+* [How to Use the Table Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-table-storage/).
+* The following defaults can be set on the Table service.
+* defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Table service.
+* defaultClientRequestTimeoutInMs The default timeout of client requests, in milliseconds, to use for the request made via the Table service.
+* defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Table service.
+* defaultLocationMode The default location mode for requests made via the Table service.
+* defaultPayloadFormat The default payload format for requests made via the Table service.
+* useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Table service.; true to use the
+* Nagle algorithm; otherwise, false. The default value is false.
+* enableGlobalHttpAgent Determines whether global HTTP(s) agent is enabled; true to use Global HTTP(s) agent; otherwise, false to use
+* http(s).Agent({keepAlive:true}).
+* @constructor
+* @extends {StorageServiceClient}
+*
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string|object} [host] The host address. To define primary only, pass a string.
+* Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+* @param {string} [sasToken] The Shared Access Signature token.
+* @param {string} [endpointSuffix] The endpoint suffix.
+*/
+function TableService(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) {
+ var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix);
+
+ TableService['super_'].call(this,
+ storageServiceSettings._name,
+ storageServiceSettings._key,
+ storageServiceSettings._tableEndpoint,
+ storageServiceSettings._usePathStyleUri,
+ storageServiceSettings._sasToken);
+
+ if (this.anonymous) {
+ throw new Error(SR.ANONYMOUS_ACCESS_BLOBSERVICE_ONLY);
+ }
+
+ if(this.storageAccount && this.storageAccessKey) {
+ this.storageCredentials = new SharedKeyTable(this.storageAccount, this.storageAccessKey, this.usePathStyleUri);
+ }
+
+ this.defaultPayloadFormat = TableUtilities.PayloadFormat.MINIMAL_METADATA;
+}
+
+util.inherits(TableService, StorageServiceClient);
+
+// Table service methods
+
+/**
+* Gets the service stats for a storage account’s Table service.
+*
+* @this {TableService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link ServiceStats}` will contain the stats.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.getServiceStats = function (optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getServiceStats', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var webResource = WebResource.get()
+ .withQueryOption(QueryStringConstants.COMP, 'stats')
+ .withQueryOption(QueryStringConstants.RESTYPE, 'service');
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.serviceStatsResult = null;
+ if (!responseObject.error) {
+ responseObject.serviceStatsResult = ServiceStatsParser.parse(responseObject.response.body.StorageServiceStats);
+ }
+
+ // function to be called after all filters
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.serviceStatsResult, returnObject.response);
+ };
+
+ // call the first filter
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Gets the properties of a storage account’s Table service, including Azure Storage Analytics.
+*
+* @this {TableService}
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `[result]{@link ServiceProperties}` will contain the properties.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.getServiceProperties = function (optionsOrCallback, callback) {
+ return this.getAccountServiceProperties(optionsOrCallback, callback);
+};
+
+/**
+* Sets the properties of a storage account’s Table service, including Azure Storage Analytics.
+* You can also use this operation to set the default request version for all incoming requests that do not have a version specified.
+*
+* @this {TableService}
+* @param {object} serviceProperties The service properties.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information if an error occurs;
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) {
+ return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of table items under the specified account.
+*
+* @this {TableService}
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The create options or callback function.
+* @param {int} [options.maxResults] Specifies the maximum number of tables to return per call to Azure ServiceClient.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of tables and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.listTablesSegmented = function (currentToken, optionsOrCallback, callback) {
+ this.listTablesSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback);
+};
+
+/**
+* Lists a segment containing a collection of table items under the specified account.
+*
+* @this {TableService}
+* @param {string} prefix The prefix of the table name.
+* @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The create options or callback function.
+* @param {int} [options.maxResults] Specifies the maximum number of tables to return per call to Azure ServiceClient.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain `entries` and `continuationToken`.
+* `entries` gives a list of tables and the `continuationToken` is used for the next listing operation.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.listTablesSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('listTables', function (v) {
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.payloadFormat = options.payloadFormat || this.defaultPayloadFormat;
+
+ var webResource = WebResource.get(TableConstants.TABLE_SERVICE_TABLE_NAME);
+ RequestHandler.setTableRequestHeadersAndBody(webResource, null, options.payloadFormat);
+
+ if(!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(TableConstants.NEXT_TABLE_NAME, currentToken.nextTableName);
+ }
+
+ if(!azureutil.objectIsNull(prefix)) {
+ var query = new TableQuery()
+ .where(TableConstants.TABLE_NAME + ' >= ?', prefix)
+ .and(TableConstants.TABLE_NAME + ' < ?', prefix + '{');
+
+ webResource.withQueryOption(QueryStringConstants.FILTER, query.toQueryObject().$filter);
+ }
+
+ if(!azureutil.objectIsNull(options.maxResults)) {
+ var query = new TableQuery().top(options.maxResults);
+ webResource.withQueryOption(QueryStringConstants.TOP, query.toQueryObject().$top);
+ }
+
+ options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.listTablesResult = null;
+
+ if (!responseObject.error) {
+ responseObject.listTablesResult = {
+ entries: null,
+ continuationToken: null
+ };
+ responseObject.listTablesResult.entries = TableResult.parse(responseObject.response);
+
+ if (responseObject.response.headers[TableConstants.CONTINUATION_NEXT_TABLE_NAME] &&
+ !azureutil.objectIsEmpty(responseObject.response.headers[TableConstants.CONTINUATION_NEXT_TABLE_NAME])) {
+ responseObject.listTablesResult.continuationToken = {
+ nextTableName: null,
+ targetLocation: null
+ };
+
+ responseObject.listTablesResult.continuationToken.nextTableName = responseObject.response.headers[TableConstants.CONTINUATION_NEXT_TABLE_NAME];
+ responseObject.listTablesResult.continuationToken.targetLocation = responseObject.targetLocation;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.listTablesResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+// Table Methods
+
+/**
+* Gets the table's ACL.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the ACL information for the table. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.getTableAcl = function (table, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('getTableAcl', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY;
+
+ var webResource = WebResource.get(table)
+ .withQueryOption(QueryStringConstants.COMP, 'acl');
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.tableResult = null;
+ if (!responseObject.error) {
+ responseObject.tableResult = new TableResult(table);
+ responseObject.tableResult.signedIdentifiers = AclResult.parse(responseObject.response.body);
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.tableResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Updates the table's ACL.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {Object.} signedIdentifiers The table ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain information for the table.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.setTableAcl = function (table, signedIdentifiers, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('setTableAcl', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var policies = null;
+ if (signedIdentifiers) {
+ if(_.isArray(signedIdentifiers)) {
+ throw new TypeError(SR.INVALID_SIGNED_IDENTIFIERS);
+ }
+ policies = AclResult.serialize(signedIdentifiers);
+ }
+
+ var webResource = WebResource.put(table)
+ .withQueryOption(QueryStringConstants.COMP, 'acl')
+ .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0)
+ .withBody(policies);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.tableResult = null;
+ if (!responseObject.error) {
+
+ // SetTableAcl doesn't actually return anything in the response
+ responseObject.tableResult = new TableResult(table);
+ if (signedIdentifiers) {
+ responseObject.tableResult.signedIdentifiers = signedIdentifiers;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.tableResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Retrieves a shared access signature token.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} sharedAccessPolicy The shared access policy.
+* @param {string} [sharedAccessPolicy.Id] The signed identifier.
+* @param {object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used).
+* @param {date|string} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired (The UTC value will be used).
+* @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive.
+* @param {string} [sharedAccessPolicy.AccessPolicy.Protocols] The protocols permitted for a request made with the account SAS.
+* Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http.
+* @param {string} [sharedAccessPolicy.AccessPolicy.StartPk] The starting Partition Key for which the SAS will be valid.
+* @param {string} [sharedAccessPolicy.AccessPolicy.EndPk] The ending Partition Key for which the SAS will be valid.
+* @param {string} [sharedAccessPolicy.AccessPolicy.StartRk] The starting Row Key for which the SAS will be valid.
+* @param {string} [sharedAccessPolicy.AccessPolicy.EndRk] The ending Row Key for which the SAS will be valid.
+* @return {object} An object with the shared access signature.
+*/
+TableService.prototype.generateSharedAccessSignature = function (table, sharedAccessPolicy) {
+ // check if the TableService is able to generate a shared access signature
+ if (!this.storageCredentials || !this.storageCredentials.generateSignedQueryString) {
+ throw new Error(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
+ }
+
+ validate.validateArgs('generateSharedAccessSignature', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.object(sharedAccessPolicy, 'sharedAccessPolicy');
+ });
+
+ var lowerCasedTableName = table.toLowerCase();
+ return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.Table, lowerCasedTableName, sharedAccessPolicy, null, { tableName: lowerCasedTableName });
+};
+
+/**
+* Checks whether or not a table exists on the service.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the table information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.doesTableExist = function (table, optionsOrCallback, callback) {
+ this._doesTableExist(table, false, optionsOrCallback, callback);
+};
+
+/**
+* Creates a new table within a storage account.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the new table information.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.createTable = function (table, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createTable', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var tableDescriptor = TableResult.serialize(table);
+
+ var webResource = WebResource.post('Tables')
+ .withHeader(HeaderConstants.PREFER, HeaderConstants.PREFER_NO_CONTENT);
+
+ RequestHandler.setTableRequestHeadersAndBody(webResource, tableDescriptor, this.defaultPayloadFormat);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.tableResponse = {};
+ responseObject.tableResponse.isSuccessful = responseObject.error ? false : true;
+ responseObject.tableResponse.statusCode = responseObject.response === null || responseObject.response === undefined ? undefined : responseObject.response.statusCode;
+ if (!responseObject.error) {
+ responseObject.tableResponse.TableName = table;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.tableResponse, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Creates a new table within a storage account if it does not exists.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* `result` will contain the table information including `created` boolean member
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var tableService = azure.createTableService();
+* tableService.createTableIfNotExists('tasktable', function(error) {
+* if(!error) {
+* // Table created or exists
+* }
+* });
+*/
+TableService.prototype.createTableIfNotExists = function (table, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('createTableIfNotExists', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var self = this;
+ self._doesTableExist(table, true, options, function(error, result, response) {
+ var exists = result.exists;
+ result.created = false;
+ delete result.exists;
+
+ if (error) {
+ callback(error, result, response);
+ } else if (exists) {
+ response.isSuccessful = true;
+ callback(error, result, response);
+ } else {
+ self.createTable(table, options, function(createError, createResult, response) {
+ if (!createError) {
+ createResult.created = true;
+ }
+ else if (createError && createError.statusCode === Constants.HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.TableErrorCodeStrings.TABLE_ALREADY_EXISTS) {
+ createError = null;
+ createResult.created = false;
+ createResult.isSuccessful = true;
+ }
+ callback(createError, createResult, response);
+ });
+ }
+ });
+};
+
+/**
+* Deletes a table from a storage account.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information if an error occurs;
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.deleteTable = function (table, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteTable', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var webResource = WebResource.del('Tables(\'' + table + '\')');
+ RequestHandler.setTableRequestHeadersAndBody(webResource, null, this.defaultPayloadFormat);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Deletes a table from a storage account, if it exists.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* `result` will be `true` if table was deleted, false otherwise
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.deleteTableIfExists = function (table, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('deleteTableIfExists', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ var self = this;
+ self._doesTableExist(table, true, options, function(error, result, response) {
+ if (error) {
+ callback(error, result.exists, response);
+ } else if (!result.exists) {
+ response.isSuccessful = true;
+ callback(error, false, response);
+ } else {
+ self.deleteTable(table, options, function(deleteError, deleteResponse) {
+ var deleted;
+ if (!deleteError) {
+ deleted = true;
+ } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.StorageErrorCodeStrings.RESOURCE_NOT_FOUND) {
+ deleted = false;
+ deleteError = null;
+ deleteResponse.isSuccessful = true;
+ }
+
+ callback(deleteError, deleted, deleteResponse);
+ });
+ }
+ });
+};
+
+// Table Entity Methods
+
+/**
+* Queries data in a table. To retrieve a single entity by partition key and row key, use retrieve entity.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {TableQuery} tableQuery The query to perform. Use null, undefined, or new TableQuery() to get all of the entities in the table.
+* @param {object} currentToken A continuation token returned by a previous listing operation.
+* Please use 'null' or 'undefined' if this is the first operation.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {bool} [options.autoResolveProperties] If true, guess at all property types.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(entity)} [options.entityResolver] The entity resolver. Given a single entity returned by the query, returns a modified object which is added to
+* the entities array.
+* @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Given the partition key, row key, property name, property value,
+* and the property Edm type if given by the service, returns the Edm type of the property.
+* @param {TableService~queryResponse} callback `error` will contain information if an error occurs;
+* otherwise `entries` will contain the entities returned by the query.
+* If more matching entities exist, and could not be returned,
+* `queryResultContinuation` will contain a continuation token that can be used
+* to retrieve the next set of results.
+* `response` will contain information related to this operation.
+*
+* The logic for returning entity types can get complicated. Here is the algorithm used:
+* ```
+* var propertyType;
+*
+* if (propertyResovler) { // If the caller provides a propertyResolver in the options, use it
+* propertyType = propertyResolver(partitionKey, rowKey, propertyName, propertyValue, propertyTypeFromService);
+* } else if (propertyTypeFromService) { // If the service provides us a property type, use it. See below for an explanation of when this will and won't occur.
+* propertyType = propertyTypeFromService;
+* } else if (autoResolveProperties) { // If options.autoResolveProperties is set to true
+* if (javascript type is string) { // See below for an explanation of how and why autoResolveProperties works as it does.
+* propertyType = 'Edm.String';
+* } else if (javascript type is boolean) {
+* propertyType = 'Edm.Boolean';
+* }
+* }
+*
+* if (propertyType) {
+* // Set the property type on the property.
+* } else {
+* // Property gets no EdmType.
+* }
+* ```
+* Notes:
+*
+* * The service only provides a type if JsonFullMetadata or JsonMinimalMetadata is used, and if the type is Int64, Guid, Binary, or DateTime.
+* * Explanation of autoResolveProperties:
+* * String gets correctly resolved to 'Edm.String'.
+* * Int64, Guid, Binary, and DateTime all get resolved to 'Edm.String.' This only happens if JsonNoMetadata is used (otherwise the service will provide the propertyType in a prior step).
+* * Boolean gets correctly resolved to 'Edm.Boolean'.
+* * For both Int32 and Double, no type information is returned, even in the case of autoResolveProperties = true. This is due to an
+* inability to distinguish between the two in certain cases.
+*
+* @example
+* var azure = require('azure-storage');
+* var tableService = azure.createTableService();
+* // tasktable should already exist and have entities
+*
+* // returns all entities in tasktable, and a continuation token for the next page of results if necessary
+* tableService.queryEntities('tasktable', null, null \/*currentToken*\/, function(error, result) {
+* if(!error) {
+* var entities = result.entries;
+* // do stuff with the returned entities if there are any
+* }
+* });
+*
+* // returns field1 and field2 of the entities in tasktable, and a continuation token for the next page of results if necessary
+* var tableQuery = new TableQuery().select('field1', 'field2');
+* tableService.queryEntities('tasktable', tableQuery, null \/*currentToken*\/, function(error, result) {
+* if(!error) {
+* var entities = result.entries;
+* // do stuff with the returned entities if there are any
+* }
+* });
+*/
+TableService.prototype.queryEntities = function (table, tableQuery, currentToken, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('queryEntities', function (v) {
+ v.string(table, 'table');
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.payloadFormat = options.payloadFormat || this.defaultPayloadFormat;
+
+ var webResource = WebResource.get(table);
+ RequestHandler.setTableRequestHeadersAndBody(webResource, null, options.payloadFormat);
+
+ if (tableQuery) {
+ var queryString = tableQuery.toQueryObject();
+ Object.keys(queryString).forEach(function (queryStringName) {
+ webResource.withQueryOption(queryStringName, queryString[queryStringName]);
+ });
+ }
+
+ if(!azureutil.objectIsNull(currentToken)) {
+ webResource.withQueryOption(TableConstants.NEXT_PARTITION_KEY, currentToken.nextPartitionKey);
+ webResource.withQueryOption(TableConstants.NEXT_ROW_KEY, currentToken.nextRowKey);
+ }
+
+ options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.queryEntitiesResult = null;
+ if (!responseObject.error) {
+ responseObject.queryEntitiesResult = {
+ entries: null,
+ continuationToken: null
+ };
+
+ // entries
+ responseObject.queryEntitiesResult.entries = entityResult.parseQuery(responseObject.response, options.autoResolveProperties, options.propertyResolver, options.entityResolver);
+
+ // continuation token
+ var continuationToken = {
+ nextPartitionKey: responseObject.response.headers[TableConstants.CONTINUATION_NEXT_PARTITION_KEY],
+ nextRowKey: responseObject.response.headers[TableConstants.CONTINUATION_NEXT_ROW_KEY],
+ targetLocation: responseObject.targetLocation
+ };
+
+ if (!azureutil.IsNullOrEmptyOrUndefinedOrWhiteSpace(continuationToken.nextPartitionKey)) {
+ responseObject.queryEntitiesResult.continuationToken = continuationToken;
+ }
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.queryEntitiesResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Retrieves an entity from a table.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {string} partitionKey The partition key.
+* @param {string} rowKey The row key.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {bool} [options.autoResolveProperties] If true, guess at all property types.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Given the partition key, row key, property name, property value,
+* and the property Edm type if given by the service, returns the Edm type of the property.
+* @param {Function(entity)} [options.entityResolver] The entity resolver. Given the single entity returned by the query, returns a modified object.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will be the matching entity.
+* `response` will contain information related to this operation.
+*
+* The logic for returning entity types can get complicated. Here is the algorithm used:
+* ```
+* var propertyType;
+*
+* if (propertyResovler) { // If the caller provides a propertyResolver in the options, use it
+* propertyType = propertyResolver(partitionKey, rowKey, propertyName, propertyValue, propertyTypeFromService);
+* } else if (propertyTypeFromService) { // If the service provides us a property type, use it. See below for an explanation of when this will and won't occur.
+* propertyType = propertyTypeFromService;
+* } else if (autoResolveProperties) { // If options.autoResolveProperties is set to true
+* if (javascript type is string) { // See below for an explanation of how and why autoResolveProperties works as it does.
+* propertyType = 'Edm.String';
+* } else if (javascript type is boolean) {
+* propertyType = 'Edm.Boolean';
+* }
+* }
+*
+* if (propertyType) {
+* // Set the property type on the property.
+* } else {
+* // Property gets no EdmType.
+* }
+* ```
+* Notes:
+*
+* * The service only provides a type if JsonFullMetadata or JsonMinimalMetadata is used, and if the type is Int64, Guid, Binary, or DateTime.
+* * Explanation of autoResolveProperties:
+* * String gets correctly resolved to 'Edm.String'.
+* * Int64, Guid, Binary, and DateTime all get resolved to 'Edm.String.' This only happens if JsonNoMetadata is used (otherwise the service will provide the propertyType in a prior step).
+* * Boolean gets correctly resolved to 'Edm.Boolean'.
+* * For both Int32 and Double, no type information is returned, even in the case of autoResolveProperties = true. This is due to an
+* inability to distinguish between the two in certain cases.
+*
+* @example
+* var azure = require('azure-storage');
+* var tableService = azure.createTableService();
+* tableService.retrieveEntity('tasktable', 'tasksSeattle', '1', function(error, serverEntity) {
+* if(!error) {
+* // Entity available in serverEntity variable
+* }
+* });
+*/
+TableService.prototype.retrieveEntity = function (table, partitionKey, rowKey, optionsOrCallback, callback) {
+ var entityDescriptor = { PartitionKey: {_: partitionKey, $: 'Edm.String'},
+ RowKey: {_: rowKey, $: 'Edm.String'},
+ };
+
+ validate.validateArgs('retrieveEntity', function (v) {
+ v.stringAllowEmpty(partitionKey, 'partitionKey');
+ v.stringAllowEmpty(rowKey, 'rowKey');
+ });
+
+ this._performEntityOperation(TableConstants.Operations.RETRIEVE, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Inserts a new entity into a table.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The request options.
+* @param {string} [options.echoContent] Whether or not to return the entity upon a successful insert. Default to false.
+* @param {string} [options.payloadFormat] The payload format to use in the response, if options.echoContent is true.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Only applied if echoContent is true. Given the partition key, row key, property name,
+* property value, and the property Edm type if given by the service, returns the Edm type of the property.
+* @param {Function(entity)} [options.entityResolver] The entity resolver. Only applied if echoContent is true. Given the single entity returned by the insert, returns
+* a modified object.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the entity information.
+* `response` will contain information related to this operation.
+*
+* @example
+* var azure = require('azure-storage');
+* var tableService = azure.createTableService();
+* var task1 = {
+* PartitionKey : {'_': 'tasksSeattle', '$':'Edm.String'},
+* RowKey: {'_': '1', '$':'Edm.String'},
+* Description: {'_': 'Take out the trash', '$':'Edm.String'},
+* DueDate: {'_': new Date(2011, 12, 14, 12), '$':'Edm.DateTime'}
+* };
+* tableService.insertEntity('tasktable', task1, function(error) {
+* if(!error) {
+* // Entity inserted
+* }
+* });
+*/
+TableService.prototype.insertEntity = function (table, entityDescriptor, optionsOrCallback, callback) {
+ this._performEntityOperation(TableConstants.Operations.INSERT, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Inserts or updates a new entity into a table.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the entity information.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.insertOrReplaceEntity = function (table, entityDescriptor, optionsOrCallback, callback) {
+ this._performEntityOperation(TableConstants.Operations.INSERT_OR_REPLACE, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Replaces an existing entity within a table. To replace conditionally based on etag, set entity['.metadata']['etag'].
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the entity information.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.replaceEntity = function (table, entityDescriptor, optionsOrCallback, callback) {
+ this._performEntityOperation(TableConstants.Operations.REPLACE, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Updates an existing entity within a table by merging new property values into the entity. To merge conditionally based on etag, set entity['.metadata']['etag'].
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the entity information.
+* response` will contain information related to this operation.
+*/
+TableService.prototype.mergeEntity = function (table, entityDescriptor, optionsOrCallback, callback) {
+ this._performEntityOperation(TableConstants.Operations.MERGE, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Inserts or updates an existing entity within a table by merging new property values into the entity.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain the entity information.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.insertOrMergeEntity = function (table, entityDescriptor, optionsOrCallback, callback) {
+ this._performEntityOperation(TableConstants.Operations.INSERT_OR_MERGE, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Deletes an entity within a table. To delete conditionally based on etag, set entity['.metadata']['etag'].
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResponse} callback `error` will contain information if an error occurs;
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.deleteEntity = function (table, entityDescriptor, optionsOrCallback, callback) {
+ this._performEntityOperation(TableConstants.Operations.DELETE, table, entityDescriptor, optionsOrCallback, callback);
+};
+
+/**
+* Executes the operations in the batch.
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {TableBatch} batch The table batch to execute.
+* @param {object} [options] The create options or callback function.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain responses for each operation executed in the batch;
+* `result.entity` will contain the entity information for each operation executed.
+* `result.response` will contain the response for each operations executed.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype.executeBatch = function (table, batch, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('executeBatch', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.object(batch, 'batch');
+ v.callback(callback);
+ });
+
+ if(!batch.hasOperations()) {
+ throw new Error(SR.EMPTY_BATCH);
+ }
+
+ var options = extend(true, {}, userOptions);
+
+ var batchResult = new BatchResult(this, table, batch.operations);
+ var webResource = batchResult.constructWebResource();
+
+ var body = batchResult.serialize();
+ webResource.withBody(body);
+ webResource.withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(body, 'utf8'));
+
+ var processResponseCallback = function (responseObject, next) {
+ var responseObjects = batchResult.parse(responseObject);
+
+ var noError = true;
+ // if the batch was unsuccesful, there will be a single response indicating the error
+ if (responseObjects && responseObjects.length > 0) {
+ responseObjects.forEach(function(item){
+ if(noError && !item.response.isSuccessful){
+ responseObject = item;
+ noError = false;
+ }
+ });
+ }
+
+ if (noError) {
+ responseObject.operationResponses = responseObjects;
+ }
+
+ var finalCallback = function (returnObject) {
+ // perform final callback
+ callback(returnObject.error, returnObject.operationResponses, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+// Private methods
+
+/**
+* Checks whether or not a table exists on the service.
+* @ignore
+*
+* @this {TableService}
+* @param {string} table The table name.
+* @param {string} primaryOnly If true, the request will be executed against the primary storage location.
+* @param {object} [options] The request options.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {Function(error, result, response)} callback `error` will contain information if an error occurs;
+* otherwise `result` will contain
+* the table information including `exists` boolean member.
+* `response` will contain information related to this operation.
+*/
+TableService.prototype._doesTableExist = function (table, primaryOnly, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('doesTableExist', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+
+ if(primaryOnly === false) {
+ options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY;
+ }
+
+ var webResource = WebResource.get('Tables(\'' + table + '\')');
+ webResource.withHeader(HeaderConstants.ACCEPT, this.defaultPayloadFormat);
+
+ var processResponseCallback = function (responseObject, next) {
+ responseObject.tableResult = {};
+ responseObject.tableResult.isSuccessful = responseObject.error ? false : true;
+ responseObject.tableResult.statusCode = responseObject.response === null || responseObject.response === undefined ? undefined : responseObject.response.statusCode;
+ responseObject.tableResult.TableName = table;
+
+ if(!responseObject.error){
+ responseObject.tableResult.exists = true;
+ } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) {
+ responseObject.error = null;
+ responseObject.tableResult.exists = false;
+ responseObject.response.isSuccessful = true;
+ }
+
+ var finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.tableResult, returnObject.response);
+ };
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, null, options, processResponseCallback);
+};
+
+/**
+* Performs a table operation.
+*
+* @this {TableService}
+* @param {string} operation The operation to perform.
+* @param {string} table The table name.
+* @param {object} entityDescriptor The entity descriptor.
+* @param {object} [options] The create options or callback function.
+* @param {string} [options.echoContent] Whether or not to return the entity upon a successful insert. Default to false.
+* @param {string} [options.payloadFormat] The payload format to use for the request.
+* @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+* Please see StorageUtilities.LocationMode for the possible values.
+* @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+* @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+* @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+* The maximum execution time interval begins at the time that the client begins building the request. The maximum
+* execution time is checked intermittently while performing requests, and before executing retries.
+* @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+* @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+* The default value is false.
+* @param {errorOrResult} callback `error` will contain information if an error occurs;
+* otherwise `entity` will contain the entity information.
+* `response` will contain information related to this operation.
+* @ignore
+*/
+TableService.prototype._performEntityOperation = function (operation, table, entityDescriptor, optionsOrCallback, callback) {
+ var userOptions;
+ azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
+
+ validate.validateArgs('entityOperation', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ v.object(entityDescriptor, 'entityDescriptor');
+
+ if(typeof entityDescriptor.PartitionKey !== 'string') {
+ v.object(entityDescriptor.PartitionKey, 'entityDescriptor.PartitionKey');
+ v.stringAllowEmpty(entityDescriptor.PartitionKey._, 'entityDescriptor.PartitionKey._');
+ }
+
+ if(typeof entityDescriptor.RowKey !== 'string') {
+ v.object(entityDescriptor.RowKey, 'entityDescriptor.RowKey');
+ v.stringAllowEmpty(entityDescriptor.RowKey._, 'entityDescriptor.RowKey._');
+ }
+ v.callback(callback);
+ });
+
+ var options = extend(true, {}, userOptions);
+ options.payloadFormat = options.payloadFormat || this.defaultPayloadFormat;
+
+ var webResource = RequestHandler.constructEntityWebResource(operation, table, entityDescriptor, options);
+
+ var processResponseCallback = function (responseObject, next) {
+ var finalCallback;
+ if (operation === TableConstants.Operations.DELETE) {
+ finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.response);
+ };
+ } else {
+ responseObject.entityResponse = null;
+ if (!responseObject.error) {
+ responseObject.entityResponse = entityResult.parseEntity(responseObject.response, options.autoResolveProperties, options.propertyResolver, options.entityResolver);
+ }
+
+ finalCallback = function (returnObject) {
+ callback(returnObject.error, returnObject.entityResponse, returnObject.response);
+ };
+ }
+
+ next(responseObject, finalCallback);
+ };
+
+ this.performRequest(webResource, webResource.body, options, processResponseCallback);
+};
+
+/**
+* Retrieves a table URL.
+*
+* @param {string} table The table name.
+* @param {string} [sasToken] The Shared Access Signature token.
+* @param {boolean} [primary] A boolean representing whether to use the primary or the secondary endpoint.
+* @return {string} The formatted URL string.
+* @example
+* var azure = require('azure-storage');
+* var tableService = azure.createTableService();
+* var sharedAccessPolicy = {
+* AccessPolicy: {
+* Permissions: azure.TableUtilities.SharedAccessPermissions.QUERY,
+* Start: startDate,
+* Expiry: expiryDate
+* },
+* };
+*
+* var sasToken = tableService.generateSharedAccessSignature(table, sharedAccessPolicy);
+* var sasUrl = tableService.getUrl(table, sasToken);
+*/
+TableService.prototype.getUrl = function (table, sasToken, primary) {
+ validate.validateArgs('getUrl', function (v) {
+ v.string(table, 'table');
+ v.tableNameIsValid(table);
+ });
+
+ return this._getUrl(table, sasToken, primary);
+};
+
+/**
+* Given the partition key, row key, property name, property value,
+* and the property Edm type if given by the service, returns the Edm type of the property.
+* @typedef {function} TableService~propertyResolver
+* @param {object} pk The partition key.
+* @param {object} rk The row key.
+* @param {string} name The property name.
+* @param {object} value The property value.
+* @param {string} type The EDM type.
+*/
+
+/**
+* Returns entities matched by a query.
+* @callback TableService~queryResponse
+* @param {object} error If an error occurs, the error information.
+* @param {object} entries The entities returned by the query.
+* @param {object} queryResultContinuation If more matching entities exist, and could not be returned,
+* a continuation token that can be used to retrieve more results.
+* @param {object} response Information related to this operation.
+*/
+
+module.exports = TableService;
diff --git a/src/node_modules/azure-storage/lib/services/table/tableutilities.js b/src/node_modules/azure-storage/lib/services/table/tableutilities.js
new file mode 100644
index 0000000..ecf7e24
--- /dev/null
+++ b/src/node_modules/azure-storage/lib/services/table/tableutilities.js
@@ -0,0 +1,154 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Expose 'HeaderConstants'.
+exports = module.exports;
+
+/**
+* Defines constants, enums, and utility functions for use with the Table service.
+* @namespace TableUtilities
+*/
+var TableUtilities = {
+ /**
+ * Permission types.
+ *
+ * @const
+ * @enum {string}
+ */
+ SharedAccessPermissions: {
+ QUERY: 'r',
+ ADD: 'a',
+ UPDATE: 'u',
+ DELETE: 'd'
+ },
+
+ /**
+ * Payload Format.
+ *
+ * @const
+ * @enum {string}
+ */
+ PayloadFormat: {
+ FULL_METADATA: 'application/json;odata=fullmetadata',
+ MINIMAL_METADATA: 'application/json;odata=minimalmetadata',
+ NO_METADATA: 'application/json;odata=nometadata'
+ },
+
+ /**
+ * Defines the set of Boolean operators for constructing queries.
+ *
+ * @const
+ * @enum {string}
+ */
+ TableOperators: {
+ AND: 'and',
+ NOT: 'not',
+ OR: 'or'
+ },
+
+ /**
+ * Filter property comparison operators.
+ *
+ * @const
+ * @enum {string}
+ */
+ QueryComparisons: {
+ EQUAL: 'eq',
+ NOT_EQUAL: 'ne',
+ GREATER_THAN: 'gt',
+ GREATER_THAN_OR_EQUAL: 'ge',
+ LESS_THAN: 'lt',
+ LESS_THAN_OR_EQUAL: 'le'
+ },
+
+ /**
+ * Edm types.
+ *
+ * @const
+ * @enum {string}
+ */
+ EdmType: {
+ STRING: 'Edm.String',
+ BINARY: 'Edm.Binary',
+ INT64: 'Edm.Int64',
+ INT32: 'Edm.Int32',
+ DOUBLE: 'Edm.Double',
+ DATETIME: 'Edm.DateTime',
+ GUID: 'Edm.Guid',
+ BOOLEAN: 'Edm.Boolean'
+ },
+
+ /**
+ * A helper to create table entities.
+ *
+ * @example
+ * var entGen = TableUtilities.entityGenerator;
+ * var entity = { PartitionKey: entGen.String('part2'),
+ * RowKey: entGen.String('row1'),
+ * boolValue: entGen.Boolean(true),
+ * intValue: entGen.Int32(42),
+ * dateValue: entGen.DateTime(new Date(Date.UTC(2011, 10, 25))),
+ * };
+ */
+ entityGenerator: (function()
+ {
+ var EntityProperty = function (value, type) {
+ var entityProperty = { _:value};
+ if (type) {
+ entityProperty['$'] = type;
+ }
+ return entityProperty;
+ };
+
+ return {
+ EntityProperty : EntityProperty,
+
+ Int32 : function(value) {
+ return new EntityProperty(value, 'Edm.Int32');
+ },
+
+ Int64 : function(value) {
+ return new EntityProperty(value, 'Edm.Int64');
+ },
+
+ Binary : function(value) {
+ return new EntityProperty(value, 'Edm.Binary');
+ },
+
+ Boolean : function(value) {
+ return new EntityProperty(value, 'Edm.Boolean');
+ },
+
+ String : function(value) {
+ return new EntityProperty(value, 'Edm.String');
+ },
+
+ Guid : function(value) {
+ return new EntityProperty(value, 'Edm.Guid');
+ },
+
+ Double : function(value) {
+ return new EntityProperty(value, 'Edm.Double');
+ },
+
+ DateTime : function(value) {
+ return new EntityProperty(value, 'Edm.DateTime');
+ }
+ };
+ })()
+};
+
+module.exports = TableUtilities;
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/package.json b/src/node_modules/azure-storage/package.json
new file mode 100644
index 0000000..edf832e
--- /dev/null
+++ b/src/node_modules/azure-storage/package.json
@@ -0,0 +1,106 @@
+{
+ "_args": [
+ [
+ "azure-storage@2.10.3",
+ "/Users/swinkler/Desktop/manning/manning-code/chapter5/creative/terraform-azure-ballroom/src"
+ ]
+ ],
+ "_from": "azure-storage@2.10.3",
+ "_id": "azure-storage@2.10.3",
+ "_inBundle": false,
+ "_integrity": "sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ==",
+ "_location": "/azure-storage",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "version",
+ "registry": true,
+ "raw": "azure-storage@2.10.3",
+ "name": "azure-storage",
+ "escapedName": "azure-storage",
+ "rawSpec": "2.10.3",
+ "saveSpec": null,
+ "fetchSpec": "2.10.3"
+ },
+ "_requiredBy": [
+ "/"
+ ],
+ "_resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.3.tgz",
+ "_spec": "2.10.3",
+ "_where": "/Users/swinkler/Desktop/manning/manning-code/chapter5/creative/terraform-azure-ballroom/src",
+ "author": {
+ "name": "Microsoft Corporation"
+ },
+ "bugs": {
+ "url": "http://github.com/Azure/azure-storage-node/issues"
+ },
+ "dependencies": {
+ "browserify-mime": "~1.2.9",
+ "extend": "^3.0.2",
+ "json-edm-parser": "0.1.2",
+ "md5.js": "1.3.4",
+ "readable-stream": "~2.0.0",
+ "request": "^2.86.0",
+ "underscore": "~1.8.3",
+ "uuid": "^3.0.0",
+ "validator": "~9.4.1",
+ "xml2js": "0.2.8",
+ "xmlbuilder": "^9.0.7"
+ },
+ "description": "Microsoft Azure Storage Client Library for Node.js",
+ "devDependencies": {
+ "batchflow": "0.4.0",
+ "browserify": "^16.1.1",
+ "coveralls": "^3.0.3",
+ "factor-bundle": "^2.5.0",
+ "grunt": "^1.0.4",
+ "grunt-jsdoc": "^2.3.0",
+ "ink-docstrap": "^1.3.0",
+ "istanbul": "^0.4.5",
+ "jshint": ">= 2.1.4",
+ "karma": "^4.0.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": ">= 1.18.0",
+ "mocha-lcov-reporter": "^1.0.0",
+ "nock": "0.16",
+ "should": "1.2.x",
+ "uglify-js": "~3.3.9",
+ "watchify": "^3.11.0"
+ },
+ "engines": {
+ "node": ">= 0.8.26"
+ },
+ "homepage": "http://github.com/Azure/azure-storage-node",
+ "keywords": [
+ "node",
+ "azure",
+ "storage"
+ ],
+ "license": "Apache-2.0",
+ "main": "./lib/azure-storage.js",
+ "name": "azure-storage",
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/Azure/azure-storage-node.git"
+ },
+ "scripts": {
+ "check": "jshint lib && npm set audit-level high && npm audit",
+ "cover": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec -u bdd --no-timeouts --recursive test",
+ "coveralls": "npm run cover && cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js",
+ "genjs": "node ./browser/bundle.js",
+ "jstest": "npm run genjs && node ./browser/test/bundle.js && karma start --single-run",
+ "test": "mocha --no-timeouts --recursive test"
+ },
+ "tags": [
+ "azure",
+ "storage",
+ "sdk"
+ ],
+ "typings": "typings/azure-storage/azure-storage.d.ts",
+ "version": "2.10.3"
+}
diff --git a/src/node_modules/azure-storage/tsconfig.json b/src/node_modules/azure-storage/tsconfig.json
new file mode 100644
index 0000000..a0e5d93
--- /dev/null
+++ b/src/node_modules/azure-storage/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "sourceMap": true,
+ "outDir": "built",
+ "noEmitOnError": true,
+ "module": "commonjs"
+ },
+ "exclude": [
+ "node_modules",
+ "built",
+ "docs"
+ ]
+}
\ No newline at end of file
diff --git a/src/node_modules/azure-storage/typings.json b/src/node_modules/azure-storage/typings.json
new file mode 100644
index 0000000..bbce788
--- /dev/null
+++ b/src/node_modules/azure-storage/typings.json
@@ -0,0 +1,6 @@
+{
+ "globalDependencies": {
+ "node": "registry:env/node#0.10.0+20160918225031",
+ "node-uuid": "registry:dt/node-uuid#0.0.0+20160316155526"
+ }
+}
diff --git a/src/node_modules/azure-storage/typings/azure-storage/azure-storage.d.ts b/src/node_modules/azure-storage/typings/azure-storage/azure-storage.d.ts
new file mode 100644
index 0000000..ffd9706
--- /dev/null
+++ b/src/node_modules/azure-storage/typings/azure-storage/azure-storage.d.ts
@@ -0,0 +1,9750 @@
+//
+// Copyright (c) Microsoft and contributors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+import * as events from 'events';
+import * as url from 'url';
+import * as stream from 'stream';
+
+interface Map {
+ [index: string]: T;
+}
+
+interface SharedKeyGenerateSignatureArgs {
+ /** The resource type, if the resource is a blob or container. Null if the resource is a queue or table. */
+ resourceType?: string;
+ /** The table name, if the resource is a table. Null if the resource is a blob orqueue. */
+ tableName?: string;
+ /** The optional header values to set for a blob returned wth this SAS. */
+ headers?: {
+ /** The value of the Cache-Control response header to be returned when this SAS is used. */
+ CacheControl?: string;
+ /** The value of the Content-Type response header to be returned when this SAS is used. */
+ ContentType?: string;
+ /** The value of the Content-Encoding response header to be returned when this SAS is used. */
+ ContentEncoding?: string;
+ /** The value of the Content-Language response header to be returned when this SAS is used. */
+ ContentLanguage?: string;
+ /** The value of the Content-Disposition response header to be returned when this SAS is used. */
+ ContentDisposition: string;
+ };
+}
+
+interface SharedKeyGenerateQueryStringArgs extends SharedKeyGenerateSignatureArgs {
+ /** The query string, if additional parameters are desired. */
+ queryString?: string;
+}
+
+declare module azurestorage {
+ export interface StorageHost {
+ primaryHost: string;
+ secondaryHost?: string;
+ }
+
+ module services {
+ module blob {
+ // ###########################
+ // ./services/blob/blobservice
+ // ###########################
+ module blobservice {
+ export class BlobService extends StorageServiceClient {
+ defaultEnableReuseSocket: boolean;
+ singleBlobPutThresholdInBytes: number;
+ parallelOperationThreadCount: number;
+
+ /**
+ * Creates a new BlobService object.
+ * If no connection string or storageaccount and storageaccesskey are provided,
+ * the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
+ * @class
+ * The BlobService class is used to perform operations on the Microsoft Azure Blob Service.
+ * The Blob Service provides storage for binary large objects, and provides
+ * functions for working with data stored in blobs as either streams or pages of data.
+ *
+ * For more information on the Blob Service, as well as task focused information on using it in a Node.js application, see
+ * [How to Use the Blob Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-blob-storage/).
+ * The following defaults can be set on the blob service.
+ * singleBlobPutThresholdInBytes The default maximum size, in bytes, of a blob before it must be separated into blocks.
+ * defaultEnableReuseSocket The default boolean value to enable socket reuse when uploading local files or streams.
+ * If the Node.js version is lower than 0.10.x, socket reuse will always be turned off.
+ * defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Blob service.
+ * defaultClientRequestTimeoutInMs The default timeout of client requests, in milliseconds, to use for the request made via the Blob service.
+ * defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Blob service.
+ * defaultLocationMode The default location mode for requests made via the Blob service.
+ * parallelOperationThreadCount The number of parallel operations that may be performed when uploading a blob that is greater than
+ * the value specified by the singleBlobPutThresholdInBytes property in size.
+ * useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Blob service; true to use the
+ * Nagle algorithm; otherwise, false. The default value is false.
+ * enableGlobalHttpAgent Determines whether global HTTP(s) agent is enabled; true to use Global HTTP(s) agent; otherwise, false to use
+ * http(s).Agent({keepAlive:true}).
+ * @constructor
+ * @extends {StorageServiceClient}
+ *
+ * @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+ * @param {string} [storageAccessKey] The storage access key.
+ * @param {string|object} [host] The host address. To define primary only, pass a string.
+ * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+ * @param {string} [sasToken] The Shared Access Signature token.
+ * @param {string} [endpointSuffix] The endpoint suffix.
+ */
+ constructor(storageAccountOrConnectionString: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string, endpointSuffix?: string);
+
+ /**
+ * Associate a filtering operation with this BlobService. Filtering operations
+ * can include logging, automatically retrying, etc. Filter operations are objects
+ * that implement a method with the signature:
+ *
+ * "function handle (requestOptions, next)".
+ *
+ * After doing its preprocessing on the request options, the method needs to call
+ * "next" passing a callback with the following signature:
+ * signature:
+ *
+ * "function (returnObject, finalCallback, next)"
+ *
+ * In this callback, and after processing the returnObject (the response from the
+ * request to the server), the callback needs to either invoke next if it exists to
+ * continue processing other filters or simply invoke finalCallback otherwise to end
+ * up the service invocation.
+ *
+ * @function BlobService#withFilter
+ * @param {Object} filter The new filter object.
+ * @return {BlobService} A new service client with the filter applied.
+ */
+ withFilter(newFilter: common.filters.IFilter): BlobService;
+
+ /**
+ * Gets the service stats for a storage account’s Blob service.
+ *
+ * @this {BlobService}
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `result` will contain the stats and
+ * `response` will contain information related to this operation.
+ */
+ getServiceStats(options: common.RequestOptions, callback: ErrorOrResult): void;
+ getServiceStats(callback: ErrorOrResult): void;
+
+ /**
+ * Gets the properties of a storage account’s Blob service, including Azure Storage Analytics.
+ *
+ * @this {BlobService}
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `result` will contain the properties
+ * and `response` will contain information related to this operation.
+ */
+ getServiceProperties(options: common.RequestOptions, callback?: ErrorOrResult): void;
+ getServiceProperties(callback?: ErrorOrResult): void;
+
+ /**
+ * Gets the properties of a storage account.
+ *
+ * @this {BlobService}
+ * @param {string} [container] Optional. Name of an existing container. Required when using a SAS token to a specific container or blob.
+ * @param {string} [blob] Optional. Name of an existing blob. Required when using a SAS token to a specific blob.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `[result]{@link AccountProperties}` will contain the properties
+ * and `response` will contain information related to this operation.
+ */
+ getAccountProperties(container?:string, blob?:string, options?: common.RequestOptions, callback?: ErrorOrResult): void;
+ getAccountProperties(container?:string, blob?:string, callback?: ErrorOrResult): void;
+
+ /**
+ * Sets the properties of a storage account’s Blob service, including Azure Storage Analytics.
+ * You can also use this operation to set the default request version for all incoming requests that do not have a version specified.
+ * When you set blob service properties (such as enabling soft delete), it may take up to 30 seconds to take effect.
+ *
+ * @this {BlobService}
+ * @param {Object} serviceProperties The service properties.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise, `response`
+ * will contain information related to this operation.
+ */
+ setServiceProperties(serviceProperties: common.models.ServicePropertiesResult.BlobServiceProperties, options: common.RequestOptions, callback: ErrorOrResponse): void;
+ setServiceProperties(serviceProperties: common.models.ServicePropertiesResult.BlobServiceProperties, callback: ErrorOrResponse): void;
+
+ /**
+ * Sets the tier of a blockblob under a blob storage LRS account, or the tier of a pageblob under a premium storage account.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} blobTier Please see BlobUtilities.BlobTier.StandardBlobTier or BlobUtilities.BlobTier.PremiumPageBlobTier for possible values.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise, `response`
+ * will contain information related to this operation.
+ */
+ setBlobTier(container: string, blob: string, blobTier: string, options: common.RequestOptions, callback: ErrorOrResponse): void;
+ setBlobTier(container: string, blob: string, blobTier: string, callback: ErrorOrResponse): void;
+
+ /**
+ * Lists a segment containing a collection of container items under the specified account.
+ *
+ * @this {BlobService}
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.maxResults] Specifies the maximum number of containers to return per call to Azure storage.
+ * @param {string} [options.include] Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of containers and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listContainersSegmented(currentToken: common.ContinuationToken, options: BlobService.ListContainerOptions, callback: ErrorOrResult): void;
+ listContainersSegmented(currentToken: common.ContinuationToken, callback: ErrorOrResult): void;
+ /**
+ * Lists a segment containing a collection of container items whose names begin with the specified prefix under the specified account.
+ *
+ * @this {BlobService}
+ * @param {string} prefix The prefix of the container name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.maxResults] Specifies the maximum number of containers to return per call to Azure storage.
+ * @param {string} [options.include] Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of containers and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listContainersSegmentedWithPrefix(prefix: string, currentToken: common.ContinuationToken, options: BlobService.ListContainerOptions, callback: ErrorOrResult): void;
+ listContainersSegmentedWithPrefix(prefix: string, currentToken: common.ContinuationToken, callback: ErrorOrResult): void;
+
+ /**
+ * Checks whether or not a container exists on the service.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the container exists, or false if the container does not exist.
+ * `response` will contain information related to this operation.
+ */
+ doesContainerExist(container: string, options: common.RequestOptions, callback: ErrorOrResult): void;
+
+
+ /**
+ * Checks whether or not a container exists on the service.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the container exists, or false if the container does not exist.
+ * `response` will contain information related to this operation.
+ */
+ doesContainerExist(container: string, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a new container under the specified account.
+ * If a container with the same name already exists, the operation fails.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the container information.
+ * `response` will contain information related to this operation.
+ */
+ createContainer(container: string, callback: ErrorOrResult): void;
+
+
+ /**
+ * Creates a new container under the specified account.
+ * If a container with the same name already exists, the operation fails.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the container information.
+ * `response` will contain information related to this operation.
+ */
+ createContainer(container: string, options: BlobService.CreateContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a new container under the specified account if the container does not exists.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the container was created, or false if the container
+ * already exists.
+ * `response` will contain information related to this operation.
+ *
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.createContainerIfNotExists('taskcontainer', {publicAccessLevel : 'blob'}, function(error) {
+ * if(!error) {
+ * // Container created or exists, and is public
+ * }
+ * });
+ */
+ createContainerIfNotExists(container: string, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a new container under the specified account if the container does not exists.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the container was created, or false if the container
+ * already exists.
+ * `response` will contain information related to this operation.
+ *
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.createContainerIfNotExists('taskcontainer', {publicAccessLevel : 'blob'}, function(error) {
+ * if(!error) {
+ * // Container created or exists, and is public
+ * }
+ * });
+ */
+ createContainerIfNotExists(container: string, options: BlobService.CreateContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Retrieves a container and its properties from a specified account.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ getContainerProperties(container: string, callback: ErrorOrResult): void;
+
+ /**
+ * Retrieves a container and its properties from a specified account.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ getContainerProperties(container: string, options: BlobService.ContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Returns all user-defined metadata for the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ getContainerMetadata(container: string, callback: ErrorOrResult): void;
+
+ /**
+ * Returns all user-defined metadata for the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ getContainerMetadata(container: string, options: BlobService.ContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Sets the container's metadata.
+ *
+ * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container.
+ * It's not possible to modify an individual name/value pair.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} metadata The metadata key/value pairs.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ setContainerMetadata(container: string, metadata: Map, callback: ErrorOrResult): void;
+
+ /**
+ * Sets the container's metadata.
+ *
+ * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container.
+ * It's not possible to modify an individual name/value pair.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} metadata The metadata key/value pairs.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ setContainerMetadata(container: string, metadata: Map, options: BlobService.ContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Gets the container's ACL.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ getContainerAcl(container: string, callback: ErrorOrResult): void;
+
+ /**
+ * Gets the container's ACL.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ getContainerAcl(container: string, options: BlobService.ContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Updates the container's ACL.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {[key:string]: AccessPolicy} signedIdentifiers The container ACL settings. See `[AccessPolicy]{@link AccessPolicy}` for detailed information.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information for the container.
+ * `response` will contain information related to this operation.
+ */
+ setContainerAcl(container: string, signedIdentifiers: {[key:string]: common.AccessPolicy}, options: BlobService.ContainerAclOptions, callback: ErrorOrResult): void;
+ setContainerAcl(container: string, signedIdentifiers: {[key:string]: common.AccessPolicy}, callback: ErrorOrResult): void;
+
+ /**
+ * Marks the specified container for deletion.
+ * The container and any blobs contained within it are later deleted during garbage collection.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ deleteContainer(container: string, callback: ErrorOrResponse): void;
+
+ /**
+ * Marks the specified container for deletion.
+ * The container and any blobs contained within it are later deleted during garbage collection.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ deleteContainer(container: string, options: BlobService.ContainerOptions, callback: ErrorOrResponse): void;
+
+ /**
+ * Marks the specified container for deletion if it exists.
+ * The container and any blobs contained within it are later deleted during garbage collection.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the container exists and was deleted, or false if the container
+ * did not exist.
+ * `response` will contain information related to this operation.
+ */
+ deleteContainerIfExists(container: string, callback: ErrorOrResult): void;
+
+ /**
+ * Marks the specified container for deletion if it exists.
+ * The container and any blobs contained within it are later deleted during garbage collection.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {string} [options.leaseId] The container lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the container exists and was deleted, or false if the container
+ * did not exist.
+ * `response` will contain information related to this operation.
+ */
+ deleteContainerIfExists(container: string, options: BlobService.ContainerOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob directory items in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of `[directories]{@link BlobDirectoryResult}` and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobDirectoriesSegmented(container: string, currentToken: common.ContinuationToken, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob directory items in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {object} [options] The request options.
+ * @param {int} [options.maxResults] Specifies the maximum number of directories to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of `[directories]{@link BlobDirectoryResult}` and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobDirectoriesSegmented(container: string, currentToken: common.ContinuationToken, options: BlobService.ListBlobPrefixesSegmentedRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob directory items whose names begin with the specified prefix in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} prefix The prefix of the blob name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of `[directories]{@link BlobDirectoryResult}` and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobDirectoriesSegmentedWithPrefix(container: string, prefix: string, currentToken: common.ContinuationToken, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob directory items whose names begin with the specified prefix in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} prefix The prefix of the blob directory.
+ * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {object} [options] The request options.
+ * @param {int} [options.maxResults] Specifies the maximum number of directories to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of `[directories]{@link BlobDirectoryResult}` and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobDirectoriesSegmentedWithPrefix(container: string, prefix: string, currentToken: common.ContinuationToken, options: BlobService.ListBlobPrefixesSegmentedRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob items in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of blobs and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobsSegmented(container: string, currentToken: common.ContinuationToken, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob items in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.delimiter] Delimiter, i.e. '/', for specifying folder hierarchy.
+ * @param {int} [options.maxResults] Specifies the maximum number of blobs to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+ * @param {string} [options.include] Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs', 'copy', 'deleted'). Multiple values can be added separated with a comma (,)
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
+ * `entries` gives a list of blobs and the `continuationToken` is used for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobsSegmented(container: string, currentToken: common.ContinuationToken, options: BlobService.ListBlobsSegmentedRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob items whose names begin with the specified prefix in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} prefix The prefix of the blob name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the entries of blobs and the continuation token for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobsSegmentedWithPrefix(container: string, prefix: string, currentToken: common.ContinuationToken, callback: ErrorOrResult): void;
+
+ /**
+ * Lists a segment containing a collection of blob items whose names begin with the specified prefix in the container.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} prefix The prefix of the blob name.
+ * @param {Object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.delimiter] Delimiter, i.e. '/', for specifying folder hierarchy.
+ * @param {int} [options.maxResults] Specifies the maximum number of blobs to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000)
+ * @param {string} [options.include] Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs', 'copy', 'deleted'). Multiple values can be added separated with a comma (,)
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs]The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the entries of blobs and the continuation token for the next listing operation.
+ * `response` will contain information related to this operation.
+ */
+ listBlobsSegmentedWithPrefix(container: string, prefix: string, currentToken: common.ContinuationToken, options: BlobService.ListBlobsSegmentedRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Acquires a new lease. If container and blob are specified, acquires a blob lease. Otherwise, if only container is specified and blob is null, acquires a container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ acquireLease(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Acquires a new lease. If container and blob are specified, acquires a blob lease. Otherwise, if only container is specified and blob is null, acquires a container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseDuration] The lease duration in seconds. A non-infinite lease can be between 15 and 60 seconds. Default is never to expire.
+ * @param {string} [options.proposedLeaseId] The proposed lease identifier. Must be a GUID.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ acquireLease(container: string, blob: string, options: BlobService.AcquireLeaseRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Renews an existing lease. If container and blob are specified, renews the blob lease. Otherwise, if only container is specified and blob is null, renews the container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} leaseId The lease identifier. Must be a GUID.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ renewLease(container: string, blob: string, leaseId: string, callback: ErrorOrResult): void;
+
+ /**
+ * Renews an existing lease. If container and blob are specified, renews the blob lease. Otherwise, if only container is specified and blob is null, renews the container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} leaseId The lease identifier. Must be a GUID.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ renewLease(container: string, blob: string, leaseId: string, options: BlobService.LeaseRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Changes the lease ID of an active lease. If container and blob are specified, changes the blob lease. Otherwise, if only container is specified and blob is null, changes the
+ * container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} leaseId The current lease identifier.
+ * @param {string} proposedLeaseId The proposed lease identifier. Must be a GUID.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs;
+ * otherwise `result` will contain the lease information.
+ * `response` will contain information related to this operation.
+ */
+ changeLease(container: string, blob: string, leaseId: string, proposedLeaseId: string, callback: ErrorOrResult): void;
+
+ /**
+ * Changes the lease ID of an active lease. If container and blob are specified, changes the blob lease. Otherwise, if only container is specified and blob is null, changes the
+ * container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} leaseId The current lease identifier.
+ * @param {string} proposedLeaseId The proposed lease identifier. Must be a GUID.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs;
+ * otherwise `result` will contain the lease information.
+ * `response` will contain information related to this operation.
+ */
+ changeLease(container: string, blob: string, leaseId: string, proposedLeaseId: string, options: BlobService.LeaseRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Releases the lease. If container and blob are specified, releases the blob lease. Otherwise, if only container is specified and blob is null, releases the container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} leaseId The lease identifier.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ releaseLease(container: string, blob: string, leaseId: string, callback: ErrorOrResult): void;
+
+ /**
+ * Releases the lease. If container and blob are specified, releases the blob lease. Otherwise, if only container is specified and blob is null, releases the container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} leaseId The lease identifier.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ releaseLease(container: string, blob: string, leaseId: string, options: BlobService.LeaseRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Breaks the lease but ensures that another client cannot acquire a new lease until the current lease period has expired. If container and blob are specified, breaks the blob lease.
+ * Otherwise, if only container is specified and blob is null, breaks the container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ breakLease(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Breaks the lease but ensures that another client cannot acquire a new lease until the current lease period has expired. If container and blob are specified, breaks the blob lease.
+ * Otherwise, if only container is specified and blob is null, breaks the container lease.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {int} [options.leaseBreakPeriod] The lease break period, between 0 and 60 seconds. If unspecified, a fixed-duration lease breaks after
+ * the remaining lease period elapses, and an infinite lease breaks immediately.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the lease information.
+ * `response` will contain information related to this operation.
+ */
+ breakLease(container: string, blob: string, options: BlobService.BreakLeaseRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Returns all user-defined metadata, standard HTTP properties, and system properties for the blob.
+ * It does not return or modify the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ getBlobProperties(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Returns all user-defined metadata, standard HTTP properties, and system properties for the blob.
+ * It does not return or modify the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ getBlobProperties(container: string, blob: string, optionsOrCallback: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Returns all user-defined metadata for the specified blob or snapshot.
+ * It does not modify or return the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ getBlobMetadata(container: string, blob: string, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+ getBlobMetadata(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Clears user-defined properties for the specified blob or snapshot.
+ * It does not modify or return the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ setBlobProperties(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Sets user-defined properties for the specified blob or snapshot.
+ * It does not modify or return the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentMD5] The blob's MD5 hash.
+ * @param {string} [options.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentDisposition] The blob's content disposition.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ setBlobProperties(container: string, blob: string, optionsOrCallback: BlobService.SetBlobPropertiesRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Sets user-defined metadata for the specified blob or snapshot as one or more name-value pairs
+ * It does not modify or return the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} metadata The metadata key/value pairs.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information on the blob.
+ * `response` will contain information related to this operation.
+ */
+ setBlobMetadata(container: string, blob: string, metadata: Map, callback: ErrorOrResult): void;
+
+ /**
+ * Sets user-defined metadata for the specified blob or snapshot as one or more name-value pairs
+ * It does not modify or return the content of the blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} metadata The metadata key/value pairs.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information on the blob.
+ * `response` will contain information related to this operation.
+ */
+ setBlobMetadata(container: string, blob: string, metadata: Map, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Downloads a blob into a file.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} localFileName The local path to the file to be downloaded.
+ * @param {Object} [options] The request options.
+ * @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+ * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+ * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs;
+ * otherwise `result` will contain the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ *
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.getBlobToLocalFile('taskcontainer', 'task1', 'task1-download.txt', function(error, serverBlob) {
+ * if(!error) {
+ * // Blob available in serverBlob.blob variable
+ * }
+ */
+ getBlobToLocalFile(container: string, blob: string, localFileName: string, options: BlobService.GetBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ getBlobToLocalFile(container: string, blob: string, localFileName: string, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ /**
+ * Provides a stream to read from a blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+ * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+ * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs;
+ * otherwise `result` will contain the blob information.
+ * `response` will contain information related to this operation.
+ * @return {Readable} A Node.js Readable stream.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * var writable = fs.createWriteStream(destinationFileNameTarget);
+ * blobService.createReadStream(containerName, blobName).pipe(writable);
+ */
+ createReadStream(container: string, blob: string, options: BlobService.GetBlobRequestOptions, callback: ErrorOrResult): stream.Readable;
+ createReadStream(container: string, blob: string, callback: ErrorOrResult): stream.Readable;
+
+ /**
+ * Downloads a blob into a stream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Writable} writeStream The Node.js Writable stream.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs;
+ * otherwise `result` will contain the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ *
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.getBlobToStream('taskcontainer', 'task1', fs.createWriteStream('task1-download.txt'), function(error, serverBlob) {
+ * if(!error) {
+ * // Blob available in serverBlob.blob variable
+ * }
+ * });
+ */
+ getBlobToStream(container: string, blob: string, writeStream: stream.Writable, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Downloads a blob into a stream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Writable} writeStream The Node.js Writable stream.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+ * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+ * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions.
+ * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information if an error occurs;
+ * otherwise `result` will contain the blob information.
+ * `response` will contain information related to this operation.
+ *
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.getBlobToStream('taskcontainer', 'task1', fs.createWriteStream('task1-download.txt'), function(error, serverBlob) {
+ * if(!error) {
+ * // Blob available in serverBlob.blob variable
+ * }
+ * });
+ */
+ getBlobToStream(container: string, blob: string, writeStream: stream.Writable, options: BlobService.GetBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Downloads a blob into a text string.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range.
+ * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range.
+ * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {BlobService~blobToText} callback `error` will contain information
+ * if an error occurs; otherwise `text` will contain the blob contents,
+ * and `blockBlob` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ */
+ getBlobToText(container: string, blob: string, options: BlobService.GetBlobRequestOptions, callback: BlobService.BlobToText): void;
+ getBlobToText(container: string, blob: string, callback: BlobService.BlobToText): void;
+
+ /**
+ * Marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
+ * If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots,
+ * or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error
+ * and nothing will be deleted.
+ * If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; `response` will contain information related to this operation.
+ */
+ deleteBlob(container: string, blob: string, callback: ErrorOrResponse): void;
+
+ /**
+ * Marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
+ * If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots,
+ * or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error
+ * and nothing will be deleted.
+ * If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.BlobUtilities.SnapshotDeleteOptions.*.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; `response` will contain information related to this operation.
+ */
+ deleteBlob(container: string, blob: string, options: BlobService.DeleteBlobRequestOptions, callback: ErrorOrResponse): void;
+
+ /**
+ * The undelete Blob operation restores the contents and metadata of soft deleted blob or snapshot.
+ * Attempting to undelete a blob or snapshot that is not soft deleted will succeed without any changes.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; `response` will contain information related to this operation.
+ */
+ undeleteBlob(container: string, blob: string, callback: ErrorOrResponse): void;
+ undeleteBlob(container: string, blob: string, options: BlobService.ConditionalRequestOption, callback: ErrorOrResponse): void;
+
+ /**
+ * Marks the specified blob or snapshot for deletion if it exists. The blob is later deleted during garbage collection.
+ * If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots,
+ * or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error
+ * and nothing will be deleted.
+ * If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the blob was deleted, or false if the blob
+ * does not exist.
+ * `response` will contain information related to this operation.
+ */
+ deleteBlobIfExists(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Marks the specified blob or snapshot for deletion if it exists. The blob is later deleted during garbage collection.
+ * If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots,
+ * or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error
+ * and nothing will be deleted.
+ * If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.BlobUtilities.SnapshotDeleteOptions.*.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will
+ * be true if the blob was deleted, or false if the blob
+ * does not exist.
+ * `response` will contain information related to this operation.
+ */
+ deleteBlobIfExists(container: string, blob: string, options: BlobService.DeleteBlobRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Checks whether or not a blob exists on the service.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `errorOrResult` will
+ * be true if the blob exists, or false if the blob does not exist.
+ * `response` will contain information related to this operation.
+ */
+ doesBlobExist(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Checks whether or not a blob exists on the service.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `errorOrResult` will
+ * be true if the blob exists, or false if the blob does not exist.
+ * `response` will contain information related to this operation.
+ */
+ doesBlobExist(container: string, blob: string, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a read-only snapshot of a blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the ID of the snapshot.
+ * `response` will contain information related to this operation.
+ */
+ createBlobSnapshot(container: string, blob: string, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+ createBlobSnapshot(container: string, blob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Starts to copy a blob or an Azure Storage file to a destination blob.
+ *
+ * For an asynchronous copy(by default), this operation returns a object including a copy ID which
+ * you can use to check or abort the copy operation. The Blob service copies blobs on a best-effort basis.
+ * The source blob for an asynchronous copy operation may be a block blob, an append blob,
+ * a page blob or an Azure Storage file.
+ *
+ * Refer to https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob for more details.
+ *
+ * @this {BlobService}
+ * @param {string} sourceUri The source blob URI.
+ * @param {string} targetContainer The target container name.
+ * @param {string} targetBlob The target blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+ * @param {boolean} [options.isIncrementalCopy] If it's incremental copy or not. Refer to https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/incremental-copy-blob
+ * @param {string} [options.snapshotId] The source blob snapshot identifier.
+ * @param {Object} [options.metadata] The target blob metadata key/value pairs.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {string} [options.sourceLeaseId] The source blob lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {AccessConditions} [options.sourceAccessConditions] The source access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ */
+ startCopyBlob(sourceUri: string, targetcontainer: string, targetblob: string, options: BlobService.CopyBlobRequestOptions, callback: ErrorOrResult): void;
+ startCopyBlob(sourceUri: string, targetcontainer: string, targetblob: string, callback: ErrorOrResult): void;
+
+ /**
+ * Abort a blob copy operation.
+ *
+ * @this {BlobService}
+ * @param {string} container The destination container name.
+ * @param {string} blob The destination blob name.
+ * @param {string} copyId The copy operation identifier.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {ErrorOrResponse} callback `error` will contain information.
+ * `response` will contain information related to this operation.
+ */
+ abortCopyBlob(container: string, blob: string, copyId: string, options: BlobService.BlobRequestOptions, callback: ErrorOrResponse): void;
+ abortCopyBlob(container: string, blob: string, copyId: string, callback: ErrorOrResponse): void;
+
+ /**
+ * Retrieves a shared access signature token.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} [blob] The blob name.
+ * @param {Object} sharedAccessPolicy The shared access policy.
+ * @param {string} [sharedAccessPolicy.Id] The signed identifier.
+ * @param {Object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+ * @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used).
+ * @param {date|string} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired (The UTC value will be used).
+ * @param {Object} [headers] The optional header values to set for a blob returned wth this SAS.
+ * @param {string} [headers.cacheControl] The optional value of the Cache-Control response header to be returned when this SAS is used.
+ * @param {string} [headers.contentType] The optional value of the Content-Type response header to be returned when this SAS is used.
+ * @param {string} [headers.contentEncoding] The optional value of the Content-Encoding response header to be returned when this SAS is used.
+ * @param {string} [headers.contentLanguage] The optional value of the Content-Language response header to be returned when this SAS is used.
+ * @param {string} [headers.contentDisposition] The optional value of the Content-Disposition response header to be returned when this SAS is used.
+ * @return {string} The shared access signature. Note this does not contain the leading "?".
+ */
+ generateSharedAccessSignature(container: string, blob: string, sharedAccessPolicy: common.SharedAccessPolicy, headers?: common.ContentSettingsHeaders): string;
+
+ /**
+ * Retrieves a shared access signature token.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} [blob] The blob name.
+ * @param {Object} sharedAccessPolicy The shared access policy.
+ * @param {string} [sharedAccessPolicy.Id] The signed identifier.
+ * @param {Object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type.
+ * @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used).
+ * @param {date|string} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired (The UTC value will be used).
+ * @param {string} [sasVersion] An optional string indicating the desired SAS version to use. Value must be 2012-02-12 or later.
+ * @param {Object} [headers] The optional header values to set for a blob returned wth this SAS.
+ * @param {string} [headers.cacheControl] The optional value of the Cache-Control response header to be returned when this SAS is used.
+ * @param {string} [headers.contentType] The optional value of the Content-Type response header to be returned when this SAS is used.
+ * @param {string} [headers.contentEncoding] The optional value of the Content-Encoding response header to be returned when this SAS is used.
+ * @param {string} [headers.contentLanguage] The optional value of the Content-Language response header to be returned when this SAS is used.
+ * @param {string} [headers.contentDisposition] The optional value of the Content-Disposition response header to be returned when this SAS is used.
+ * @return {string} The shared access signature query string. Note this string does not contain the leading "?".
+ */
+ generateSharedAccessSignatureWithVersion(container: string, blob: string, sharedAccessPolicy: common.SharedAccessPolicy, sasVersion: string, headers?: common.ContentSettingsHeaders): string;
+
+ /**
+ * Retrieves a blob or container URL.
+ *
+ * @param {string} container The container name.
+ * @param {string} [blob] The blob name.
+ * @param {string} [sasToken] The Shared Access Signature token.
+ * @param {boolean} [primary] A boolean representing whether to use the primary or the secondary endpoint.
+ * @param {string} [snapshotId] The snapshot identifier.
+ * @return {string} The formatted URL string.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * //create a SAS that expires in an hour
+ * var sasToken = blobService.generateSharedAccessSignature(containerName, blobName, { AccessPolicy: { Expiry: azure.date.minutesFromNow(60); } });
+ * var sasUrl = blobService.getUrl(containerName, blobName, sasToken, true);
+ */
+ getUrl(container: string, blob?: string, sasToken?: string, primary?: boolean, snapshotId?: string): string
+
+ createPageBlob(container: string, blob: string, length: number, callback: ErrorOrResponse): void;
+
+ createPageBlob(container: string, blob: string, length: number, options: BlobService.CreatePageBlobOptions, callback: ErrorOrResponse): void;
+
+ /**
+ * Uploads a page blob from file.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param (string) localFileName The local path to the file to be uploaded.
+ * @param {Object} [options] The request options.
+ * @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ createPageBlobFromLocalFile(container: string, blob: string, localFileName: string, options: BlobService.CreatePageBlobOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createPageBlobFromLocalFile(container: string, blob: string, localFileName: string, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads a page blob from an HTML file. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * (Only available in the JavaScript Client Library for Browsers)
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} browserFile The File object to be uploaded created by HTML File API.
+ * @param {Object} [options] The request options.
+ * @param {SpeedSummary} [options.speedSummary] The upload tracker objects.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ */
+ createPageBlobFromBrowserFile(container: string, blob: string, browserFile: Object, options: BlobService.CreatePageBlobOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createPageBlobFromBrowserFile(container: string, blob: string, browserFile: Object, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads a page blob from a stream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param (Stream) stream Stream to the data to store.
+ * @param {int} streamLength The length of the stream to upload.
+ * @param {Object} [options] The request options.
+ * @param {SpeedSummary} [options.speedSummary] The download tracker objects;
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ createPageBlobFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, options: BlobService.CreatePageBlobOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createPageBlobFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Provides a stream to write to a page blob. Assumes that the blob exists.
+ * If it does not, please create the blob using createPageBlob before calling this method or use createWriteStreamNewPageBlob.
+ * Please note the `Stream` returned by this API should be used with piping.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs and true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {Writable} A Node.js Writable stream.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.createPageBlob(containerName, blobName, 1024, function (err) {
+ * // Pipe file to a blob
+ * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToExistingPageBlob(containerName, blobName));
+ * });
+ */
+ createWriteStreamToExistingPageBlob(container: string, blob: string, options: BlobService.CreatePageBlobOptions, callback: ErrorOrResult): stream.Writable;
+ createWriteStreamToExistingPageBlob(container: string, blob: string, callback: ErrorOrResult): stream.Writable;
+
+ /**
+ * Provides a stream to write to a page blob. Creates the blob before writing data.
+ * Please note the `Stream` returned by this API should be used with piping.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} length The blob length.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs and true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.blobTier] For page blobs on premium accounts only. Set the tier of the target blob. Refer to BlobUtilities.BlobTier.PremiumPageBlobTier.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {Writable} A Node.js Writable stream.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.createPageBlob(containerName, blobName, 1024, function (err) {
+ * // Pipe file to a blob
+ * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToNewPageBlob(containerName, blobName));
+ * });
+ */
+ createWriteStreamToNewPageBlob(container: string, blob: string, length: number, options: BlobService.CreatePageBlobOptions, callback: ErrorOrResult): stream.Writable;
+ createWriteStreamToNewPageBlob(container: string, blob: string, length: number, callback: ErrorOrResult): stream.Writable;
+
+ /**
+ * Updates a page blob from a stream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Readable} readStream The Node.js Readable stream.
+ * @param {int} rangeStart The range start.
+ * @param {int} rangeEnd The range end.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.transactionalContentMD5] An optional hash value used to ensure transactional integrity for the page.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ */
+ createPagesFromStream(container: string, blob: string, readStream: stream.Readable, rangeStart: number, rangeEnd: number, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+ createPagesFromStream(container: string, blob: string, readStream: stream.Readable, rangeStart: number, rangeEnd: number, callback: ErrorOrResult): void;
+
+ /**
+ * Lists page ranges. Lists all of the page ranges by default, or only the page ranges over a specific range of bytes if rangeStart and rangeEnd are specified.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {int} [options.rangeStart] The range start.
+ * @param {int} [options.rangeEnd] The range end.
+ * @param {string} [options.snapshotId] The snapshot identifier.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the page range information.
+ * `response` will contain information related to this operation.
+ */
+ listPageRanges(container: string, blob: string, options: BlobService.GetBlobRequestOptions, callback: ErrorOrResult): void;
+ listPageRanges(container: string, blob: string, callback: ErrorOrResult): void;
+
+ getPageRangesDiff(container: string, blob: string, previousSnapshotTime: string, options: BlobService.GetBlobRequestOptions, callback: ErrorOrResult): void;
+ getPageRangesDiff(container: string, blob: string, previousSnapshotTime: string, callback: ErrorOrResult): void;
+
+ /**
+ * Clears a range of pages.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {int} rangeStart The range start.
+ * @param {int} rangeEnd The range end.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ clearPageRange(container: string, blob: string, rangeStart: number, rangeEnd: number, options: BlobService.BlobRequestOptions, callback: ErrorOrResponse): void;
+ clearPageRange(container: string, blob: string, rangeStart: number, rangeEnd: number, callback: ErrorOrResponse): void;
+
+ /**
+ * Resizes a page blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {String} size The size of the page blob, in bytes.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The blob lease identifier.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ resizePageBlob(container: string, blob: string, size: number, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+ resizePageBlob(container: string, blob: string, size: number, callback: ErrorOrResult): void;
+
+ /**
+ * Sets the page blob's sequence number.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {SequenceNumberAction} sequenceNumberAction A value indicating the operation to perform on the sequence number.
+ * The allowed values are defined in azure.BlobUtilities.SequenceNumberAction.
+ * @param {string} sequenceNumber The sequence number. The value of the sequence number must be between 0 and 2^63 - 1.
+ * Set this parameter to null if this operation is an increment action.
+ * @param {Object} [options] The request options.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ setPageBlobSequenceNumber(container: string, blob: string, sequenceNumberAction: string, sequenceNumber: number, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+ setPageBlobSequenceNumber(container: string, blob: string, sequenceNumberAction: string, sequenceNumber: number, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a new block blob or updates the content of an existing block blob.
+ * Updating an existing block blob overwrites any existing metadata on the blob.
+ * Partial updates are not supported with Put Blob; The content of the existing blob is overwritten with the content of the new blob.
+ * To perform a partial update of the content of a block blob, use the Put Block List operation.
+ * Calling Put Blob to create a page blob only initializes the blob. To add content to a page blob, call the Put Page operation.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} localFileName The local path to the file to be uploaded.
+ * @param {Object} [options] The request options.
+ * @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+ * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ */
+ createBlockBlobFromLocalFile(container: string, blob: string, localFileName: string, options: BlobService.CreateBlockBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createBlockBlobFromLocalFile(container: string, blob: string, localFileName: string, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Creates a new block blob. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * (Only available in the JavaScript Client Library for Browsers)
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} browserFile The File object to be uploaded created by HTML File API.
+ * @param {Object} [options] The request options.
+ * @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+ * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ */
+ createBlockBlobFromBrowserFile(container: string, blob: string, browserFile: Object, options: BlobService.CreateBlockBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createBlockBlobFromBrowserFile(container: string, blob: string, browserFile: Object, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads a block blob from a stream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param (Stream) stream Stream to the data to store.
+ * @param {int} streamLength The length of the stream to upload.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ createBlockBlobFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads a block blob from a stream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param (Stream) stream Stream to the data to store.
+ * @param {int} streamLength The length of the stream to upload.
+ * @param {Object} [options] The request options.
+ * @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+ * @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+ * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ createBlockBlobFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, options: BlobService.CreateBlockBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads a block blob from a text string.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string|object} text The blob text, as a string or in a Buffer.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ createBlockBlobFromText(container: string, blob: string, text: string | Buffer, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): void;
+ createBlockBlobFromText(container: string, blob: string, text: string | Buffer, callback: ErrorOrResult): void;
+
+ /**
+ * Provides a stream to write to a block blob.
+ * Please note the `Stream` returned by this API should be used with piping.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {int} [options.blockSize] The size of each block. Maximum is 100MB.
+ * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {string} [options.transactionalContentMD5] The MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {int} [options.parallelOperationThreadCount] The number of parallel operations that may be performed when uploading.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs and true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ * @return {Writable} A Node.js Writable stream.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToBlockBlob(containerName, blobName, { blockIdPrefix: 'block' }));
+ */
+ createWriteStreamToBlockBlob(container: string, blob: string, options: BlobService.CreateBlockBlobRequestOptions, callback?: ErrorOrResult): stream.Writable;
+ createWriteStreamToBlockBlob(container: string, blob: string, callback?: ErrorOrResult): stream.Writable;
+
+ /**
+ * Creates a new block to be committed as part of a blob.
+ *
+ * @this {BlobService}
+ * @param {string} blockId The block identifier.
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Readable} readStream The Node.js Readable stream.
+ * @param {int} streamLength The stream length.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ createBlockFromStream(blockId: string, container: string, blob: string, readStream: stream.Readable, streamLength: number, options: BlobService.BlobRequestOptions, callback: ErrorOrResponse): void;
+ createBlockFromStream(blockId: string, container: string, blob: string, readStream: stream.Readable, streamLength: number, callback: ErrorOrResponse): void;
+
+ /**
+ * Creates a new block to be committed as part of a blob.
+ *
+ * @this {BlobService}
+ * @param {string} blockId The block identifier.
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string|buffer} content The block content.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ createBlockFromText(blockId: string, container: string, blob: string, content: string | Buffer, options: BlobService.BlobRequestOptions, callback: ErrorOrResponse): void;
+ createBlockFromText(blockId: string, container: string, blob: string, content: string | Buffer, callback: ErrorOrResponse): void;
+
+ /**
+ * Creates a new block to be committed as part of a blob from an URL of an Azure blob or file.
+ *
+ * @this {BlobService}
+ * @param {string} blockId The block identifier.
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} sourceURL The URL of the source data.
+ * It can point to any Azure Blob or File, that is either public or has a shared access signature attached.
+ * @param {int} sourceRangeStart The start of the range of bytes(inclusive) that has to be taken from the copy source.
+ * @param {int} sourceRangeEnd The end of the range of bytes(inclusive) that has to be taken from the copy source.
+ * @param {object} [options] The request options.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ createBlockFromURL(blockId: string, container: string, blob: string, sourceURL: string, sourceRangeStart: number, sourceRangeEnd: number, options: BlobService.CreateBlockRequestOptions, callback: ErrorOrResponse): void;
+ createBlockFromURL(blockId: string, container: string, blob: string, sourceURL: string, sourceRangeStart: number, sourceRangeEnd: number, callback: ErrorOrResponse): void;
+
+ /**
+ * Writes a blob by specifying the list of block IDs that make up the blob.
+ * In order to be written as part of a blob, a block must have been successfully written to the server in a prior
+ * createBlock operation.
+ * Note: If no valid list is specified in the blockList parameter, blob would be updated with empty content,
+ * i.e. existing blocks in the blob will be removed, this behavior is kept for backward compatibility consideration.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} blockList The wrapper for block ID list contains block IDs that make up the blob.
+ * Three kinds of list are provided, please choose one to use according to requirement.
+ * For more background knowledge, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/put-block-list
+ * @param {string[]} [blockList.LatestBlocks] The list contains block IDs that make up the blob sequentially.
+ * All the block IDs in this list will be specified within Latest element.
+ * Choose this list to contain block IDs indicates that the Blob service should first search
+ * the uncommitted block list, and then the committed block list for the named block.
+ * @param {string[]} [blockList.CommittedBlocks] The list contains block IDs that make up the blob sequentially.
+ * All the block IDs in this list will be specified within Committed element.
+ * Choose this list to contain block IDs indicates that the Blob service should only search
+ * the committed block list for the named block.
+ * @param {string[]} [blockList.UncommittedBlocks] The list contains block IDs that make up the blob sequentially.
+ * All the block IDs in this list will be specified within Uncommitted element.
+ * Choose this list to contain block IDs indicates that the Blob service should only search
+ * the uncommitted block list for the named block.
+ * @param {Object} [options] The request options.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the blocklist information.
+ * `response` will contain information related to this operation.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * blobService.createBlockFromText("sampleBlockName", containerName, blobName, "sampleBlockContent", function(error) {
+ * assert.equal(error, null);
+ * // In this example, LatestBlocks is used, we hope the Blob service first search
+ * // the uncommitted block list, and then the committed block list for the named block "sampleBlockName",
+ * // and thus make sure the block is with latest content.
+ * blobService.commitBlocks(containerName, blobName, { LatestBlocks: ["sampleBlockName"] }, function(error) {
+ * assert.equal(error, null);
+ * });
+ * });
+ */
+ commitBlocks(container: string, blob: string, blockList: BlobService.PutBlockListRequest, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): void;
+ commitBlocks(container: string, blob: string, blockList: BlobService.PutBlockListRequest, callback: ErrorOrResult): void;
+
+ /**
+ * Retrieves the list of blocks that have been uploaded as part of a block blob.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {BlockListFilter} blocklisttype The type of block list to retrieve.
+ * @param {Object} [options] The request options.
+ * @param {string} [options.snapshotId] The source blob snapshot identifier.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * the blocklist information.
+ * `response` will contain information related to this operation.
+ */
+ listBlocks(container: string, blob: string, blocklisttype: string, options: BlobService.BlobRequestOptions, callback: ErrorOrResult): void;
+ listBlocks(container: string, blob: string, blocklisttype: string, callback: ErrorOrResult): void;
+
+ /**
+ * Generate a random block id prefix
+ */
+ generateBlockIdPrefix(): string;
+
+ /**
+ * Get a block id according to prefix and block number
+ */
+ getBlockId(prefix: string, number: number | string): string;
+
+ /**
+ * Creates an empty append blob. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResponse} callback `error` will contain information
+ * if an error occurs; otherwise
+ * `response` will contain information related to this operation.
+ */
+ createOrReplaceAppendBlob(container: string, blob: string, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResponse): void;
+ createOrReplaceAppendBlob(container: string, blob: string, callback: ErrorOrResponse): void;
+
+ /**
+ * Creates a new append blob from a local file. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * If you want to append data to an already existing blob, please look at appendFromLocalFile.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} localFileName The local path to the file to be uploaded.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ createAppendBlobFromLocalFile(container: string, blob: string, localFileName: string, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createAppendBlobFromLocalFile(container: string, blob: string, localFileName: string, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Creates a new append blob from an HTML File object. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * If you want to append data to an already existing blob, please look at appendFromBrowserFile.
+ * (Only available in the JavaScript Client Library for Browsers)
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} browserFile The File object to be uploaded created by HTML File API.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 ahash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ */
+ createAppendBlobFromBrowserFile(container: string, blob: string, browserFile: Object, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createAppendBlobFromBrowserFile(container: string, blob: string, browserFile: Object, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads an append blob from a stream. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * If you want to append data to an already existing blob, please look at appendFromStream.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param (Stream) stream Stream to the data to store.
+ * @param {int} streamLength The length of the stream to upload.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ createAppendBlobFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ createAppendBlobFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Uploads an append blob from a text string. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * If you want to append data to an already existing blob, please look at appendFromText.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string|object} text The blob text, as a string or in a Buffer.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ createAppendBlobFromText(container: string, blob: string, text: string | Buffer, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): void;
+ createAppendBlobFromText(container: string, blob: string, text: string | Buffer, callback: ErrorOrResult): void;
+
+ /**
+ * Provides a stream to write to a new append blob. If the blob already exists on the service, it will be overwritten.
+ * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * Please note the `Stream` returned by this API should be used with piping.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs and true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ * @return {Writable} A Node.js Writable stream.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToAppendBlob(containerName, blobName));
+ */
+ createWriteStreamToNewAppendBlob(container: string, blob: string, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): stream.Writable;
+ createWriteStreamToNewAppendBlob(container: string, blob: string, callback: ErrorOrResult): stream.Writable;
+
+ /**
+ * Provides a stream to write to an existing append blob. Assumes that the blob exists.
+ * If it does not, please create the blob using createAppendBlob before calling this method or use createWriteStreamToNewAppendBlob.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * Please note the `Stream` returned by this API should be used with piping.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads.
+ * The default value is false for page blobs and true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ * @return {Writable} A Node.js Writable stream.
+ * @example
+ * var azure = require('azure-storage');
+ * var blobService = azure.createBlobService();
+ * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToAppendBlob(containerName, blobName));
+ */
+ createWriteStreamToExistingAppendBlob(container: string, blob: string, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): stream.Writable;
+ createWriteStreamToExistingAppendBlob(container: string, blob: string, callback: ErrorOrResult): stream.Writable;
+
+ /**
+ * Appends to an append blob from a local file. Assumes the blob already exists on the service.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string} localFileName The local path to the file to be uploaded.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ appendFromLocalFile(container: string, blob: string, localFileName: string, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ appendFromLocalFile(container: string, blob: string, localFileName: string, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Appends to an append blob from an HTML File object. Assumes the blob already exists on the service.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ * (Only available in the JavaScript Client Library for Browsers)
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Object} browserFile The File object to be uploaded created by HTML File API.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.clientRequestTimeoutInMs] The timeout of client requests, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `[result]{@link BlobResult}` will contain
+ * the blob information.
+ * `response` will contain information related to this operation.
+ * @return {SpeedSummary}
+ */
+ appendFromBrowserFile(container: string, blob: string, browserFile: Object, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+ appendFromBrowserFile(container: string, blob: string, browserFile: Object, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;
+
+ /**
+ * Appends to an append blob from a stream. Assumes the blob already exists on the service.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param (Stream) stream Stream to the data to store.
+ * @param {int} streamLength The length of the stream to upload.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {SpeedSummary} [options.speedSummary] The download tracker objects.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback The callback function.
+ * @return {SpeedSummary}
+ */
+ appendFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;;
+ appendFromStream(container: string, blob: string, stream: stream.Readable, streamLength: number, callback: ErrorOrResult): common.streams.speedsummary.SpeedSummary;;
+
+ /**
+ * Appends to an append blob from a text string. Assumes the blob already exists on the service.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string|object} text The blob text, as a string or in a Buffer.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {string} [options.leaseId] The lease identifier.
+ * @param {Object} [options.metadata] The metadata key/value pairs.
+ * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs.
+ * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions.
+ * @param {Object} [options.contentSettings] The content settings of the blob.
+ * @param {string} [options.contentSettings.contentType] The MIME content type of the blob. The default type is application/octet-stream.
+ * @param {string} [options.contentSettings.contentEncoding] The content encodings that have been applied to the blob.
+ * @param {string} [options.contentSettings.contentLanguage] The natural languages used by this resource.
+ * @param {string} [options.contentSettings.cacheControl] The Blob service stores this value but does not use or modify it.
+ * @param {string} [options.contentSettings.contentDisposition] The blob's content disposition.
+ * @param {string} [options.contentSettings.contentMD5] The blob's MD5 hash.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ appendFromText(container: string, blob: string, text: string, options: BlobService.CreateBlobRequestOptions, callback: ErrorOrResult): void;
+ appendFromText(container: string, blob: string, text: string, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a new block from a read stream to be appended to an append blob.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {Readable} readStream The Node.js Readable stream.
+ * @param {int} streamLength The stream length.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to.
+ * @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ appendBlockFromStream(container: string, blob: string, readStream: stream.Readable, streamLength: number, options: BlobService.AppendBlobRequestOptions, callback: ErrorOrResult): void;
+ appendBlockFromStream(container: string, blob: string, readStream: stream.Readable, streamLength: number, callback: ErrorOrResult): void;
+
+ /**
+ * Creates a new block from a text to be appended to an append blob.
+ * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks.
+ * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you.
+ *
+ * @this {BlobService}
+ * @param {string} container The container name.
+ * @param {string} blob The blob name.
+ * @param {string|object} content The block text, as a string or in a Buffer.
+ * @param {Object} [options] The request options.
+ * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry.
+ * @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to.
+ * @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number.
+ * @param {string} [options.leaseId] The target blob lease identifier.
+ * @param {string} [options.transactionalContentMD5] An MD5 hash of the block content. This hash is used to verify the integrity of the block during transport.
+ * @param {AccessConditions} [options.accessConditions] The access conditions.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise `result` will contain
+ * information about the blob.
+ * `response` will contain information related to this operation.
+ */
+ appendBlockFromText(container: string, blob: string, content: string | Buffer, options: BlobService.AppendBlobRequestOptions, callback: ErrorOrResult): void;
+ appendBlockFromText(container: string, blob: string, content: string | Buffer, callback: ErrorOrResult): void;
+
+ /**
+ * The callback for {BlobService~getBlobToText}.
+ * @typedef {function} BlobService~blobToText
+ * @param {Object} error If an error occurs, the error information.
+ * @param {string} text The text returned from the blob.
+ * @param {Object} blockBlob Information about the blob.
+ * @param {Object} response Information related to this operation.
+ */
+ static SpeedSummary: common.streams.speedsummary.SpeedSummary;
+ }
+ export module BlobService {
+ export interface CreateContainerOptions extends common.RequestOptions {
+ metadata?: Map;
+ publicAccessLevel?: string;
+ }
+
+ export interface ListContainerOptions extends common.RequestOptions {
+ maxResults?: number;
+ include?: string;
+ }
+
+ export interface ConditionalRequestOption extends common.RequestOptions {
+ accessConditions?: AccessConditions;
+ }
+
+ export interface ContainerOptions extends ConditionalRequestOption {
+ leaseId?: string;
+ }
+
+ export interface ContainerAclOptions extends ContainerOptions {
+ publicAccessLevel?: string;
+ }
+
+ export interface LeaseRequestOptions extends ConditionalRequestOption {
+ }
+
+ export interface AcquireLeaseRequestOptions extends LeaseRequestOptions {
+ leaseDuration?: number;
+ proposedLeaseId?: string;
+ }
+
+ export interface BreakLeaseRequestOptions extends LeaseRequestOptions {
+ leaseBreakPeriod?: number;
+ }
+
+ export interface ListBlobsSegmentedRequestOptions extends common.RequestOptions {
+ /**
+ * {string} Delimiter, i.e. '/', for specifying folder hierarchy.
+ */
+ delimiter?: string;
+ /**
+ * {int} Specifies the maximum number of blobs to return per call to Azure ServiceClient. (maximum: 5000)
+ */
+ maxResults?: number;
+
+ /**
+ * {string} Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs'). Multiple values can be added separated with a comma (,)
+ */
+ include?: string;
+ }
+
+ export interface ListBlobPrefixesSegmentedRequestOptions extends ListBlobsSegmentedRequestOptions {}
+
+ export interface LeaseResult {
+ container: string;
+ blob: string;
+ id: string;
+ time: number;
+ etag: string;
+ lastModified: string;
+ }
+
+ export interface ListBlobsResult {
+ entries: BlobResult[];
+ continuationToken?: common.ContinuationToken;
+ }
+
+ export interface ListBlobDirectoriesResult {
+ entries: BlobDirectoryResult[];
+ continuationToken?: common.ContinuationToken;
+ }
+
+ export interface ContainerAclResult extends ContainerResult {
+ signedIdentifiers: {[key:string]: common.AccessPolicy}
+ }
+
+ export interface ContainerResult {
+ name: string;
+ publicAccessLevel: string;
+ etag: string;
+ lastModified: string;
+ hasImmutabilityPolicy: boolean;
+ hasLegalHold: boolean;
+ metadata?: { [key: string]: string; };
+ requestId?: string;
+ lease?: {
+ duration?: string;
+ status: string;
+ state: string;
+ };
+ exists?: boolean;
+ created?: boolean;
+ }
+
+ export interface ListContainerResult {
+ continuationToken: common.ContinuationToken;
+ entries: ContainerResult[];
+ }
+
+ export interface BlobDirectoryResult {
+ name: string;
+ }
+
+ export interface BlobResult {
+ name: string;
+ snapshot?: string;
+ deleted?: boolean;
+ container: string;
+ metadata?: { [key: string]: string; };
+ etag: string;
+ lastModified: string;
+ creationTime: string;
+ contentLength: string;
+ blobType: string;
+ accessTier?: string;
+ accessTierChangeTime?: string;
+ accessTierInferred?: boolean;
+ archiveStatus?: string;
+ isIncrementalCopy?: boolean;
+ requestId: string;
+ sequenceNumber?: string;
+ contentRange?: string;
+ committedBlockCount?: string;
+ serverEncrypted?: string;
+ deletedTime?: string;
+ remainingRetentionDays?: string;
+ appendOffset? : string;
+ contentSettings?: {
+ contentType?: string;
+ contentEncoding?: string;
+ contentLanguage?: string;
+ cacheControl?: string;
+ contentDisposition?: string;
+ contentMD5?: string;
+ }
+ lease?: {
+ id?: string;
+ status?: string;
+ state?: string;
+ duration?: string;
+ }
+ copy?: {
+ id?: string;
+ status?: string;
+ completionTime?: string;
+ statusDescription?: string;
+ destinationSnapshot?: string;
+ progress?: string;
+ source?: string;
+ },
+ exists?: boolean;
+ created?: boolean;
+ }
+
+ export interface CreatePageBlobOptions {
+ metadata?: Object;
+ leaseId?: string;
+ transactionalContentMD5?: string;
+ blobTier?: string;
+ contentSettings?: {
+ contentType?: string;
+ contentEncoding?: string;
+ contentLanguage?: string;
+ cacheControl?: string;
+ contentDisposition?: string;
+ contentMD5?: string;
+ }
+ sequenceNumber?: string;
+ accessConditions?: AccessConditions;
+ locationMode?: StorageUtilities.LocationMode;
+ timeoutIntervalInMs?: number;
+ clientRequestTimeoutInMs?: number;
+ maximumExecutionTimeInMs?: number;
+ useNagleAlgorithm?: boolean;
+ }
+
+ export interface BlobRequestOptions extends ConditionalRequestOption {
+ snapshotId?: string; // TODO: Not valid for most write requests...
+ leaseId?: string;
+ }
+
+ export interface CreateBlockRequestOptions extends BlobRequestOptions {
+ transactionalContentMD5?: string;
+ }
+
+ export interface AppendBlobRequestOptions extends ConditionalRequestOption, BlobRequestOptions {
+ absorbConditionalErrorsOnRetry?: boolean;
+ maxBlobSize?: number;
+ appendPosition?: number;
+ }
+
+ export interface SetBlobPropertiesRequestOptions extends BlobRequestOptions {
+ contentType?: string;
+ contentEncoding?: string;
+ contentLanguage?: string;
+ contentMD5?: string;
+ cacheControl?: string;
+ contentDisposition?: string;
+ }
+
+ export interface GetBlobRequestOptions extends BlobRequestOptions {
+ speedSummary?: common.streams.speedsummary.SpeedSummary;
+ parallelOperationThreadCount?: number;
+ rangeStart?: number;
+ rangeEnd?: number;
+ useTransactionalMD5?: boolean;
+ disableContentMD5Validation?: boolean;
+ }
+
+ export interface CopyBlobRequestOptions extends BlobRequestOptions {
+ metadata?: { [k: string]: string; };
+ sourceLeaseId?: string;
+ accessConditions?: AccessConditions;
+ sourceAccessConditions?: AccessConditions;
+ isIncrementalCopy?: boolean;
+ }
+
+ export interface DeleteBlobRequestOptions extends BlobRequestOptions {
+ deleteSnapshots?: string;
+ }
+
+ export interface CreateBlobRequestOptions extends BlobRequestOptions {
+ speedSummary?: common.streams.speedsummary.SpeedSummary;
+ parallelOperationThreadCount?: number;
+ useTransactionalMD5?: boolean;
+ blockIdPrefix?: string;
+ metadata?: {[k: string]: string};
+ storeBlobContentMD5?: boolean;
+ transactionalContentMD5?: string;
+ contentSettings?: {
+ contentType?: string;
+ contentEncoding?: string;
+ contentLanguage?: string;
+ cacheControl?: string;
+ contentDisposition?: string;
+ contentMD5?: string;
+ }
+ }
+
+ export interface CreateBlockBlobRequestOptions extends CreateBlobRequestOptions {
+ blockSize?: number;
+ }
+
+ export interface BlobToText {
+ (error: Error, text: string, result: BlobResult, response: ServiceResponse): void
+ }
+
+ export interface ListPageRangesRequestOptions extends common.RequestOptions {
+ rangeStart?: number;
+ rangeEnd?: number;
+ }
+
+ export interface BlockListResult {
+ CommittedBlocks?: Block[];
+ UncommittedBlocks?: Block[];
+ }
+
+ export interface PutBlockListRequest {
+ LatestBlocks?: string[];
+ CommittedBlocks?: string[];
+ UncommittedBlocks?: string[];
+ }
+
+ export interface Block {
+ Name?: string;
+ Size?: string;
+ }
+ }
+ }
+
+ // ###########################
+ // ./services/blob/blobutilities
+ // ###########################
+ module blobutilities {
+ export var BlobUtilities: {
+ SharedAccessPermissions: {
+ READ: string;
+ WRITE: string;
+ DELETE: string;
+ LIST: string;
+ };
+ BlobListingDetails: {
+ SNAPSHOTS: string;
+ METADATA: string;
+ UNCOMMITTED_BLOBS: string;
+ COPY: string;
+ DELETED: string;
+ };
+ SnapshotDeleteOptions: {
+ SNAPSHOTS_ONLY: string;
+ BLOB_AND_SNAPSHOTS: string;
+ };
+ BlockListFilter: {
+ ALL: string;
+ COMMITTED: string;
+ UNCOMMITTED: string;
+ };
+ BlobContainerPublicAccessType: {
+ OFF: string;
+ CONTAINER: string;
+ BLOB: string;
+ };
+ SequenceNumberAction: {
+ MAX: string;
+ UPDATE: string;
+ INCREMENT: string;
+ };
+ BlobTier: {
+ PremiumPageBlobTier: {
+ P4: string;
+ P6: string;
+ P10: string;
+ P20: string;
+ P30: string;
+ P40: string;
+ P50: string;
+ P60: string;
+ };
+ StandardBlobTier: {
+ HOT: string;
+ COOL: string;
+ ARCHIVE: string;
+ };
+ }
+ };
+ }
+ }
+
+ module queue {
+ export class QueueService extends StorageServiceClient {
+ /**
+ * @property {boolean} QueueService#queueMessagEncoder
+ * @defaultvalue {boolean} true
+ * A flag indicating whether the message should be base-64 encoded. Default is true.
+ */
+ messageEncoder: QueueMessageEncoder;
+
+ /**
+ * Creates a new QueueService object.
+ *
+ * The QueueService class is used to perform operations on the Microsoft Azure Queue Service.
+ *
+ * For more information on using the Queue Service, as well as task focused information on using it from a Node.js application, see
+ * [How to Use the Queue Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-queues/).
+ * The following defaults can be set on the Queue service.
+ * messageEncoder The message encoder to specify how QueueService encodes and decodes the queue message. Default is `[TextXmlQueueMessageEncoder]{@link TextXmlQueueMessageEncoder}`.
+ * defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Queue service.
+ * defaultClientRequestTimeoutInMs The default timeout of client requests, in milliseconds, to use for the request made via the Queue service.
+ * defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Queue service.
+ * defaultLocationMode The default location mode for requests made via the Queue service.
+ * useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Queue service; true to use the
+ * Nagle algorithm; otherwise, false. The default value is false.
+ * enableGlobalHttpAgent Determines whether global HTTP(s) agent is enabled; true to use Global HTTP(s) agent; otherwise, false to use
+ * http(s).Agent({keepAlive:true}).
+ * If no connection string or storageaccount and storageaccesskey are provided,
+ * the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
+ * @augments {StorageServiceClient}
+ * @constructor QueueService
+ * @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+ * @param {string} [storageAccessKey] The storage access key.
+ * @param {string|object} [host] The host address. To define primary only, pass a string.
+ * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host.
+ * @param {string} [sasToken] The Shared Access Signature token.
+ * @param {string} [endpointSuffix] The endpoint suffix.
+ */
+ constructor(storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string, endpointSuffix?: string);
+
+ /**
+ * Associate a filtering operation with this QueueService. Filtering operations
+ * can include logging, automatically retrying, etc. Filter operations are objects
+ * that implement a method with the signature:
+ *
+ * "function handle (requestOptions, next)".
+ *
+ * After doing its preprocessing on the request options, the method needs to call
+ * "next" passing a callback with the following signature:
+ * signature:
+ *
+ * "function (returnObject, finalCallback, next)"
+ *
+ * In this callback, and after processing the returnObject (the response from the
+ * request to the server), the callback needs to either invoke next if it exists to
+ * continue processing other filters or simply invoke finalCallback otherwise to end
+ * up the service invocation.
+ *
+ * @function QueueService#withFilter
+ * @param {Object} filter The new filter object.
+ * @return {QueueService} A new service client with the filter applied.
+ */
+ withFilter(newFilter: common.filters.IFilter): QueueService;
+
+ /**
+ * Gets the service stats for a storage account’s Queue service.
+ *
+ * @function QueueService#getServiceStats
+ *
+ * @this {QueueService}
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise, `result`
+ * will contain the stats and `response`
+ * will contain information related to this operation.
+ */
+ getServiceStats(options: common.RequestOptions, callback: ErrorOrResult): void;
+
+ /**
+ * Gets the service stats for a storage account’s Queue service.
+ *
+ * @function QueueService#getServiceStats
+ *
+ * @this {QueueService}
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise, `result`
+ * will contain the stats and `response`
+ * will contain information related to this operation.
+ */
+ getServiceStats(callback: ErrorOrResult): void;
+
+ /**
+ * Gets the properties of a storage account’s Queue service, including Microsoft Azure Storage Analytics.
+ *
+ * @this {QueueService}
+ * @param {Object} [options] The request options.
+ * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to.
+ * Please see StorageUtilities.LocationMode for the possible values.
+ * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request.
+ * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request.
+ * The maximum execution time interval begins at the time that the client begins building the request. The maximum
+ * execution time is checked intermittently while performing requests, and before executing retries.
+ * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit.
+ * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false.
+ * The default value is false.
+ * @param {errorOrResult} callback `error` will contain information
+ * if an error occurs; otherwise, `errorOrResult`
+ * will contain the properties and `response`
+ * will contain information related to this operation.
+ */
+ getServiceProperties(options: common.RequestOptions, callback?: ErrorOrResult