├── .eslintrc ├── .gitignore ├── Contributing.md ├── Gruntfile.js ├── LICENSE ├── changelog.md ├── documentclientwrapper.js ├── nodejspromisessdk.proj ├── package.json ├── readme.md └── test ├── _testConfig.js ├── readme.md └── test.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [ 4 | 2, 5 | 4 6 | ], 7 | "quotes": [ 8 | 2, 9 | "double" 10 | ], 11 | "linebreak-style": [ 12 | 2, 13 | "windows" 14 | ], 15 | "semi": [ 16 | 2, 17 | "always" 18 | ], 19 | "curly": 0, 20 | "dot-notation": 0, 21 | "eol-last": 0, 22 | "no-redeclare": 0, 23 | "no-shadow": 0, 24 | "no-undef": 0, 25 | "no-underscore-dangle": 0, 26 | "no-unused-vars": 0 27 | }, 28 | "env": { 29 | "node": true 30 | } 31 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | generateDocs.cmd 2 | runtests.cmd 3 | nodejspromisessdk.proj 4 | 5 | config.js 6 | 7 | 8 | ################# 9 | ## Eclipse 10 | ################# 11 | 12 | *.pydevproject 13 | .project 14 | .metadata 15 | bin/ 16 | obj/ 17 | tmp/ 18 | *.tmp 19 | *.bak 20 | *.swp 21 | *~.nib 22 | local.properties 23 | .classpath 24 | .settings/ 25 | .loadpath 26 | 27 | # External tool builders 28 | .externalToolBuilders/ 29 | 30 | # Locally stored "Eclipse launch configurations" 31 | *.launch 32 | 33 | # CDT-specific 34 | .cproject 35 | 36 | # PDT-specific 37 | .buildpath 38 | 39 | 40 | ################# 41 | ## Visual Studio 42 | ################# 43 | 44 | ## Ignore Visual Studio temporary files, build results, and 45 | ## files generated by popular Visual Studio add-ons. 46 | 47 | # User-specific files 48 | *.suo 49 | *.user 50 | *.sln.docstates 51 | 52 | # Build results 53 | 54 | [Dd]ebug/ 55 | [Rr]elease/ 56 | x64/ 57 | build/ 58 | [Bb]in/ 59 | [Oo]bj/ 60 | 61 | # MSTest test Results 62 | [Tt]est[Rr]esult*/ 63 | [Bb]uild[Ll]og.* 64 | 65 | *_i.c 66 | *_p.c 67 | *.ilk 68 | *.meta 69 | *.obj 70 | *.pch 71 | *.pdb 72 | *.pgc 73 | *.pgd 74 | *.rsp 75 | *.sbr 76 | *.tlb 77 | *.tli 78 | *.tlh 79 | *.tmp 80 | *.tmp_proj 81 | *.log 82 | *.vspscc 83 | *.vssscc 84 | .builds 85 | *.pidb 86 | *.log 87 | *.scc 88 | 89 | # Visual C++ cache files 90 | ipch/ 91 | *.aps 92 | *.ncb 93 | *.opensdf 94 | *.sdf 95 | *.cachefile 96 | 97 | # Visual Studio profiler 98 | *.psess 99 | *.vsp 100 | *.vspx 101 | 102 | # Guidance Automation Toolkit 103 | *.gpState 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper*/ 107 | *.[Rr]e[Ss]harper 108 | 109 | # TeamCity is a build add-in 110 | _TeamCity* 111 | 112 | # DotCover is a Code Coverage Tool 113 | *.dotCover 114 | 115 | # NCrunch 116 | *.ncrunch* 117 | .*crunch*.local.xml 118 | 119 | # Installshield output folder 120 | [Ee]xpress/ 121 | 122 | # DocProject is a documentation generator add-in 123 | DocProject/buildhelp/ 124 | DocProject/Help/*.HxT 125 | DocProject/Help/*.HxC 126 | DocProject/Help/*.hhc 127 | DocProject/Help/*.hhk 128 | DocProject/Help/*.hhp 129 | DocProject/Help/Html2 130 | DocProject/Help/html 131 | 132 | # Click-Once directory 133 | publish/ 134 | 135 | # Publish Web Output 136 | *.Publish.xml 137 | *.pubxml 138 | 139 | # NuGet Packages Directory 140 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 141 | #packages/ 142 | 143 | # Windows Azure Build Output 144 | csx 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.[Pp]ublish.xml 159 | *.pfx 160 | *.publishsettings 161 | 162 | # RIA/Silverlight projects 163 | Generated_Code/ 164 | 165 | # Backup & report files from converting an old project file to a newer 166 | # Visual Studio version. Backup files are not needed, because we have git ;-) 167 | _UpgradeReport_Files/ 168 | Backup*/ 169 | UpgradeLog*.XML 170 | UpgradeLog*.htm 171 | 172 | # SQL Server files 173 | App_Data/*.mdf 174 | App_Data/*.ldf 175 | 176 | ############# 177 | ## Windows detritus 178 | ############# 179 | 180 | # Windows image file caches 181 | Thumbs.db 182 | ehthumbs.db 183 | 184 | # Folder config file 185 | Desktop.ini 186 | 187 | # Recycle Bin used on file shares 188 | $RECYCLE.BIN/ 189 | 190 | # Mac crap 191 | .DS_Store 192 | 193 | 194 | ############# 195 | ## Python 196 | ############# 197 | 198 | *.py[cod] 199 | 200 | # Packages 201 | *.egg 202 | *.egg-info 203 | dist/ 204 | build/ 205 | eggs/ 206 | parts/ 207 | var/ 208 | sdist/ 209 | develop-eggs/ 210 | .installed.cfg 211 | 212 | # Installer logs 213 | pip-log.txt 214 | 215 | # Unit test / coverage reports 216 | .coverage 217 | .tox 218 | 219 | #Translations 220 | *.mo 221 | 222 | #Mr Developer 223 | .mr.developer.cfg 224 | 225 | ############# 226 | ## Node.js 227 | ############# 228 | 229 | # Logs 230 | logs 231 | 232 | # Runtime data 233 | pids 234 | *.pid 235 | *.seed 236 | 237 | # Directory for instrumented libs generated by jscoverage/JSCover 238 | lib-cov 239 | 240 | # Coverage directory used by tools like istanbul 241 | coverage 242 | 243 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 244 | .grunt 245 | 246 | # node-waf configuration 247 | .lock-wscript 248 | 249 | # Compiled binary addons (http://nodejs.org/api/addons.html) 250 | build/Release 251 | 252 | # Dependency directory 253 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 254 | node_modules 255 | 256 | # Dependency sub-directories for samples 257 | **/node_nodules/ 258 | 259 | *.dat 260 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | Please read the contributing guidelines from the [Azure Team](https://azure.microsoft.com/en-us/blog/simple-contribution-to-azure-documentation-and-sdk/) 2 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | Copyright (c) 2014 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | "use strict"; 25 | 26 | module.exports = function (grunt) { 27 | require("time-grunt")(grunt); 28 | // Load grunt tasks automatically 29 | require("load-grunt-tasks")(grunt); 30 | 31 | grunt.initConfig({ 32 | eslint: { 33 | src: ["lib/*.js", "test/*.js"], 34 | options: { 35 | configFile: ".eslintrc" 36 | } 37 | } 38 | }); 39 | 40 | grunt.registerTask("lint", ["eslint"]); 41 | grunt.registerTask("default", "lint"); 42 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2014 Microsoft Corporation 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## Changes in 1.6.0 : ## 2 | 3 | - Add support for partitioned collections 4 | 5 | 6 | ## Changes in 1.5.0 : ## 7 | 8 | - Added client side partitioning support 9 | 10 | ## Changes in 1.4.0 : ## 11 | 12 | - Add upsert support 13 | 14 | ## Changes in 1.3.0 : ## 15 | 16 | - Skipped to bring version numbers in alignment with other SDKs 17 | 18 | ## Changes in 1.2.2 : ## 19 | 20 | - Move to seperate repository 21 | 22 | ## Changes in 1.2.0 : ## 23 | 24 | - Added support for GeoSpatial index. 25 | - Validates id property for all resources. Ids for resources cannot contain ?, /, #, \\, characters or end with a space. 26 | - Adds new header "index transformation progress" to ResourceResponse. 27 | 28 | ## Changes in 1.1.0 : ## 29 | 30 | - Implements V2 indexing policy 31 | 32 | ## Changes in 1.0.3 : ## 33 | 34 | - Issue [#40] (https://github.com/Azure/azure-documentdb-node/issues/40) - Implemented eslint and grunt configurations in the core and promise SDK 35 | 36 | ## Changes in 1.0.2 : ## 37 | 38 | - Resolved issue [#45](https://github.com/Azure/azure-documentdb-node/issues/45) - promises wrapper does not include header with error. 39 | 40 | ## Changes in 1.0.1 : ## 41 | 42 | - Implemented ability to query for conflicts by adding readConflicts, readConflictAsync, queryConflicts; 43 | - Updated API documentation 44 | - Resolved issue [#41](https://github.com/Azure/azure-documentdb-node/issues/41) - client.createDocumentAsync error 45 | -------------------------------------------------------------------------------- /documentclientwrapper.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | Copyright (c) 2014 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | "use strict"; 25 | 26 | var Base = require("documentdb").Base 27 | , DocumentClient = require("documentdb").DocumentClient 28 | , DocumentBase = require("documentdb").DocumentBase 29 | , Q = require("q"); 30 | 31 | function addOrMergeHeadersForError(error, responseHeaders){ 32 | if (!error.responseHeaders) { 33 | error.responseHeaders = responseHeaders; 34 | } else { 35 | for (var headerIndex in responseHeaders) { 36 | if (!error.responseHeaders[headerIndex]) { 37 | error.responseHeaders[headerIndex] = responseHeaders[headerIndex]; 38 | } // else you lose it because we don't overwrite existing... 39 | } 40 | } 41 | } 42 | 43 | function createOperationPromise(contextObject, functionName, parentLink, body, options){ 44 | var deferred = Q.defer(); 45 | var cb = function (error, resource, responseHeaders) { 46 | if (error) { 47 | addOrMergeHeadersForError(error, responseHeaders); 48 | deferred.reject(error); 49 | } else { 50 | deferred.resolve({resource: resource, headers: responseHeaders}); 51 | } 52 | }; 53 | 54 | if (parentLink) { 55 | contextObject[functionName](parentLink, body, options, cb); 56 | } else { 57 | contextObject[functionName](body, options, cb); 58 | } 59 | 60 | return deferred.promise; 61 | } 62 | 63 | function upsertOperationPromise(contextObject, functionName, parentLink, body, options){ 64 | var deferred = Q.defer(); 65 | var cb = function (error, resource, responseHeaders) { 66 | if (error) { 67 | addOrMergeHeadersForError(error, responseHeaders); 68 | deferred.reject(error); 69 | } else { 70 | deferred.resolve({resource: resource, headers: responseHeaders}); 71 | } 72 | }; 73 | 74 | contextObject[functionName](parentLink, body, options, cb); 75 | 76 | return deferred.promise; 77 | } 78 | 79 | function deleteOperationPromise(contextObject, functionName, resourceLink, options){ 80 | var deferred = Q.defer(); 81 | contextObject[functionName](resourceLink, options, function (error, resource, responseHeaders) { 82 | if (error) { 83 | addOrMergeHeadersForError(error, responseHeaders); 84 | deferred.reject(error); 85 | } else { 86 | deferred.resolve({resource: resource, headers: responseHeaders}); 87 | } 88 | }); 89 | 90 | return deferred.promise; 91 | } 92 | 93 | function replaceOperationPromise(contextObject, functionName, resourceLink, newResource, options){ 94 | var deferred = Q.defer(); 95 | var callback = function (error, resource, responseHeaders) { 96 | if (error) { 97 | addOrMergeHeadersForError(error, responseHeaders); 98 | deferred.reject(error); 99 | } else { 100 | deferred.resolve({ resource: resource, headers: responseHeaders }); 101 | } 102 | }; 103 | 104 | if (options === undefined) { 105 | contextObject[functionName](resourceLink, newResource, callback); 106 | } else { 107 | contextObject[functionName](resourceLink, newResource, options, callback); 108 | } 109 | 110 | return deferred.promise; 111 | } 112 | 113 | function readOperationPromise(contextObject, functionName, resourceLink, options){ 114 | var deferred = Q.defer(); 115 | var callback = function (error, resource, responseHeaders) { 116 | if (error) { 117 | addOrMergeHeadersForError(error, responseHeaders); 118 | deferred.reject(error); 119 | } else { 120 | deferred.resolve({ resource: resource, headers: responseHeaders }); 121 | } 122 | }; 123 | 124 | if (options === undefined) { 125 | contextObject[functionName](resourceLink, callback); 126 | } else { 127 | contextObject[functionName](resourceLink, options, callback); 128 | } 129 | 130 | return deferred.promise; 131 | } 132 | 133 | function noParameterPromise(contextObject, functionName, resourceLink){ 134 | var deferred = Q.defer(); 135 | contextObject[functionName](resourceLink, function (error, resources, responseHeaders) { 136 | if (error) { 137 | addOrMergeHeadersForError(error, responseHeaders); 138 | deferred.reject(error); 139 | } else { 140 | deferred.resolve({result: resources, headers: responseHeaders}); 141 | } 142 | }); 143 | 144 | return deferred.promise; 145 | } 146 | 147 | function readFeedOperationPromise(contextObject, functionName, query, options, successFn) { 148 | var deferred = Q.defer(); 149 | contextObject[functionName](query, options, function (error, resources, responseHeaders) { 150 | if (error) { 151 | addOrMergeHeadersForError(error, responseHeaders); 152 | deferred.reject(error); 153 | } else { 154 | deferred.resolve(successFn(resources), responseHeaders); 155 | } 156 | }); 157 | 158 | return deferred.promise; 159 | } 160 | 161 | var QueryIteratorWrapper = Base.defineClass( 162 | /** 163 | * Provides a wrapper for all the functions of {@link QueryIterator} that uses the Q module promise API instead of the callback model. 164 | * @constructor QueryIteratorWrapper 165 | */ 166 | function (queryIterator) { 167 | this._innerQueryIterator = queryIterator; 168 | }, 169 | { 170 | /** 171 | * Execute a provided function once per feed element. 172 | * @memberof QueryIteratorWrapper 173 | * @instance 174 | * @param {callback} callback - Function to execute for each element. the function takes two parameters error, element. 175 | * Note: the last element the callback will be called on will be undefined. 176 | * If the callback explicitly returned false, the loop gets stopped. 177 | */ 178 | forEach: function (callback) { 179 | this._innerQueryIterator.forEach(callback); 180 | }, 181 | 182 | /** 183 | * Execute a provided function on the next element in the QueryIterator. 184 | * @memberof QueryIteratorWrapper 185 | * @instance 186 | * @Returns {Object} A promise object for the request completion. the onFulfilled callback is of type {@link FeedResponse} and onError callback is of type {@link ResponseError} 187 | */ 188 | toArrayAsync: function () { 189 | var deferred = Q.defer(); 190 | var that = this; 191 | this._innerQueryIterator.toArray(function (error, resources, responseHeaders) { 192 | if (error) { 193 | addOrMergeHeadersForError(error, responseHeaders); 194 | deferred.reject(error); 195 | } else { 196 | deferred.resolve({ feed: resources, headers: responseHeaders }); 197 | } 198 | }); 199 | 200 | return deferred.promise; 201 | }, 202 | 203 | /** 204 | * Gets the next element in the QueryIterator. 205 | * @memberof QueryIteratorWrapper 206 | * @instance 207 | * @Returns {Object} A promise object for the request completion. The onFulfilled callback is of type {@link ResourceResponse} and onError callback is of type {@link ResponseError} 208 | */ 209 | nextItemAsync: function () { 210 | var deferred = Q.defer(); 211 | var that = this; 212 | this._innerQueryIterator.nextItem(function (error, item, responseHeaders) { 213 | if (error) { 214 | addOrMergeHeadersForError(error, responseHeaders); 215 | deferred.reject(error); 216 | } else { 217 | deferred.resolve({ resource: item, headers: responseHeaders }); 218 | } 219 | }); 220 | 221 | return deferred.promise; 222 | }, 223 | 224 | /** 225 | * Retrieve the next batch of the feed and pass them as an array to a function 226 | * @memberof QueryIteratorWrapper 227 | * @instance 228 | * @Returns {Object} A promise object for the request completion. the onFulfilled callback is of type {@link FeedResponse} and onError callback is of type {@link ResponseError} 229 | */ 230 | executeNextAsync: function () { 231 | var deferred = Q.defer(); 232 | var that = this; 233 | this._innerQueryIterator.executeNext(function (error, resources, responseHeaders) { 234 | if (error) { 235 | addOrMergeHeadersForError(error, responseHeaders); 236 | deferred.reject(error); 237 | } else { 238 | deferred.resolve({ feed: resources, headers: responseHeaders }); 239 | } 240 | }); 241 | 242 | return deferred.promise; 243 | }, 244 | 245 | /** 246 | * Retrieve the current element on the QueryIterator. 247 | * @memberof QueryIteratorWrapper 248 | * @instance 249 | * @returns {Object} The current resource in the QueryIterator, undefined if there isn't. 250 | */ 251 | current: function () { 252 | return this._innerQueryIterator.current(); 253 | }, 254 | 255 | /** 256 | * Determine if there are still remaining resources to processs based on the value of the continuation token or the elements remaining on the current batch in the QueryIterator. 257 | * @memberof QueryIteratorWrapper 258 | * @instance 259 | * @returns {Boolean} true if there is other elements to process in the QueryIterator. 260 | */ 261 | hasMoreResults: function () { 262 | return this._innerQueryIterator.hasMoreResults(); 263 | }, 264 | 265 | /** 266 | * Reset the QueryIterator to the beginning and clear all the resources inside it 267 | * @memberof QueryIteratorWrapper 268 | * @instance 269 | */ 270 | reset: function () { 271 | return this._innerQueryIterator.reset(); 272 | } 273 | } 274 | ); 275 | 276 | var DocumentClientWrapper = Base.defineClass( 277 | /** 278 | * Provides a wrapper for all the functions of {@link DocumentClient} that uses the Q module promise API instead of the callback model. 279 | * @constructor DocumentClientWrapper 280 | * @param {string} urlConnection - The service endpoint to use to create the client. 281 | * @param {object} auth - An object that is used for authenticating requests and must contains one of the options 282 | * @param {string} [auth.masterkey] - The authorization master key to use to create the client. 283 | * @param {Object} [auth.resourceTokens] - An object that contains resources tokens. Keys for the object are resource Ids and values are the resource tokens. 284 | * @param {Array} [auth.permissionFeed] - An array of {@link Permission} objects. 285 | * @param {object} [connectionPolicy] - An instance of {@link ConnectionPolicy} class. this parameter is optional and the default connectionPolicy will be used if omitted. 286 | * @param {string} [consistencyLevel] - An optional parameter that represent the consistency level. It can take any value from {@link ConsistencyLevel}. 287 | */ 288 | function(urlConnection, auth, connectionPolicy, consistencyLevel) { 289 | this._innerDocumentclient = new DocumentClient(urlConnection, auth, connectionPolicy, consistencyLevel); 290 | Base.extend(this, this._innerDocumentclient); 291 | }, 292 | { 293 | /** Send a request for creating a database. 294 | *

295 | * A database manages users, permissions and a set of collections.
296 | * Each Azure DocumentDB Database Account is able to support multiple independent named databases, with the database being the logical container for data.
297 | * Each Database consists of one or more collections, each of which in turn contain one or more documents. Since databases are an an administrative resource, the Service Master Key will be required in order to access and successfully complete any action using the User APIs.
298 | *

299 | * @memberof DocumentClientWrapper 300 | * @instance 301 | * @param {Object} body - A json object represents The database to be created. 302 | * @param {string} body.id - The id of the database. 303 | * @param {RequestOptions} [options] - The request options. 304 | * @Returns {Object}

A promise object for the request completion.
305 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

306 | */ 307 | createDatabaseAsync: function (body, options) { 308 | return createOperationPromise(this._innerDocumentclient, "createDatabase", undefined, body, options); 309 | }, 310 | 311 | /** read a database. 312 | * @memberof DocumentClientWrapper 313 | * @instance 314 | * @param {string} databaseLink - The self-link of the database. 315 | * @param {RequestOptions} [options] - The request options. 316 | * @Returns {Object}

A promise object for the request completion.
317 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

318 | */ 319 | readDatabaseAsync: function (databaseLink, options) { 320 | return readOperationPromise(this._innerDocumentclient, "readDatabase", databaseLink, options); 321 | }, 322 | 323 | /** lists all databases. 324 | * @memberof DocumentClientWrapper 325 | * @instance 326 | * @param {FeedOptions} [options] - Represents the feed options. 327 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 328 | */ 329 | readDatabases: function (options) { 330 | return new QueryIteratorWrapper(this._innerDocumentclient.readDatabases(options)); 331 | }, 332 | 333 | /** lists all databases that satisfy a query. 334 | * @memberof DocumentClientWrapper 335 | * @instance 336 | * @param {SqlQuerySpec | string} query - A SQL query. 337 | * @param {FeedOptions} [options] - Represents the feed options. 338 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 339 | */ 340 | queryDatabases: function (query, options) { 341 | return new QueryIteratorWrapper(this._innerDocumentclient.queryDatabases(query, options)); 342 | }, 343 | 344 | /** Gets the Database account information. 345 | * @memberof DocumentClientWrapper 346 | * @instance 347 | * @Returns {Object}

A promise object for the request completion.
348 | The onFulfilled callback takes a parameter of type {@link DatabaseAccount} and the OnError callback takes a parameter of type {@link ResponseError}

349 | */ 350 | getDatabaseAccountAsync: function() { 351 | return noParameterPromise(this._innerDocumentclient, "getStorageStatistics", function(result) { return result; }); 352 | }, 353 | 354 | /** 355 | * Get all collections in this database. 356 | * @memberof DocumentClientWrapper 357 | * @instance 358 | * @param {string} databaseLink - The self-link of the database. 359 | * @param {FeedOptions} [options] - The feed options 360 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 361 | */ 362 | readCollections: function (databaseLink, options) { 363 | return new QueryIteratorWrapper(this._innerDocumentclient.readCollections(databaseLink, options)); 364 | }, 365 | 366 | /** 367 | * Query the collections for the database. 368 | * @memberof DocumentClientWrapper 369 | * @instance 370 | * @param {string} databaseLink - The self-link of the database. 371 | * @param {SqlQuerySpec | string} query - A SQL query. 372 | * @param {FeedOptions} [options] - Represents the feed options. 373 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 374 | */ 375 | queryCollections: function (databaseLink, query, options) { 376 | return new QueryIteratorWrapper(this._innerDocumentclient.queryCollections(databaseLink, query, options)); 377 | }, 378 | 379 | /** 380 | * Create a collection. 381 | *

382 | * A collection is a named logical container for documents.
383 | * A database may contain zero or more named collections and each collection consists of zero or more JSON documents.
384 | * Being schema-free, the documents in a collection do not need to share the same structure or fields.
385 | * Since collections are application resources, they can be authorized using either the master key or resource keys.
386 | *

387 | * @memberof DocumentClientWrapper 388 | * @instance 389 | * @param {string} databaseLink - The self-link of the database. 390 | * @param {object} body - Represents the body of the collection. 391 | * @param {string} body.id - The id of the collection. 392 | * @param {IndexingPolicy} body.indexingPolicy - The indexing policy associated with the collection. 393 | * @param {RequestOptions} [options] - The request options. 394 | * @Returns {Object}

A promise object for the request completion.
395 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

396 | */ 397 | createCollectionAsync: function (databaseLink, body, options) { 398 | return createOperationPromise(this._innerDocumentclient, "createCollection", databaseLink, body, options); 399 | }, 400 | 401 | /** 402 | * Reads a collection. 403 | * @memberof DocumentClientWrapper 404 | * @instance 405 | * @param {string} collectionLink - The self-link of the collection. 406 | * @param {RequestOptions} [options] - The request options. 407 | * @Returns {Object}

A promise object for the request completion.
408 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

409 | */ 410 | readCollectionAsync: function (collectionLink, options) { 411 | return readOperationPromise(this._innerDocumentclient, "readCollection", collectionLink, options); 412 | }, 413 | 414 | /** 415 | * Create a user. 416 | * @memberof DocumentClientWrapper 417 | * @instance 418 | * @param {string} databaseLink - The self-link of the database. 419 | * @param {object} body - represents the body of the user. 420 | * @param {string} body.id - The id of the user. 421 | * @param {RequestOptions} [options] - The request options. 422 | * @Returns {Object}

A promise object for the request completion.
423 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

424 | */ 425 | createUserAsync: function (databaseLink, body, options) { 426 | return createOperationPromise(this._innerDocumentclient, "createUser", databaseLink, body, options); 427 | }, 428 | 429 | /** 430 | * Upsert a user. 431 | * @memberof DocumentClientWrapper 432 | * @instance 433 | * @param {string} databaseLink - The self-link of the database. 434 | * @param {object} body - represents the body of the user. 435 | * @param {string} body.id - The id of the user. 436 | * @param {RequestOptions} [options] - The request options. 437 | * @Returns {Object}

A promise object for the request completion.
438 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

439 | */ 440 | upsertUserAsync: function (databaseLink, body, options) { 441 | return upsertOperationPromise(this._innerDocumentclient, "upsertUser", databaseLink, body, options); 442 | }, 443 | 444 | /** 445 | * Get all users in this database. 446 | * @memberof DocumentClientWrapper 447 | * @instance 448 | * @param {string} databaseLink - The self-link of the database. 449 | * @param {FeedOptions} [feedOptions] - The feed options 450 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 451 | */ 452 | readUsers: function (databaseLink, options) { 453 | return new QueryIteratorWrapper(this._innerDocumentclient.readUsers(databaseLink, options)); 454 | }, 455 | 456 | /** 457 | * Reads a user. 458 | * @memberof DocumentClientWrapper 459 | * @instance 460 | * @param {string} userLink - The self-link of the user. 461 | * @param {RequestOptions} [options] - The request options. 462 | * @Returns {Object}

A promise object for the request completion.
463 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

464 | */ 465 | readUserAsync: function (userLink, options) { 466 | return readOperationPromise(this._innerDocumentclient, "readUser", userLink, options); 467 | }, 468 | 469 | /** 470 | * Query the users for the database. 471 | * @memberof DocumentClientWrapper 472 | * @instance 473 | * @param {string} databaseLink - The self-link of the database. 474 | * @param {SqlQuerySpec | string} query - A SQL query. 475 | * @param {FeedOptions} [options] - Represents the feed options. 476 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 477 | */ 478 | queryUsers: function(databaseLink, query, options) { 479 | return new QueryIteratorWrapper(this._innerDocumentclient.queryUsers(databaseLink, query, options)); 480 | }, 481 | 482 | /** 483 | * Delete the database object. 484 | * @memberof DocumentClientWrapper 485 | * @instance 486 | * @param {string} databaseLink - The self-link of the database. 487 | * @param {RequestOptions} [options] - The request options. 488 | * @Returns {Object}

A promise object for the request completion.
489 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

490 | */ 491 | deleteDatabaseAsync: function (databaseLink, options) { 492 | return deleteOperationPromise(this._innerDocumentclient, "deleteDatabase", databaseLink, options); 493 | }, 494 | 495 | /** 496 | * Create a permission. 497 | *

A permission represents a per-User Permission to access a specific resource e.g. Document or Collection.

498 | * @memberof DocumentClientWrapper 499 | * @instance 500 | * @param {string} userLink - The self-link of the user. 501 | * @param {object} body - represents the body of the permission. 502 | * @param {string} body.id - The id of the permission 503 | * @param {string} body.permissionMode - The mode of the permission, must be a value of {@link PermissionMode} 504 | * @param {string} body.resource - the link of the resource that the permission will be applied to. 505 | * @param {RequestOptions} [options] - The request options. 506 | * @Returns {Object}

A promise object for the request completion.
507 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

508 | */ 509 | createPermissionAsync: function(userLink, body, options) { 510 | return createOperationPromise(this._innerDocumentclient, "createPermission", userLink, body, options); 511 | }, 512 | 513 | /** 514 | * Upsert a permission. 515 | *

A permission represents a per-User Permission to access a specific resource e.g. Document or Collection.

516 | * @memberof DocumentClientWrapper 517 | * @instance 518 | * @param {string} userLink - The self-link of the user. 519 | * @param {object} body - represents the body of the permission. 520 | * @param {string} body.id - The id of the permission 521 | * @param {string} body.permissionMode - The mode of the permission, must be a value of {@link PermissionMode} 522 | * @param {string} body.resource - the link of the resource that the permission will be applied to. 523 | * @param {RequestOptions} [options] - The request options. 524 | * @Returns {Object}

A promise object for the request completion.
525 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

526 | */ 527 | upsertPermissionAsync: function(userLink, body, options) { 528 | return upsertOperationPromise(this._innerDocumentclient, "upsertPermission", userLink, body, options); 529 | }, 530 | 531 | /** 532 | * Reads a permission. 533 | * @memberof DocumentClientWrapper 534 | * @instance 535 | * @param {string} permissionLink - The self-link of the permission. 536 | * @param {RequestOptions} [options] - The request options. 537 | * @Returns {Object}

A promise object for the request completion.
538 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

539 | */ 540 | readPermissionAsync: function (permissionLink, options) { 541 | return readOperationPromise(this._innerDocumentclient, "readPermission", permissionLink, options); 542 | }, 543 | 544 | /** 545 | * Get all permissions for this user. 546 | * @memberof DocumentClientWrapper 547 | * @instance 548 | * @param {string} userLink - The self-link of the user. 549 | * @param {FeedOptions} [feedOptions] - The feed options 550 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 551 | */ 552 | readPermissions: function(userLink, options) { 553 | return new QueryIteratorWrapper(this._innerDocumentclient.readPermissions(userLink, options)); 554 | }, 555 | 556 | /** 557 | * Query the permission for the user. 558 | * @memberof DocumentClientWrapper 559 | * @instance 560 | * @param {string} userLink - The self-link of the user. 561 | * @param {SqlQuerySpec | string} query - A SQL query. 562 | * @param {FeedOptions} [options] - Represents the feed options. 563 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 564 | */ 565 | queryPermissions: function(userLink, query, options) { 566 | return new QueryIteratorWrapper(this._innerDocumentclient.queryPermissions(userLink, query, options)); 567 | }, 568 | 569 | /** 570 | * Replace the user object. 571 | * @memberof DocumentClientWrapper 572 | * @instance 573 | * @param {string} userLink - The self-link of the user. 574 | * @param {User} user - Represent the new user body. 575 | * @param {RequestOptions} [options] - The request options. 576 | * @Returns {Object}

A promise object for the request completion.
577 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

578 | */ 579 | replaceUserAsync: function(userLink, user, options) { 580 | return replaceOperationPromise(this._innerDocumentclient, "replaceUser", userLink, user, options); 581 | }, 582 | 583 | /** 584 | * Delete the user object. 585 | * @memberof DocumentClientWrapper 586 | * @instance 587 | * @param {string} userLink - The self-link of the user. 588 | * @param {RequestOptions} [options] - The request options. 589 | * @Returns {Object}

A promise object for the request completion.
590 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

591 | */ 592 | deleteUserAsync: function(userLink, options) { 593 | return deleteOperationPromise(this._innerDocumentclient, "deleteUser", userLink, options); 594 | }, 595 | 596 | /** 597 | * Replace the permission object. 598 | * @memberof DocumentClientWrapper 599 | * @instance 600 | * @param {string} permissionLink - The self-link of the permission. 601 | * @param {Permission} permission - Represent the new permission body. 602 | * @param {RequestOptions} [options] - The request options. 603 | * @Returns {Object}

A promise object for the request completion.
604 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

605 | */ 606 | replacePermissionAsync: function(permissionLink, permission, options) { 607 | return replaceOperationPromise(this._innerDocumentclient, "replacePermission", permissionLink, permission, options); 608 | }, 609 | 610 | /** 611 | * Delete the permission object. 612 | * @memberof DocumentClientWrapper 613 | * @instance 614 | * @param {string} permissionLink - The self-link of the permission. 615 | * @param {RequestOptions} [options] - The request options. 616 | * @Returns {Object}

A promise object for the request completion.
617 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

618 | */ 619 | deletePermissionAsync: function(permissionLink, options) { 620 | return deleteOperationPromise(this._innerDocumentclient, "deletePermission", permissionLink, options); 621 | }, 622 | 623 | /** 624 | * Get all documents in this collection. 625 | * @memberof DocumentClientWrapper 626 | * @instance 627 | * @param {string} collectionLink - The self-link of the collection. 628 | * @param {FeedOptions} [options] - The feed options 629 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 630 | */ 631 | readDocuments: function (collectionLink, options) { 632 | return new QueryIteratorWrapper(this._innerDocumentclient.readDocuments(collectionLink, options)); 633 | }, 634 | 635 | /** 636 | * Query the documents for the collection. 637 | * @memberof DocumentClientWrapper 638 | * @instance 639 | * @param {string} collectionOrDatabaseLink - The collection link or database link if using a partition resolver 640 | * @param {SqlQuerySpec | string} query - A SQL query. 641 | * @param {FeedOptions} [options] - Represents the feed options. 642 | * @param {object} [options.partitionKey] - Optional partition key to be used with the partiotion resolver 643 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 644 | */ 645 | queryDocuments: function (collectionLink, query, options) { 646 | return new QueryIteratorWrapper(this._innerDocumentclient.queryDocuments(collectionLink, query, options)); 647 | }, 648 | 649 | /** 650 | * Create a document. 651 | *

652 | * There is no set schema for JSON documents. They may contain any number of custom properties as well as an optional list of attachments.
653 | * A Document is an application resource and can be authorized using the master key or resource keys 654 | *

655 | * @memberof DocumentClientWrapper 656 | * @instance 657 | * @param {string} collectionOrDatabaseLink - The collection link or database link if using a partition resolver 658 | * @param {object} body - Represents the body of the document. Can contain any number of user defined properties. 659 | * @param {string} [body.id] - The id of the document, MUST be unique for each document. 660 | * @param {RequestOptions} [options] - The request options. 661 | * @param {boolean} [options.disableAutomaticIdGeneration] - Disables the automatic id generation. If id is missing in the body and this option is true, an error will be returned. 662 | * @Returns {Object}

A promise object for the request completion.
663 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

664 | */ 665 | createDocumentAsync: function (collectionLink, body, options) { 666 | return createOperationPromise(this._innerDocumentclient, "createDocument", collectionLink, body, options); 667 | }, 668 | 669 | /** 670 | * Upsert a document. 671 | *

672 | * There is no set schema for JSON documents. They may contain any number of custom properties as well as an optional list of attachments.
673 | * A Document is an application resource and can be authorized using the master key or resource keys 674 | *

675 | * @memberof DocumentClientWrapper 676 | * @instance 677 | * @param {string} collectionLink - The self-link of the collection. 678 | * @param {object} body - Represents the body of the document. Can contain any number of user defined properties. 679 | * @param {string} [body.id] - The id of the document, MUST be unique for each document. 680 | * @param {RequestOptions} [options] - The request options. 681 | * @param {boolean} [options.disableAutomaticIdGeneration] - Disables the automatic id generation. If id is missing in the body and this option is true, an error will be returned. 682 | * @Returns {Object}

A promise object for the request completion.
683 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

684 | */ 685 | upsertDocumentAsync: function (collectionLink, body, options) { 686 | return upsertOperationPromise(this._innerDocumentclient, "upsertDocument", collectionLink, body, options); 687 | }, 688 | 689 | /** 690 | * Reads a document. 691 | * @memberof DocumentClientWrapper 692 | * @instance 693 | * @param {string} documentLink - The self-link of the document. 694 | * @param {RequestOptions} [options] - The request options. 695 | * @Returns {Object}

A promise object for the request completion.
696 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

697 | */ 698 | readDocumentAsync: function (documentLink, options) { 699 | return readOperationPromise(this._innerDocumentclient, "readDocument", documentLink, options); 700 | }, 701 | 702 | /** 703 | * Get all triggers in this collection. 704 | * @memberof DocumentClientWrapper 705 | * @instance 706 | * @param {string} collectionLink - The self-link of the collection. 707 | * @param {FeedOptions} [options] - The feed options 708 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 709 | */ 710 | readTriggers: function (collectionLink, options) { 711 | return new QueryIteratorWrapper(this._innerDocumentclient.readTriggers(collectionLink, options)); 712 | }, 713 | 714 | /** 715 | * Query the triggers for the collection. 716 | * @memberof DocumentClientWrapper 717 | * @instance 718 | * @param {string} collectionLink - The self-link of the collection. 719 | * @param {SqlQuerySpec | string} query - A SQL query. 720 | * @param {FeedOptions} [options] - Represents the feed options. 721 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 722 | */ 723 | queryTriggers: function (collectionLink, query, options) { 724 | return new QueryIteratorWrapper(this._innerDocumentclient.queryTriggers(collectionLink, query, options)); 725 | }, 726 | 727 | /** 728 | * Create a trigger. 729 | *

730 | * DocumentDB supports pre and post triggers defined in JavaScript to be executed on creates, updates and deletes.
731 | * For additional details, refer to the server-side JavaScript API documentation. 732 | *

733 | * @memberof DocumentClientWrapper 734 | * @instance 735 | * @param {string} collectionLink - The self-link of the collection. 736 | * @param {object} trigger - represents the body of the trigger. 737 | * @param {string} trigger.id - represents The id of the trigger. 738 | * @param {string} trigger.triggerType - represents the type of the trigger, should be one of the values of {@link TriggerType}. 739 | * @param {string} trigger.triggerOperation - represents the trigger operation, should be one of the values of {@link TriggerOperation}. 740 | * @param {function} trigger.serverScript - represents the body of the trigger, it can be passed as stringified too. 741 | * @param {RequestOptions} [options] - The request options. 742 | * @Returns {Object}

A promise object for the request completion.
743 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

744 | */ 745 | createTriggerAsync: function (collectionLink, trigger, options) { 746 | return createOperationPromise(this._innerDocumentclient, "createTrigger", collectionLink, trigger, options); 747 | }, 748 | 749 | /** 750 | * Create a trigger. 751 | *

752 | * DocumentDB supports pre and post triggers defined in JavaScript to be executed on creates, updates and deletes.
753 | * For additional details, refer to the server-side JavaScript API documentation. 754 | *

755 | * @memberof DocumentClientWrapper 756 | * @instance 757 | * @param {string} collectionLink - The self-link of the collection. 758 | * @param {object} trigger - represents the body of the trigger. 759 | * @param {string} trigger.id - represents The id of the trigger. 760 | * @param {string} trigger.triggerType - represents the type of the trigger, should be one of the values of {@link TriggerType}. 761 | * @param {string} trigger.triggerOperation - represents the trigger operation, should be one of the values of {@link TriggerOperation}. 762 | * @param {function} trigger.serverScript - represents the body of the trigger, it can be passed as stringified too. 763 | * @param {RequestOptions} [options] - The request options. 764 | * @Returns {Object}

A promise object for the request completion.
765 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

766 | */ 767 | upsertTriggerAsync: function (collectionLink, trigger, options) { 768 | return upsertOperationPromise(this._innerDocumentclient, "upsertTrigger", collectionLink, trigger, options); 769 | }, 770 | 771 | /** 772 | * Reads a trigger object. 773 | * @memberof DocumentClientWrapper 774 | * @instance 775 | * @param {string} triggerLink - The self-link of the trigger. 776 | * @param {RequestOptions} [options] - The request options. 777 | * @Returns {Object}

A promise object for the request completion.
778 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

779 | */ 780 | readTriggerAsync: function (triggerLink, options) { 781 | return readOperationPromise(this._innerDocumentclient, "readTrigger", triggerLink, options); 782 | }, 783 | 784 | /** 785 | * Get all UserDefinedFunctions in this collection. 786 | * @memberof DocumentClientWrapper 787 | * @instance 788 | * @param {string} collectionLink - The self-link of the collection. 789 | * @param {FeedOptions} [options] - The feed options 790 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 791 | */ 792 | readUserDefinedFunctions: function (collectionLink, options) { 793 | return new QueryIteratorWrapper(this._innerDocumentclient.readUserDefinedFunctions(collectionLink, options)); 794 | }, 795 | 796 | /** 797 | * Query the user defined functions for the collection. 798 | * @memberof DocumentClientWrapper 799 | * @instance 800 | * @param {string} collectionLink - The self-link of the collection. 801 | * @param {SqlQuerySpec | string} query - A SQL query. 802 | * @param {FeedOptions} [options] - Represents the feed options. 803 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 804 | */ 805 | queryUserDefinedFunctions: function (collectionLink, query, options) { 806 | return new QueryIteratorWrapper(this._innerDocumentclient.queryUserDefinedFunctions(collectionLink, query, options)); 807 | }, 808 | 809 | /** 810 | * Create a UserDefinedFunction. 811 | *

812 | * DocumentDB supports JavaScript UDFs which can be used inside queries, stored procedures and triggers.
813 | * For additional details, refer to the server-side JavaScript API documentation. 814 | *

815 | * @memberof DocumentClientWrapper 816 | * @instance 817 | * @param {string} collectionLink - The self-link of the collection. 818 | * @param {object} udf - represents the body of the userDefinedFunction. 819 | * @param {string} udf.id - represents The id of the udf. 820 | * @param {string} udf.userDefinedFunctionType - the type of the udf, it should be one of the values of {@link UserDefinedFunctionType} 821 | * @param {function} udf.serverScript - represents the body of the udf, it can be passed as stringified too. 822 | * @param {RequestOptions} [options] - The request options. 823 | * @Returns {Object}

A promise object for the request completion.
824 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

825 | */ 826 | createUserDefinedFunctionAsync: function (collectionLink, udf, options) { 827 | return createOperationPromise(this._innerDocumentclient, "createUserDefinedFunction", collectionLink, udf, options); 828 | }, 829 | 830 | /** 831 | * Upsert a UserDefinedFunction. 832 | *

833 | * DocumentDB supports JavaScript UDFs which can be used inside queries, stored procedures and triggers.
834 | * For additional details, refer to the server-side JavaScript API documentation. 835 | *

836 | * @memberof DocumentClientWrapper 837 | * @instance 838 | * @param {string} collectionLink - The self-link of the collection. 839 | * @param {object} udf - represents the body of the userDefinedFunction. 840 | * @param {string} udf.id - represents The id of the udf. 841 | * @param {string} udf.userDefinedFunctionType - the type of the udf, it should be one of the values of {@link UserDefinedFunctionType} 842 | * @param {function} udf.serverScript - represents the body of the udf, it can be passed as stringified too. 843 | * @param {RequestOptions} [options] - The request options. 844 | * @Returns {Object}

A promise object for the request completion.
845 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

846 | */ 847 | upsertUserDefinedFunctionAsync: function (collectionLink, udf, options) { 848 | return upsertOperationPromise(this._innerDocumentclient, "upsertUserDefinedFunction", collectionLink, udf, options); 849 | }, 850 | 851 | /** 852 | * Reads a udf object. 853 | * @memberof DocumentClientWrapper 854 | * @instance 855 | * @param {string} udfLink - The self-link of the user defined function. 856 | * @param {RequestOptions} [options] - The request options. 857 | * @Returns {Object}

A promise object for the request completion.
858 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

859 | */ 860 | readUserDefinedFunctionAsync: function (udfLink, options) { 861 | return readOperationPromise(this._innerDocumentclient, "readUserDefinedFunction", udfLink, options); 862 | }, 863 | 864 | /** 865 | * Get all StoredProcedures in this collection. 866 | * @memberof DocumentClientWrapper 867 | * @instance 868 | * @param {string} collectionLink - The self-link of the collection. 869 | * @param {FeedOptions} [options] - The feed options 870 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 871 | */ 872 | readStoredProcedures: function (collectionLink, options) { 873 | return new QueryIteratorWrapper(this._innerDocumentclient.readStoredProcedures(collectionLink, options)); 874 | }, 875 | 876 | /** 877 | * Query the storedProcedures for the collection. 878 | * @memberof DocumentClientWrapper 879 | * @instance 880 | * @param {string} collectionLink - The self-link of the collection. 881 | * @param {SqlQuerySpec | string} query - A SQL query. 882 | * @param {FeedOptions} [options] - Represents the feed options. 883 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 884 | */ 885 | queryStoredProcedures: function (collectionLink, query, options) { 886 | return new QueryIteratorWrapper(this._innerDocumentclient.queryStoredProcedures(collectionLink, query, options)); 887 | }, 888 | 889 | /** 890 | * Create a StoredProcedure object. 891 | *

892 | * DocumentDB allows stored procedures to be executed in the storage tier, directly against a document collection. The script
893 | * gets executed under ACID transactions on the primary storage partition of the specified collection. For additional details,
894 | * refer to the server-side JavaScript API documentation. 895 | *

896 | * @memberof DocumentClientWrapper 897 | * @instance 898 | * @param {string} collectionLink - The self-link of the collection. 899 | * @param {object} sproc - represents the body of the stored procedure. 900 | * @param {string} sproc.id - represents The id of the stored procedure. 901 | * @param {function} sproc.serverScript - represents the body of the stored procedure, it can be passed as stringified too. 902 | * @param {RequestOptions} [options] - The request options. 903 | * @Returns {Object}

A promise object for the request completion.
904 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

905 | */ 906 | createStoredProcedureAsync: function (collectionLink, sproc, options) { 907 | return createOperationPromise(this._innerDocumentclient, "createStoredProcedure", collectionLink, sproc, options); 908 | }, 909 | 910 | /** 911 | * Upsert a StoredProcedure object. 912 | *

913 | * DocumentDB allows stored procedures to be executed in the storage tier, directly against a document collection. The script
914 | * gets executed under ACID transactions on the primary storage partition of the specified collection. For additional details,
915 | * refer to the server-side JavaScript API documentation. 916 | *

917 | * @memberof DocumentClientWrapper 918 | * @instance 919 | * @param {string} collectionLink - The self-link of the collection. 920 | * @param {object} sproc - represents the body of the stored procedure. 921 | * @param {string} sproc.id - represents The id of the stored procedure. 922 | * @param {function} sproc.serverScript - represents the body of the stored procedure, it can be passed as stringified too. 923 | * @param {RequestOptions} [options] - The request options. 924 | * @Returns {Object}

A promise object for the request completion.
925 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

926 | */ 927 | upsertStoredProcedureAsync: function (collectionLink, sproc, options) { 928 | return upsertOperationPromise(this._innerDocumentclient, "upsertStoredProcedure", collectionLink, sproc, options); 929 | }, 930 | 931 | /** 932 | * Reads a StoredProcedure object. 933 | * @memberof DocumentClientWrapper 934 | * @instance 935 | * @param {string} sprocLink - The self-link of the stored procedure. 936 | * @param {RequestOptions} [options] - The request options. 937 | * @Returns {Object}

A promise object for the request completion.
938 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

939 | */ 940 | readStoredProcedureAsync: function (sprocLink, options) { 941 | return readOperationPromise(this._innerDocumentclient, "readStoredProcedure", sprocLink, options); 942 | }, 943 | 944 | /** 945 | * Get all conflicts in this collection. 946 | * @memberof DocumentClientWrapper 947 | * @instance 948 | * @param {string} collectionLink - The self-link of the collection. 949 | * @param {FeedOptions} [options] - The feed options 950 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 951 | */ 952 | readConflicts: function (collectionLink, options) { 953 | return new QueryIteratorWrapper(this._innerDocumentclient.readConflicts(collectionLink, options)); 954 | }, 955 | 956 | /** 957 | * Query the conflicts for the collection. 958 | * @memberof DocumentClientWrapper 959 | * @instance 960 | * @param {string} collectionLink - The self-link of the collection. 961 | * @param {SqlQuerySpec | string} query - A SQL query. 962 | * @param {FeedOptions} [options] - Represents the feed options. 963 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 964 | */ 965 | queryConflicts: function (collectionLink, query, options) { 966 | return new QueryIteratorWrapper(this._innerDocumentclient.queryConflicts(collectionLink, query, options)); 967 | }, 968 | 969 | /** 970 | * Reads a conflict. 971 | * @memberof DocumentClientWrapper 972 | * @instance 973 | * @param {string} conflictLink - The self-link of the conflict. 974 | * @param {RequestOptions} [options] - The request options. 975 | * @Returns {Object}

A promise object for the request completion.
976 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

977 | */ 978 | readConflictAsync: function (conflictLink, options) { 979 | return readOperationPromise(this._innerDocumentclient, "readConflict", conflictLink, options); 980 | }, 981 | 982 | /** 983 | * Replace the collection object. 984 | * @memberof DocumentClientWrapper 985 | * @instance 986 | * @param {string} collectionLink - The self-link of the collection. 987 | * @param {object} collection - Represent the new collection body. 988 | * @param {RequestOptions} [options] - The request options. 989 | * @Returns {Object}

A promise object for the request completion.
990 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

991 | */ 992 | replaceCollectionAsync: function(collectionLink, collection, options) { 993 | return replaceOperationPromise(this._innerDocumentclient, "replaceCollection", collectionLink, collection, options); 994 | }, 995 | 996 | /** 997 | * Delete the collection object. 998 | * @memberof DocumentClientWrapper 999 | * @instance 1000 | * @param {string} collectionLink - The self-link of the collection. 1001 | * @param {RequestOptions} [options] - The request options. 1002 | * @Returns {Object}

A promise object for the request completion.
1003 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1004 | */ 1005 | deleteCollectionAsync: function(collectionLink, options) { 1006 | return deleteOperationPromise(this._innerDocumentclient, "deleteCollection", collectionLink, options); 1007 | }, 1008 | 1009 | /** 1010 | * Replace the document object. 1011 | * @memberof DocumentClientWrapper 1012 | * @instance 1013 | * @param {string} documentLink - The self-link of the document. 1014 | * @param {object} document - Represent the new document body. 1015 | * @param {RequestOptions} [options] - The request options. 1016 | * @Returns {Object}

A promise object for the request completion.
1017 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1018 | */ 1019 | replaceDocumentAsync: function(documentLink, document, options) { 1020 | return replaceOperationPromise(this._innerDocumentclient, "replaceDocument", documentLink, document, options); 1021 | }, 1022 | 1023 | /** 1024 | * Delete the document object. 1025 | * @memberof DocumentClientWrapper 1026 | * @instance 1027 | * @param {string} documentLink - The self-link of the document. 1028 | * @param {RequestOptions} [options] - The request options. 1029 | * @Returns {Object}

A promise object for the request completion.
1030 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1031 | */ 1032 | deleteDocumentAsync: function(documentLink, options) { 1033 | return deleteOperationPromise(this._innerDocumentclient, "deleteDocument", documentLink, options); 1034 | }, 1035 | 1036 | /** 1037 | * Create an attachment for the document object. 1038 | *

1039 | * Each document may contain zero or more attachemnts. Attachments can be of any MIME type - text, image, binary data.
1040 | * These are stored externally in Azure Blob storage. Attachments are automatically deleted when the parent document is deleted. 1041 | *

1042 | * @memberof DocumentClientWrapper 1043 | * @instance 1044 | * @param {string} documentLink - The self-link of the document. 1045 | * @param {Object} body - The metadata the defines the attachment media like media, contentType. It can include any other properties as part of the metedata. 1046 | * @param {string} body.contentType - the MIME contentType of the attachment. 1047 | * @param {string} body.media - Media link associated with the attachment content. 1048 | * @param {RequestOptions} [options] - The request options. 1049 | * @Returns {Object}

A promise object for the request completion.
1050 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1051 | */ 1052 | createAttachmentAsync: function (documentLink, body, options) { 1053 | return createOperationPromise(this._innerDocumentclient, "createAttachment", documentLink, body, options); 1054 | }, 1055 | 1056 | /** 1057 | * Upsert an attachment for the document object. 1058 | *

1059 | * Each document may contain zero or more attachemnts. Attachments can be of any MIME type - text, image, binary data.
1060 | * These are stored externally in Azure Blob storage. Attachments are automatically deleted when the parent document is deleted. 1061 | *

1062 | * @memberof DocumentClientWrapper 1063 | * @instance 1064 | * @param {string} documentLink - The self-link of the document. 1065 | * @param {Object} body - The metadata the defines the attachment media like media, contentType. It can include any other properties as part of the metedata. 1066 | * @param {string} body.contentType - the MIME contentType of the attachment. 1067 | * @param {string} body.media - Media link associated with the attachment content. 1068 | * @param {RequestOptions} [options] - The request options. 1069 | * @Returns {Object}

A promise object for the request completion.
1070 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1071 | */ 1072 | upsertAttachmentAsync: function (documentLink, body, options) { 1073 | return upsertOperationPromise(this._innerDocumentclient, "upsertAttachment", documentLink, body, options); 1074 | }, 1075 | 1076 | /** 1077 | * Create an attachment for the document object. 1078 | * @memberof DocumentClientWrapper 1079 | * @instance 1080 | * @param {string} documentLink - The self-link of the document. 1081 | * @param {stream.Readable} readableStream - the stream that represents the media itself that needs to be uploaded. 1082 | * @param {MediaOptions} [options] - The request options. 1083 | * @Returns {Object}

A promise object for the request completion.
1084 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1085 | */ 1086 | createAttachmentAndUploadMediaAsync: function(documentLink, readableStream, options) { 1087 | return createOperationPromise(this._innerDocumentclient, "createAttachmentAndUploadMedia", documentLink, readableStream, options); 1088 | }, 1089 | 1090 | /** 1091 | * Upsert an attachment for the document object. 1092 | * @memberof DocumentClientWrapper 1093 | * @instance 1094 | * @param {string} documentLink - The self-link of the document. 1095 | * @param {stream.Readable} readableStream - the stream that represents the media itself that needs to be uploaded. 1096 | * @param {MediaOptions} [options] - The request options. 1097 | * @Returns {Object}

A promise object for the request completion.
1098 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1099 | */ 1100 | upsertAttachmentAndUploadMediaAsync: function(documentLink, readableStream, options) { 1101 | return upsertOperationPromise(this._innerDocumentclient, "upsertAttachmentAndUploadMedia", documentLink, readableStream, options); 1102 | }, 1103 | 1104 | /** 1105 | * Reads an Attachment object. 1106 | * @memberof DocumentClientWrapper 1107 | * @instance 1108 | * @param {string} attachmentLink - The self-link of the attachment. 1109 | * @param {RequestOptions} [options] - The request options. 1110 | * @Returns {Object}

A promise object for the request completion.
1111 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1112 | */ 1113 | readAttachmentAsync: function (attachmentLink, options) { 1114 | return readOperationPromise(this._innerDocumentclient, "readAttachment", attachmentLink, options); 1115 | }, 1116 | 1117 | /** 1118 | * Get all attachments for this document. 1119 | * @memberof DocumentClientWrapper 1120 | * @instance 1121 | * @param {string} documentLink - The self-link of the document. 1122 | * @param {FeedOptions} [options] - The feed options 1123 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 1124 | */ 1125 | readAttachments: function (documentLink, options) { 1126 | return new QueryIteratorWrapper(this._innerDocumentclient.readAttachments(documentLink, options)); 1127 | }, 1128 | 1129 | /** 1130 | * Query the attachments for the document. 1131 | * @memberof DocumentClientWrapper 1132 | * @instance 1133 | * @param {string} documentLink - The self-link of the document. 1134 | * @param {SqlQuerySpec | string} query - A SQL query. 1135 | * @param {FeedOptions} [options] - Represents the feed options. 1136 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 1137 | */ 1138 | queryAttachments: function (documentLink, query, options) { 1139 | return new QueryIteratorWrapper(this._innerDocumentclient.queryAttachments(documentLink, query, options)); 1140 | }, 1141 | 1142 | /** 1143 | * Read the media for the attachment object. 1144 | * @memberof DocumentClientWrapper 1145 | * @instance 1146 | * @param {string} mediaLink - The media link of the media in the attachment. 1147 | * @Returns {Object}

A promise object for the request completion.
1148 | The onFulfilled callback takes a parameter of type {@link Response} and the OnError callback takes a parameter of type {@link ResponseError}

1149 |

The result parameter can be a buffer or a stream depending on the value of {@link MediaReadMode}.

1150 | */ 1151 | readMediaAsync: function (mediaLink) { 1152 | return noParameterPromise(this._innerDocumentclient, "readMedia", mediaLink); 1153 | }, 1154 | 1155 | /** 1156 | * Update media for the attachment 1157 | * @memberof DocumentClientWrapper 1158 | * @instance 1159 | * @param {string} mediaLink - The media link of the media in the attachment. 1160 | * @param {stream.Readable} readableStream - the stream that represents the media itself that needs to be uploaded. 1161 | * @param {MediaOptions} [options] - options for the media 1162 | * @Returns {Object}

A promise object for the request completion.
1163 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1164 | */ 1165 | updateMediaAsync: function (mediaLink, readableStream, options) { 1166 | return replaceOperationPromise(this._innerDocumentclient, "updateMedia", mediaLink, readableStream, options); 1167 | }, 1168 | 1169 | /** 1170 | * Replace the attachment object. 1171 | * @memberof DocumentClientWrapper 1172 | * @instance 1173 | * @param {string} attachmentLink - The self-link of the attachment. 1174 | * @param {object} attachment - Represent the new attachment body. 1175 | * @param {RequestOptions} [options] - The request options. 1176 | * @Returns {Object}

A promise object for the request completion.
1177 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1178 | */ 1179 | replaceAttachmentAsync: function(attachmentLink, attachment, options) { 1180 | return replaceOperationPromise(this._innerDocumentclient, "replaceAttachment", attachmentLink, attachment, options); 1181 | }, 1182 | 1183 | /** 1184 | * Delete the attachment object. 1185 | * @memberof DocumentClientWrapper 1186 | * @instance 1187 | * @param {string} attachmentLink - The self-link of the attachment. 1188 | * @param {RequestOptions} [options] - The request options. 1189 | * @Returns {Object}

A promise object for the request completion.
1190 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1191 | */ 1192 | deleteAttachmentAsync: function(attachmentLink, options) { 1193 | return deleteOperationPromise(this._innerDocumentclient, "deleteAttachment", attachmentLink, options); 1194 | }, 1195 | 1196 | /** 1197 | * Replace the trigger object. 1198 | * @memberof DocumentClientWrapper 1199 | * @instance 1200 | * @param {string} triggerLink - The self-link of the trigger. 1201 | * @param {object} trigger - Represent the new trigger body. 1202 | * @param {RequestOptions} [options] - The request options. 1203 | * @Returns {Object}

A promise object for the request completion.
1204 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1205 | */ 1206 | replaceTriggerAsync: function(triggerLink, trigger, options) { 1207 | return replaceOperationPromise(this._innerDocumentclient, "replaceTrigger", triggerLink, trigger, options); 1208 | }, 1209 | 1210 | /** 1211 | * Delete the trigger object. 1212 | * @memberof DocumentClientWrapper 1213 | * @instance 1214 | * @param {string} triggerLink - The self-link of the trigger. 1215 | * @param {RequestOptions} [options] - The request options. 1216 | * @Returns {Object}

A promise object for the request completion.
1217 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1218 | */ 1219 | deleteTriggerAsync: function(triggerLink, options) { 1220 | return deleteOperationPromise(this._innerDocumentclient, "deleteTrigger", triggerLink, options); 1221 | }, 1222 | 1223 | /** 1224 | * Replace the UserDefinedFunction object. 1225 | * @memberof DocumentClientWrapper 1226 | * @instance 1227 | * @param {string} udfLink - The self-link of the user defined function. 1228 | * @param {object} udf - Represent the new udf body. 1229 | * @param {RequestOptions} [options] - The request options. 1230 | * @Returns {Object}

A promise object for the request completion.
1231 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1232 | */ 1233 | replaceUserDefinedFunctionAsync: function(udfLink, udf, options) { 1234 | return replaceOperationPromise(this._innerDocumentclient, "replaceUserDefinedFunction", udfLink, udf, options); 1235 | }, 1236 | 1237 | /** 1238 | * Delete the UserDefinedFunction object. 1239 | * @memberof DocumentClientWrapper 1240 | * @instance 1241 | * @param {string} udfLink - The self-link of the user defined function. 1242 | * @param {RequestOptions} [options] - The request options. 1243 | * @Returns {Object}

A promise object for the request completion.
1244 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1245 | */ 1246 | deleteUserDefinedFunctionAsync: function(udfLink, options) { 1247 | return deleteOperationPromise(this._innerDocumentclient, "deleteUserDefinedFunction", udfLink, options); 1248 | }, 1249 | 1250 | /** 1251 | * Execute the StoredProcedure represented by the object. 1252 | * @memberof DocumentClientWrapper 1253 | * @instance 1254 | * @param {string} sprocLink - The self-link of the stored procedure. 1255 | * @param {Array} [params] - Represent the parameters of the stored procedure. 1256 | * @param {Object} [options] - options for executing the stored procedure 1257 | * @param {Object} [options.partitionKey] - partition key value if executing against a partitioned collection 1258 | * @Returns {Object}

A promise object for the request completion.
1259 | The onFulfilled callback takes a parameter of type {@link Response} and the OnError callback takes a parameter of type {@link ResponseError}

1260 | */ 1261 | executeStoredProcedureAsync: function(sprocLink, params, options) { 1262 | var deferred = Q.defer(); 1263 | this._innerDocumentclient.executeStoredProcedure(sprocLink, params, options, function (error, result, responseHeaders) { 1264 | if (error) { 1265 | addOrMergeHeadersForError(error, responseHeaders); 1266 | deferred.reject(error); 1267 | } else { 1268 | deferred.resolve({result: result, headers: responseHeaders}); 1269 | } 1270 | }); 1271 | return deferred.promise; 1272 | }, 1273 | 1274 | /** 1275 | * Replace the StoredProcedure object. 1276 | * @memberof DocumentClientWrapper 1277 | * @instance 1278 | * @param {string} sprocLink - The self-link of the stored procedure. 1279 | * @param {object} sproc - Represent the new sproc body. 1280 | * @param {RequestOptions} [options] - The request options. 1281 | * @Returns {Object}

A promise object for the request completion.
1282 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1283 | */ 1284 | replaceStoredProcedureAsync: function(sprocLink, sproc, options) { 1285 | return replaceOperationPromise(this._innerDocumentclient, "replaceStoredProcedure", sprocLink, sproc, options); 1286 | }, 1287 | 1288 | /** 1289 | * Delete the StoredProcedure object. 1290 | * @memberof DocumentClientWrapper 1291 | * @instance 1292 | * @param {string} sprocLink - The self-link of the stored procedure. 1293 | * @param {RequestOptions} [options] - The request options. 1294 | * @Returns {Object}

A promise object for the request completion.
1295 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1296 | */ 1297 | deleteStoredProcedureAsync: function(sprocLink, options) { 1298 | return deleteOperationPromise(this._innerDocumentclient, "deleteStoredProcedure", sprocLink, options); 1299 | }, 1300 | 1301 | /** 1302 | * Delete the conflict object. 1303 | * @memberof DocumentClientWrapper 1304 | * @instance 1305 | * @param {string} conflictLink - The self-link of the conflict. 1306 | * @param {RequestOptions} [options] - The request options. 1307 | * @Returns {Object}

A promise object for the request completion.
1308 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1309 | */ 1310 | deleteConflictAsync: function(conflictLink, options) { 1311 | return deleteOperationPromise(this._innerDocumentclient, "deleteConflict", conflictLink, options); 1312 | }, 1313 | 1314 | /** 1315 | * Replace the Offer object. 1316 | * @memberof DocumentClientWrapper 1317 | * @instance 1318 | * @param {string} offerLink - The self-link of the offer. 1319 | * @param {object} offer - Represent the new offer body. 1320 | * @Returns {Object}

A promise object for the request completion.
1321 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1322 | */ 1323 | replaceOfferAsync: function(offerLink, offer) { 1324 | return replaceOperationPromise(this._innerDocumentclient, "replaceOffer", offerLink, offer, undefined); 1325 | }, 1326 | 1327 | /** 1328 | * Reads an offer object. 1329 | * @memberof DocumentClientWrapper 1330 | * @instance 1331 | * @param {string} offerLink - The self-link of the offer. 1332 | * @Returns {Object}

A promise object for the request completion.
1333 | The onFulfilled callback takes a parameter of type {@link ResourceResponse} and the OnError callback takes a parameter of type {@link ResponseError}

1334 | */ 1335 | readOfferAsync: function (offerLink) { 1336 | return readOperationPromise(this._innerDocumentclient, "readOffer", offerLink, undefined); 1337 | }, 1338 | 1339 | /** 1340 | * Get all offers for this database. 1341 | * @memberof DocumentClientWrapper 1342 | * @instance 1343 | * @param {FeedOptions} [options] - The feed options 1344 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 1345 | */ 1346 | readOffers: function (options) { 1347 | return new QueryIteratorWrapper(this._innerDocumentclient.readOffers(options)); 1348 | }, 1349 | 1350 | /** 1351 | * Query offers for this database. 1352 | * @memberof DocumentClientWrapper 1353 | * @instance 1354 | * @param {SqlQuerySpec | string} query - A SQL query. 1355 | * @param {FeedOptions} [options] - Represents the feed options. 1356 | * @returns {QueryIterator} - An instance of queryIterator to handle reading feed. 1357 | */ 1358 | queryOffers: function (query, options) { 1359 | return new QueryIteratorWrapper(this._innerDocumentclient.queryOffers(query, options)); 1360 | } 1361 | } 1362 | ); 1363 | 1364 | 1365 | /** 1366 | * The response of a request 1367 | * @typedef {Object} Response 1368 | * @property {Object} result - An object that represents the result of the request. 1369 | * @property {Object} headers - An object that contain the response headers. 1370 | * 1371 | */ 1372 | 1373 | /** 1374 | * The response of a request that contains a resource. 1375 | * @typedef {Object} ResourceResponse 1376 | * @property {Object} resource - An object that represents the requested resource (Db, collection, document ... etc). 1377 | * @property {Object} headers - An object that contain the response headers. 1378 | * 1379 | */ 1380 | 1381 | /** 1382 | * The feed response of a request 1383 | * @typedef {Object} FeedResponse 1384 | * @property {Object} feed - An Array of objects that represents the resources (Db, collection, document ... etc). 1385 | * @property {Object} headers - An object that contain the response headers. 1386 | * 1387 | */ 1388 | 1389 | /** 1390 | * The error of a request 1391 | * @typedef {Object} ResponseError Contains error information if an error occurs. 1392 | * @param {int} code - The response code corresponding to the error. 1393 | * @param {string} body - A string represents the error information. 1394 | * 1395 | */ 1396 | 1397 | if (typeof exports !== "undefined") { 1398 | exports.DocumentClientWrapper = DocumentClientWrapper; 1399 | exports.DocumentClient = DocumentClient; 1400 | exports.DocumentBase = DocumentBase; 1401 | } -------------------------------------------------------------------------------- /nodejspromisessdk.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {C08DD1E9-7197-497E-A585-76BD7563999A} 5 | 6 | 7 | 8 | 9 | 10 | $(DocDBTargetDestination)SDK\package\nodejspromisesclient\ 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | tests\ 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "documentdb-q-promises", 3 | "description": "Q promises wrapper for the Azure DocumentDB Node.js SDK", 4 | "keywords": [ 5 | "documentdb", 6 | "document database", 7 | "azure", 8 | "nosql", 9 | "database", 10 | "cloud", 11 | "promises" 12 | ], 13 | "version": "1.6.0", 14 | "author": "Microsoft Corporation", 15 | "main": "./documentclientwrapper.js", 16 | "engine": { 17 | "node": ">=0.8" 18 | }, 19 | "dependencies": { 20 | "q": "*", 21 | "documentdb": "*" 22 | }, 23 | "devDependencies": { 24 | "eslint": "*", 25 | "grunt": "^0.4.5", 26 | "grunt-eslint": "^13.0.0", 27 | "jsdoc": "*", 28 | "load-grunt-tasks": "^3.1.0", 29 | "mocha": "*", 30 | "time-grunt": "^1.2.0" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/Azure/azure-documentdb-node-q" 35 | }, 36 | "licenses": [ 37 | { 38 | "type": "Apache License, Version 2.0", 39 | "url": "http://www.apache.org/licenses/LICENSE-2.0" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #Microsoft Azure DocumentDB Node.js Q promises wrapper 2 | 3 | [![Join the chat at https://gitter.im/Azure/azure-documentdb-node](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Azure/azure-documentdb-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | ![](https://img.shields.io/npm/v/documentdb-q-promises.svg) 6 | ![](https://img.shields.io/npm/dm/documentdb-q-promises.svg) 7 | ![](https://img.shields.io/github/issues/azure/azure-documentdb-node-q.svg) 8 | 9 | This project provides a node module that makes it easy to interact with Azure DocumentDB. 10 | 11 | For documentation please see the Microsoft Azure [Node.js Developer Center](http://azure.microsoft.com/en-us/develop/nodejs/) and the [Microsoft Azure DocumentDB Node.js SDK Documentation](http://azure.github.io/azure-documentdb-node-q/). 12 | 13 | ##Installation 14 | 15 | This is a wrapper of the [Azure DocumentDB Node.js SDK](https://github.com/Azure/azure-documentdb-node) using the [Q promises](https://github.com/kriskowal/q) library. 16 | 17 | npm install documentdb-q-promises 18 | 19 | ##Usage 20 | 21 | To use this SDK to call Azure DocumentDB, you need to first [create an account](http://azure.microsoft.com/en-us/documentation/articles/documentdb-create-account/). 22 | 23 | ##Hello world example code using Q promises 24 | ```js 25 | var DocumentClient = require('documentdb-q-promises').DocumentClientWrapper; 26 | 27 | var host = [hostendpoint]; // Add your endpoint 28 | var masterKey = [database account masterkey]; // Add the masterkey of the endpoint 29 | 30 | var client = new DocumentClient(host, {masterKey: masterKey}); 31 | var databaseDefinition = { id: "sample database" } 32 | var collectionDefinition = { id: "sample collection" }; 33 | var documentDefinition = { id: "hello world doc", content: "Hello World!" }; 34 | 35 | var database, collection, document; 36 | client.createDatabaseAsync(databaseDefinition) 37 | .then(function(databaseResponse) { 38 | database = databaseResponse.resource; 39 | return client.createCollectionAsync(database._self, collectionDefinition); 40 | }) 41 | .then(function(collectionResponse) { 42 | collection = collectionResponse.resource; 43 | 44 | return client.createDocumentAsync(collection._self, documentDefinition); 45 | }) 46 | .then(function(documentResponse) { 47 | var document = documentResponse.resource; 48 | console.log('Created Document with content: ', document.content); 49 | }) 50 | .fail(function(error) { 51 | console.log("An error occured", error); 52 | }); 53 | ``` 54 | 55 | ###Youtube Videos 56 | 57 | Getting started with Azure DocumentDB on Node.js: 58 | 59 | [![Azure Demo: Getting started with Azure DocumentDB on Node.js](http://img.youtube.com/vi/UAE7h9PCZjA/0.jpg)](http://www.youtube.com/watch?v=UAE7h9PCZjA) 60 | 61 | ##Need Help? 62 | 63 | Be sure to check out the Microsoft Azure [Developer Forums on MSDN](https://social.msdn.microsoft.com/forums/azure/en-US/home?forum=AzureDocumentDB) or the [Developer Forums on Stack Overflow](http://stackoverflow.com/questions/tagged/azure-documentdb) if you have trouble with the provided code. 64 | 65 | ##Contribute Code or Provide Feedback 66 | 67 | If you would like to become an active contributor to this project please follow the instructions provided in [Azure Projects Contribution Guidelines](http://azure.github.io/guidelines.html). 68 | 69 | If you encounter any bugs with the library please file an issue in the [Issues](https://github.com/Azure/azure-documentdb-node-q/issues) section of the project. 70 | 71 | ##Learn More 72 | 73 | * [Azure Developer Center](http://azure.microsoft.com/en-us/develop/nodejs) 74 | * [Azure DocumentDB Node.js SDK Documentation](http://azure.github.io/azure-documentdb-node-q/) 75 | * [Azure DocumentDB Service](http://azure.microsoft.com/en-us/documentation/services/documentdb/) 76 | -------------------------------------------------------------------------------- /test/_testConfig.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | Copyright (c) 2014 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | var masterKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; 25 | var host = "https://localhost:443"; 26 | 27 | exports.host = host; 28 | exports.masterKey = masterKey; 29 | -------------------------------------------------------------------------------- /test/readme.md: -------------------------------------------------------------------------------- 1 | #Microsoft Azure DocumentDB Node.js Q promises wrapper tests 2 | 3 | 4 | 5 | ##Running the tests 6 | 7 | 8 | 9 | First You need to install mocha and q 10 | > npm install mocha -g 11 | > npm install q 12 | 13 | 14 | 15 | Pack the local directory 16 | > npm pack 17 | 18 | 19 | 20 | Install to node_modules 21 | > npm install documentdb-q-promises-.tgz 22 | 23 | 24 | 25 | Edit _testConfig.js, supplying a host and masterKey for an existing DocumentDB account. 26 | 27 | WARNING! - DO NOT use an account which contains objects or data which you care about. The test suite 28 | cleans up after itself and may delete any or all contents. 29 | 30 | 31 | 32 | From the test folder run 33 | > mocha -t 0 -R spec -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | Copyright (c) 2014 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | "use strict"; 25 | 26 | var DocumentDBClient = require("documentdb-q-promises").DocumentClientWrapper 27 | , DocumentBase = require("documentdb-q-promises").DocumentBase 28 | , assert = require("assert") 29 | , Stream = require("stream") 30 | , testConfig = require("./_testConfig") 31 | , Q = require("q"); 32 | 33 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; 34 | 35 | var host = testConfig.host; 36 | var masterKey = testConfig.masterKey; 37 | 38 | describe("NodeJS Client Q promise Wrapper CRUD Tests", function(){ 39 | 40 | function validateCRUDAsync(client, parentLink, options) { 41 | var deferred = Q.defer(), 42 | className = options.className, 43 | replaceProperties = options.replaceProperties, 44 | replacePropertiesForUpsert = options.replacePropertiesForUpsert, 45 | resourceDefinition = options.resourceDefinition, 46 | useUpsert = options.useUpsert || false, 47 | validateCreate = options.validateCreate, 48 | validateReplace = options.validateReplace, 49 | validateReplaceWithUpsert = options.validateReplaceWithUpsert; 50 | 51 | var resources, replacedResource, readResource, createdResource, beforeCount; 52 | 53 | client["read" + className + "s"](parentLink).toArrayAsync() 54 | // create or upsert 55 | .then(function (response) { 56 | resources = response.feed; 57 | assert.equal(resources.constructor, Array, "Value should be an array"); 58 | beforeCount = resources.length; 59 | if (parentLink && useUpsert) { 60 | return client["upsert" + className + "Async"](parentLink, resourceDefinition); 61 | } else if (parentLink) { 62 | return client["create" + className + "Async"](parentLink, resourceDefinition); 63 | } else { 64 | return client["create" + className + "Async"](resourceDefinition); 65 | } 66 | }) 67 | // read 68 | .then(function (response) { 69 | createdResource = response.resource; 70 | validateCreate(createdResource); 71 | return client["read" + className + "s"](parentLink).toArrayAsync(); 72 | }) 73 | // query 74 | .then(function (response) { 75 | var resources = response.feed; 76 | assert(resources.length > 0, "number of resources for the query should be > 0"); 77 | if (parentLink) { 78 | var querySpec = { 79 | query: "select * FROM root r WHERE r.id=@id", 80 | parameters: [ 81 | { 82 | name: "@id", 83 | value: resourceDefinition.id 84 | } 85 | ] 86 | }; 87 | return client["query" + className + "s"](parentLink, querySpec).toArrayAsync(); 88 | } else { 89 | return client["query" + className + "s"](querySpec).toArrayAsync(); 90 | } 91 | }) 92 | // replace or upsert 93 | .then(function (response) { 94 | var resources = response.feed; 95 | assert(resources.length > 0, "number of resources for the query should be > 0"); 96 | if (className === "Database") { 97 | createdResource = replaceProperties(createdResource); 98 | return client["read" + className + "Async"](createdResource._self); 99 | } else { 100 | if (useUpsert) { 101 | createdResource = replacePropertiesForUpsert(createdResource); 102 | return client["upsert" + className + "Async"](parentLink, createdResource); 103 | } else { 104 | createdResource = replaceProperties(createdResource); 105 | return client["replace" + className + "Async"](createdResource._self, createdResource); 106 | } 107 | } 108 | }) 109 | // read 110 | .then(function (response) { 111 | replacedResource = response.resource; 112 | if (useUpsert) { 113 | validateReplaceWithUpsert(createdResource, replacedResource); 114 | } else { 115 | validateReplace(createdResource, replacedResource); 116 | } 117 | return client["read" + className + "Async"](replacedResource._self); 118 | }) 119 | // delete 120 | .then(function (response) { 121 | var readResource = response.resource; 122 | assert.equal(replacedResource.id, readResource.id); 123 | return client["delete" + className + "Async"](readResource._self); 124 | }) 125 | // read 126 | .then(function (response) { 127 | client["read" + className + "Async"](replacedResource._self).then( 128 | function (response) { 129 | assert.fail("", "", "request should return an error"); 130 | }, 131 | function (error) { 132 | var notFoundErrorCode = 404; 133 | assert.equal(error.code, notFoundErrorCode, "response should return error code 404"); 134 | deferred.resolve(); 135 | }); 136 | }) 137 | // handle any error 138 | .fail(function (error) { 139 | console.log("error", error, error.stack); 140 | assert.fail("", "", "an error occurred"); 141 | deferred.reject(error); 142 | }); 143 | 144 | return deferred.promise; 145 | } 146 | 147 | function createParentResourcesAsync(client, options) { 148 | var deferred = Q.defer(); 149 | var createdResources = {}; 150 | if (options.db) { 151 | client.createDatabaseAsync({ id: "sample database" }) 152 | .then(function (response) { 153 | var db = createdResources.createdDb = response.resource; 154 | if (options.coll) { 155 | client.createCollectionAsync(db._self, { id: "sample coll" }) 156 | .then(function (response) { 157 | var coll = createdResources.createdCollection = response.resource; 158 | if (options.doc) { 159 | client.createDocumentAsync(coll._self, { id: "sample doc" }) 160 | .then(function (response) { 161 | var doc = createdResources.createdDoc = response.resource; 162 | deferred.resolve(createdResources); 163 | }); 164 | } else if (options.user) { 165 | client.createUserAsync(db._self, { id: "sample user" }) 166 | .then(function (response) { 167 | var user = createdResources.createdUser = response.resource; 168 | deferred.resolve(createdResources); 169 | }); 170 | } else { 171 | deferred.resolve(createdResources); 172 | } 173 | }); 174 | } else if (options.user) { 175 | client.createUserAsync(db._self, { id: "sample user" }) 176 | .then(function (response) { 177 | var user = createdResources.createdUser = response.resource; 178 | deferred.resolve(createdResources); 179 | }); 180 | } else { 181 | deferred.resolve(createdResources); 182 | } 183 | }) 184 | .fail(function (error) { 185 | deferred.reject(error); 186 | }); 187 | } 188 | 189 | return deferred.promise; 190 | } 191 | 192 | // remove all databases from the endpoint before each test 193 | beforeEach(function(done) { 194 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 195 | client.readDatabases().toArrayAsync() 196 | .then(function(result) { 197 | var databases = result.feed; 198 | var length = databases.length; 199 | if(length === 0){ 200 | return done(); 201 | } 202 | 203 | var count = 0; 204 | databases.forEach(function(database){ 205 | client.deleteDatabaseAsync(database._self) 206 | .then(function(){ 207 | count++; 208 | if(count === length){ 209 | done(); 210 | } 211 | }, 212 | function(err){ 213 | console.log(err); 214 | }); 215 | }); 216 | }, 217 | function(err){ 218 | console.log(err); 219 | done(); 220 | }); 221 | }); 222 | 223 | describe("Validate Database CRUD", function() { 224 | it("[promiseApi] Should do database CRUD operations successfully", function(done){ 225 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 226 | var validateOptions = { 227 | className: "Database", 228 | resourceDefinition: {id: "sampleDb"}, 229 | validateCreate: function(created) { 230 | assert.equal(created.id, "sampleDb", "wrong id"); 231 | }, 232 | validateReplace: function (created, replaced) { 233 | // database doesn't support replace. 234 | }, 235 | replaceProperties: function (resource) { 236 | return resource; 237 | } 238 | }; 239 | 240 | validateCRUDAsync(client, undefined, validateOptions) 241 | .then(function() { 242 | done(); 243 | }) 244 | .fail(function(error) { 245 | done(); 246 | }); 247 | 248 | }); 249 | }); 250 | 251 | describe("Validate Collection CRUD", function(){ 252 | it("[promiseApi] Should do collection CRUD operations successfully", function(done){ 253 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 254 | createParentResourcesAsync(client, {db: true}) 255 | .then(function(createdResources) { 256 | var validateOptions = { 257 | className: "Collection", 258 | resourceDefinition: {id: "sample coll", indexingPolicy: { indexingMode: "consistent" } }, 259 | validateCreate: function(created) { 260 | assert.equal(created.id, "sample coll", "wrong id"); 261 | }, 262 | validateReplace: function(created, replaced) { 263 | assert.equal(replaced.indexingPolicy.indexingMode, 264 | "lazy", 265 | "indexingMode should have changed"); 266 | assert.equal(created.id, replaced.id, "id should stay the same"); 267 | }, 268 | replaceProperties: function (resource) { 269 | resource.indexingPolicy.indexingMode = "lazy"; 270 | return resource; 271 | } 272 | }; 273 | 274 | validateCRUDAsync(client, createdResources.createdDb._self, validateOptions) 275 | .then(function() { 276 | done(); 277 | }) 278 | .fail(function(error) { 279 | console.log(error); 280 | done(); 281 | }); 282 | }); 283 | }); 284 | }); 285 | 286 | describe("Validate Document CRUD", function() { 287 | var validateDocumentCrudTest = function (useUpsert, done) { 288 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 289 | createParentResourcesAsync(client, { db: true, coll: true }) 290 | .then(function(createdResources) { 291 | var validateOptions = { 292 | className: "Document", 293 | resourceDefinition: { id: "sample document", foo: "bar", key: "value" }, 294 | validateCreate: function(created) { 295 | assert.equal(created.id, "sample document", "wrong id"); 296 | assert.equal(created.foo, "bar", "wrong property value"); 297 | }, 298 | validateReplace: function(created, replaced) { 299 | assert.equal(replaced.id, "replaced document", "id property should change"); 300 | assert.equal(replaced.foo, "not bar", "property should have changed"); 301 | assert.equal(created.id, replaced.id, "id should stay the same"); 302 | }, 303 | replaceProperties: function(resource) { 304 | resource.id = "replaced document"; 305 | resource.foo = "not bar"; 306 | return resource; 307 | }, 308 | replacePropertiesForUpsert: function (resource) { 309 | resource.foo = "not bar"; 310 | return resource; 311 | }, 312 | validateReplaceWithUpsert: function(created, replaced) { 313 | assert.equal(replaced.foo, "not bar", "property should have changed"); 314 | assert.equal(created.id, replaced.id, "id should stay the same"); 315 | }, 316 | useUpsert: useUpsert 317 | }; 318 | 319 | validateCRUDAsync(client, createdResources.createdCollection._self, validateOptions) 320 | .then(function() { 321 | done(); 322 | }) 323 | .fail(function(error) { 324 | console.log(error); 325 | done(); 326 | }); 327 | }); 328 | }; 329 | 330 | it("[promiseApi] Should do document CRUD operations successfully", function (done) { validateDocumentCrudTest(false, done) }); 331 | it("[promiseApi] Should do document CRUD operations successfully with upsert", function (done) { validateDocumentCrudTest(true, done) }); 332 | 333 | var validateDocumentCrudWithPartitionResolverTest = function(useUpsert, done) { 334 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 335 | var getPartitionResolver = function(collectionLink1, collectionLink2) { 336 | return { 337 | getPartitionKey: function(document) { 338 | return document.id; 339 | }, 340 | resolve: function(partitionKey) { 341 | var endsWith = function(str, suffix) { 342 | return (str.indexOf(suffix, str.length - suffix.length) !== -1); 343 | }; 344 | 345 | if (endsWith(partitionKey, "1")) { 346 | return collectionLink1; 347 | } else { 348 | return collectionLink2; 349 | } 350 | }, 351 | resolveForCreate: function(partitionKey) { 352 | return this.resolve(partitionKey); 353 | }, 354 | resolveForRead: function(partitionKey) { 355 | return [this.resolve(partitionKey)]; 356 | } 357 | }; 358 | } 359 | var querySpec = { 360 | query: "SELECT * FROM root" 361 | }; 362 | 363 | createParentResourcesAsync(client, { db: true }).then(function(createdResources) { 364 | var db = createdResources.createdDb; 365 | client.createCollectionAsync(db._self, { id: "sample coll 1" }).then(function(response) { 366 | var collection1 = response.resource; 367 | client.createCollectionAsync(db._self, { id: "sample coll 2" }).then(function(response) { 368 | var collection2 = response.resource; 369 | 370 | client.partitionResolvers["foo"] = getPartitionResolver(collection1._self, collection2._self); 371 | 372 | client.createDocumentAsync("foo", { id: "sample doc 1" }).then(function(response) { 373 | client.createDocumentAsync("foo", { id: "sample doc 2" }).then(function(response) { 374 | client.createDocumentAsync("foo", { id: "sample doc 11" }).then(function(response) { 375 | client.queryDocuments("foo", querySpec, { partitionKey: "1" }).toArrayAsync().then(function(response) { 376 | assert(response.feed.length === 2, "number of documents in collection 1"); 377 | client.queryDocuments("foo", querySpec, { partitionKey: "2" }).toArrayAsync().then(function(response) { 378 | assert(response.feed.length === 1, "number of documents in collection 2"); 379 | }).then(function() { 380 | done(); 381 | }); 382 | }); 383 | }); 384 | }); 385 | }); 386 | }); 387 | }); 388 | }); 389 | }; 390 | 391 | it("[promiseApi] Should do document CRUD operations with a partition resolver successfully", function (done) { validateDocumentCrudWithPartitionResolverTest(false, done) }); 392 | it("[promiseApi] Should do document CRUD operations with a partition resolver successfully with upsert", function (done) { validateDocumentCrudWithPartitionResolverTest(true, done) }); 393 | 394 | 395 | }); 396 | 397 | describe("Validate Attachment CRUD", function(){ 398 | var createReadableStream = function(firstChunk, secondChunk){ 399 | var readableStream = new Stream.Readable(); 400 | var chunkCount = 0; 401 | readableStream._read = function(n){ 402 | if(chunkCount === 0){ 403 | this.push(firstChunk || "first chunk "); 404 | } else if(chunkCount === 1) { 405 | this.push(secondChunk || "second chunk"); 406 | } else { 407 | this.push(null); 408 | } 409 | chunkCount++; 410 | }; 411 | 412 | return readableStream; 413 | }; 414 | 415 | var readMediaResponse = function(response, callback){ 416 | var data = ""; 417 | response.on("data", function(chunk) { 418 | data += chunk; 419 | }); 420 | response.on("end", function() { 421 | if (response.statusCode >= 300) { 422 | return callback({code: response.statusCode, body: data}); 423 | } 424 | 425 | return callback(undefined, data); 426 | }); 427 | }; 428 | 429 | var validateAttachmentCrudTest = function(useUpsert, done) { 430 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 431 | createParentResourcesAsync(client, { db: true, coll: true, doc: true }) 432 | .then(function(createdResources) { 433 | var attachmentDefinition = { 434 | id: "dynamic attachment", 435 | media: "http://xstore.", 436 | MediaType: "Book", 437 | Author: "My Book Author", 438 | Title: "My Book Title", 439 | contentType: "application/text" 440 | }; 441 | var validateOptions = { 442 | className: "Attachment", 443 | resourceDefinition: attachmentDefinition, 444 | validateCreate: function(created) { 445 | assert.equal(created.MediaType, "Book", "invalid media type"); 446 | assert.equal(created.Author, "My Book Author", "invalid property value"); 447 | }, 448 | validateReplace: function(created, replaced) { 449 | assert.equal(replaced.id, "dynamic attachment replaced", "invalid id"); 450 | assert.equal(replaced.MediaType, "Book", "invalid media type"); 451 | assert.equal(replaced.Author, "new author", "invalid property value"); 452 | }, 453 | replaceProperties: function (resource) { 454 | resource.id = "dynamic attachment replaced" 455 | resource.Author = "new author"; 456 | return resource; 457 | }, 458 | replacePropertiesForUpsert: function(resource) { 459 | resource.Author = "new author"; 460 | return resource; 461 | }, 462 | validateReplaceForUpsert: function(created, replaced) { 463 | assert.equal(replaced.MediaType, "Book", "invalid media type"); 464 | assert.equal(replaced.Author, "new author", "invalid property value"); 465 | } 466 | }; 467 | 468 | validateCRUDAsync(client, createdResources.createdDoc._self, validateOptions) 469 | .then(function() { 470 | done(); 471 | }) 472 | .fail(function(error) { 473 | console.log(error, error.stack); 474 | done(); 475 | }); 476 | }); 477 | }; 478 | 479 | it("[promiseApi] Should do attachment CRUD operations successfully", function (done) { validateAttachmentCrudTest(false, done) }); 480 | it("[promiseApi] Should do attachment CRUD operations successfully with upsert", function(done) { validateAttachmentCrudTest(true, done) }); 481 | 482 | it("[promiseApi] Should do attachment media operations successfully", function(done){ 483 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 484 | var validMediaOptions = { slug: "attachment name", contentType: "application/text" }; 485 | var invalidMediaOptions = { slug: "attachment name", contentType: "junt/test" }; 486 | var validAttachment; 487 | createParentResourcesAsync(client, { db: true, coll: true, doc: true }).then(function (createdResources) { 488 | var document = createdResources.createdDoc; 489 | var validMediaOptions = { slug: "attachment name", contentType: "application/text" }; 490 | // create attachment with invalid content-type 491 | var contentStream = createReadableStream(); 492 | client.createAttachmentAndUploadMediaAsync(document._self, contentStream, invalidMediaOptions).then(function (response) { 493 | assert.fail("", "", "create shouldn't have succeeded"); 494 | }, function (error) { 495 | var badRequestErrorCode = 400; 496 | assert.equal(error.code, badRequestErrorCode); 497 | contentStream = createReadableStream(); 498 | return client.createAttachmentAndUploadMediaAsync(document._self, contentStream, validMediaOptions); 499 | }).then(function (response) { 500 | validAttachment = response.resource; 501 | assert.equal(validAttachment.id, "attachment name", "id of created attachment should be the same as the one in the request"); 502 | return client.readMediaAsync(validAttachment.media); 503 | }).then(function (response) { 504 | assert.equal(response.result, "first chunk second chunk"); 505 | contentStream = createReadableStream("modified first chunk ", "modified second chunk"); 506 | return client.updateMediaAsync(validAttachment.media, contentStream, validMediaOptions); 507 | }).then(function (response) { 508 | return client.readMediaAsync(validAttachment.media); 509 | }).then(function (response) { 510 | // read media streamed 511 | assert.equal(response.result, "modified first chunk modified second chunk"); 512 | client.connectionPolicy.MediaReadMode = DocumentBase.MediaReadMode.Streamed; 513 | return client.readMediaAsync(validAttachment.media); 514 | }).then(function (response) { 515 | readMediaResponse(response.result, function (err, mediaResult) { 516 | assert.equal(err, undefined, "error reading media response"); 517 | assert.equal(mediaResult, "modified first chunk modified second chunk"); 518 | done(); 519 | }); 520 | }).fail(function (error) { 521 | console.log(error); 522 | done(); 523 | }); 524 | }); 525 | }); 526 | }); 527 | 528 | describe("Validate User CRUD", function() { 529 | var userCrudTest = function(useUpsert, done) { 530 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 531 | createParentResourcesAsync(client, { db: true }) 532 | .then(function(createdResources) { 533 | var validateOptions = { 534 | className: "User", 535 | resourceDefinition: { id: "new user" }, 536 | validateCreate: function(created) { 537 | assert.equal(created.id, "new user", "wrong id"); 538 | }, 539 | validateReplace: function(created, replaced) { 540 | assert.equal(replaced.id, "replaced user", "id property should change"); 541 | assert.equal(created.id, replaced.id, "id should stay the same"); 542 | }, 543 | replaceProperties: function(resource) { 544 | resource.id = "replaced user"; 545 | return resource; 546 | }, 547 | validateReplaceForUpsert: function (created, replaced) { 548 | // Upsert on an exisiting user is a No Op 549 | assert.equal(created.id, replaced.id, "id should stay the same"); 550 | }, 551 | replacePropertiesForUpsert: function (resource) { 552 | // no properties other than id to update 553 | return resource; 554 | } 555 | }; 556 | 557 | validateCRUDAsync(client, createdResources.createdDb._self, validateOptions) 558 | .then(function() { 559 | done(); 560 | }) 561 | .fail(function(error) { 562 | console.log(error); 563 | done(); 564 | }); 565 | }); 566 | }; 567 | 568 | it("[promiseApi] Should do User CRUD operations successfully", function(done) { userCrudTest(false, done) }); 569 | it("[promiseApi] Should do User CRUD operations successfully with upsert", function(done) { userCrudTest(true, done) }); 570 | }); 571 | 572 | describe("Validate Permission CRUD", function() { 573 | var permissionCrudTest = function(useUpsert, done) { 574 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 575 | createParentResourcesAsync(client, { db: true, user: true, coll: true }) 576 | .then(function(createdResources) { 577 | var validateOptions = { 578 | className: "Permission", 579 | resourceDefinition: { id: "new permission", permissionMode: DocumentBase.PermissionMode.Read, resource: createdResources.createdCollection._self }, 580 | validateCreate: function(created) { 581 | assert.equal(created.id, "new permission", "wrong id"); 582 | assert.equal(created.permissionMode, DocumentBase.PermissionMode.Read, "wrong permissionMode"); 583 | assert.equal(created.resource, createdResources.createdCollection._self, "wrong resource"); 584 | }, 585 | validateReplace: function(created, replaced) { 586 | assert.equal(replaced.id, "replaced permission", "id property should change"); 587 | assert.equal(replaced.permissionMode, DocumentBase.PermissionMode.All, "permission mode should change"); 588 | assert.equal(created.id, replaced.id, "id should stay the same"); 589 | }, 590 | replaceProperties: function(resource) { 591 | resource.id = "replaced permission"; 592 | resource.permissionMode = DocumentBase.PermissionMode.All; 593 | return resource; 594 | }, 595 | validateReplaceForUpsert: function(created, replaced) { 596 | assert.equal(replaced.permissionMode, DocumentBase.PermissionMode.All, "permission mode should change"); 597 | assert.equal(created.id, replaced.id, "id should stay the same"); 598 | }, 599 | replacePropertiesForUpsert: function(resource) { 600 | resource.permissionMode = DocumentBase.PermissionMode.All; 601 | return resource; 602 | } 603 | }; 604 | 605 | validateCRUDAsync(client, createdResources.createdUser._self, validateOptions) 606 | .then(function() { 607 | done(); 608 | }) 609 | .fail(function(error) { 610 | console.log(error); 611 | done(); 612 | }); 613 | }); 614 | }; 615 | 616 | it("[promiseApi] Should do Permission CRUD operations successfully", function (done) { permissionCrudTest(false, done); }); 617 | it("[promiseApi] Should do Permission CRUD operations successfully with upsert", function (done) { permissionCrudTest(true, done); }); 618 | }); 619 | 620 | describe("Validate Trigger CRUD", function() { 621 | var triggerCrudTest = function(userUpsert, done) { 622 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 623 | createParentResourcesAsync(client, { db: true, coll: true }) 624 | .then(function(createdResources) { 625 | var triggerDefinition = { 626 | id: "sample trigger", 627 | serverScript: function() { var x = 10; }, 628 | triggerType: DocumentBase.TriggerType.Pre, 629 | triggerOperation: DocumentBase.TriggerOperation.All 630 | }; 631 | 632 | var validateOptions = { 633 | className: "Trigger", 634 | resourceDefinition: triggerDefinition, 635 | validateCreate: function(created) { 636 | for (var property in triggerDefinition) { 637 | if (property === "serverScript") { 638 | assert.equal(created.body, "function () { var x = 10; }"); 639 | } else { 640 | assert.equal(created[property], triggerDefinition[property], "property " + property + " should match"); 641 | } 642 | } 643 | }, 644 | validateReplace: function(created, replaced) { 645 | for (var property in triggerDefinition) { 646 | if (property === "serverScript") { 647 | assert.equal(replaced.body, "function () { var x = 20; }"); 648 | } else if (property === "id") { 649 | assert.equal(replaced.id, "sample trigger replaced", "id should match"); 650 | } else { 651 | assert.equal(replaced[property], created[property], "property " + property + " should match"); 652 | } 653 | } 654 | }, 655 | replaceProperties: function (resource) { 656 | resource.id = "sample trigger replaced"; 657 | resource.body = function() { var x = 20; }; 658 | return resource; 659 | }, 660 | validateReplaceForUpsert: function(created, replaced) { 661 | for (var property in triggerDefinition) { 662 | if (property === "serverScript") { 663 | assert.equal(replaced.body, "function () { var x = 20; }"); 664 | } else { 665 | assert.equal(replaced[property], created[property], "property " +property + " should match"); 666 | } 667 | } 668 | }, 669 | replacePropertiesForUpsert: function(resource) { 670 | resource.body = function() { var x = 20; }; 671 | return resource; 672 | } 673 | }; 674 | 675 | validateCRUDAsync(client, createdResources.createdCollection._self, validateOptions) 676 | .then(function() { 677 | done(); 678 | }) 679 | .fail(function(error) { 680 | console.log(error); 681 | done(); 682 | }); 683 | }); 684 | }; 685 | 686 | it("[promiseApi] Should do trigger CRUD operations successfully", function(done) { triggerCrudTest(false, done); }); 687 | it("[promiseApi] Should do trigger CRUD operations successfully with upsert", function(done) { triggerCrudTest(true, done); }); 688 | }); 689 | 690 | describe("Validate UDF CRUD", function() { 691 | var udfCrudTest = function(useUpsert, done) { 692 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 693 | createParentResourcesAsync(client, { db: true, coll: true }) 694 | .then(function(createdResources) { 695 | var udfDefinition = { id: "sample udf", serverScript: function() { var x = 10; } }; 696 | 697 | var validateOptions = { 698 | className: "UserDefinedFunction", 699 | resourceDefinition: udfDefinition, 700 | validateCreate: function(created) { 701 | for (var property in udfDefinition) { 702 | if (property === "serverScript") { 703 | assert.equal(created.body, "function () { var x = 10; }"); 704 | } else { 705 | assert.equal(created[property], udfDefinition[property], "property " + property + " should match"); 706 | } 707 | } 708 | }, 709 | validateReplace: function(created, replaced) { 710 | for (var property in udfDefinition) { 711 | if (property === "serverScript") { 712 | assert.equal(replaced.body, "function () { var x = 20; }"); 713 | } else if (property === "id") { 714 | assert.equal(replaced.id, "sample udf replaced", "id should match"); 715 | } else { 716 | assert.equal(replaced[property], created[property], "property " + property + " should match"); 717 | } 718 | } 719 | }, 720 | replaceProperties: function(resource) { 721 | resource.id = "sample udf replaced"; 722 | resource.body = function () { var x = 20; }; 723 | return resource; 724 | }, 725 | validateReplaceForUpsert: function(created, replaced) { 726 | for (var property in udfDefinition) { 727 | if (property === "serverScript") { 728 | assert.equal(replaced.body, "function () { var x = 20; }"); 729 | } else { 730 | assert.equal(replaced[property], created[property], "property " +property + " should match"); 731 | } 732 | } 733 | }, 734 | replacePropertiesForUpsert: function(resource) { 735 | resource.body = function() { var x = 20; }; 736 | return resource; 737 | } 738 | }; 739 | 740 | validateCRUDAsync(client, createdResources.createdCollection._self, validateOptions) 741 | .then(function() { 742 | done(); 743 | }) 744 | .fail(function(error) { 745 | console.log(error); 746 | done(); 747 | }); 748 | }); 749 | }; 750 | 751 | it("[promiseApi] Should do UDF CRUD operations successfully", function (done) { udfCrudTest(false, done); }); 752 | it("[promiseApi] Should do UDF CRUD operations successfully with upsert", function(done) { udfCrudTest(true, done); }); 753 | }); 754 | 755 | describe("Validate sproc CRUD", function() { 756 | var sprocCrudTest = function(useUpsert, done) { 757 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 758 | createParentResourcesAsync(client, { db: true, coll: true }) 759 | .then(function(createdResources) { 760 | var sprocDefinition = { 761 | id: "sample sproc", 762 | serverScript: function() { var x = 10; } 763 | }; 764 | 765 | var validateOptions = { 766 | className: "StoredProcedure", 767 | resourceDefinition: sprocDefinition, 768 | validateCreate: function(created) { 769 | for (var property in sprocDefinition) { 770 | if (property === "serverScript") { 771 | assert.equal(created.body, "function () { var x = 10; }"); 772 | } else { 773 | assert.equal(created[property], sprocDefinition[property], "property " + property + " should match"); 774 | } 775 | } 776 | }, 777 | validateReplace: function (created, replaced) { 778 | for (var property in sprocDefinition) { 779 | if (property === "serverScript") { 780 | assert.equal(replaced.body, "function () { var x = 20; }"); 781 | } else if (property === "id") { 782 | assert.equal(replaced.id, "sample sproc replaced", "id should match"); 783 | } else { 784 | assert.equal(replaced[property], created[property], "property " + property + " should match"); 785 | } 786 | } 787 | }, 788 | replaceProperties: function (resource) { 789 | resource.id = "sample sproc replaced"; 790 | resource.body = function () { var x = 20; }; 791 | return resource; 792 | }, 793 | validateReplaceForUpsert: function (created, replaced) { 794 | for (var property in sprocDefinition) { 795 | if (property === "serverScript") { 796 | assert.equal(replaced.body, "function () { var x = 20; }"); 797 | } else { 798 | assert.equal(replaced[property], created[property], "property " + property + " should match"); 799 | } 800 | } 801 | }, 802 | replacePropertiesForUpsert: function (resource) { 803 | resource.body = function () { var x = 20; }; 804 | return resource; 805 | } 806 | }; 807 | 808 | validateCRUDAsync(client, createdResources.createdCollection._self, validateOptions) 809 | .then(function() { 810 | done(); 811 | }) 812 | .fail(function(error) { 813 | console.log(error); 814 | done(); 815 | }); 816 | }); 817 | }; 818 | 819 | it("[promiseApi] Should do sproc CRUD operations successfully", function (done) { sprocCrudTest(false, done); }); 820 | it("[promiseApi] Should do sproc CRUD operations successfully with upsert", function(done) { sprocCrudTest(true, done); }); 821 | }); 822 | 823 | describe("Validate QueryIterator Functionality", function() { 824 | var createTestResources = function(client) { 825 | var deferred = Q.defer(); 826 | var db, collection, doc1, doc2, doc3; 827 | client.createDatabaseAsync({ id: "sample database" }) 828 | .then(function(response) { 829 | db = response.resource; 830 | return client.createCollectionAsync(db._self, {id: "sample collection"}); 831 | }) 832 | .then(function(response) { 833 | collection = response.resource; 834 | return client.createDocumentAsync(collection._self, {id: "doc1", prop1: "value1"}); 835 | }) 836 | .then(function(response) { 837 | doc1 = response.resource; 838 | return client.createDocumentAsync(collection._self, {id: "doc2", prop1: "value2"}); 839 | }) 840 | .then(function(response) { 841 | doc2 = response.resource; 842 | return client.createDocumentAsync(collection._self, {id: "doc3", prop1: "value3"}); 843 | }) 844 | .then(function(response) { 845 | doc3 = response.resource; 846 | var resources = { 847 | coll: collection, 848 | doc1: doc1, 849 | doc2: doc2, 850 | doc3: doc3 851 | }; 852 | deferred.resolve(resources); 853 | }) 854 | .fail(function(error){ 855 | deferred.reject(error); 856 | }); 857 | 858 | return deferred.promise; 859 | }; 860 | 861 | it("[promiseApi] validate QueryIterator iterator toArray", function(done) { 862 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 863 | createTestResources(client) 864 | .then(function(resources) { 865 | var queryIterator = client.readDocuments(resources.coll._self, {maxItemCount: 2}); 866 | queryIterator.toArrayAsync() 867 | .then(function(response) { 868 | var docs = response.feed; 869 | assert.equal(docs.length, 3, "queryIterator should return all documents using continuation"); 870 | assert.equal(docs[0].id, resources.doc1.id); 871 | assert.equal(docs[1].id, resources.doc2.id); 872 | assert.equal(docs[2].id, resources.doc3.id); 873 | done(); 874 | }) 875 | .fail(function(error){ 876 | console.log("An error has occurred", error, error.stack); 877 | done(); 878 | }); 879 | }) 880 | .fail(function(error){ 881 | console.log("An error has occurred", error, error.stack); 882 | done(); 883 | }); 884 | }); 885 | 886 | it("[promiseApi] validate queryIterator iterator forEach", function(done) { 887 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 888 | createTestResources(client) 889 | .then(function(resources) { 890 | var queryIterator = client.readDocuments(resources.coll._self, {maxItemCount: 2}); 891 | var counter = 0; 892 | // test queryIterator.forEach 893 | queryIterator.forEach(function(err, doc) { 894 | if (err) { 895 | console.log("an error occurred", err, err.stack); 896 | return done(); 897 | } 898 | 899 | counter++; 900 | if (counter === 1) { 901 | assert.equal(doc.id, resources.doc1.id, "first document should be doc1"); 902 | } else if(counter === 2) { 903 | assert.equal(doc.id, resources.doc2.id, "second document should be doc2"); 904 | } else if(counter === 3) { 905 | assert.equal(doc.id, resources.doc3.id, "third document should be doc3"); 906 | } 907 | 908 | if (doc === undefined) { 909 | assert(counter < 5, "iterator should have stopped"); 910 | return done(); 911 | } 912 | }); 913 | }) 914 | .fail(function(error){ 915 | console.log("An error has occurred", error, error.stack); 916 | done(); 917 | }); 918 | }); 919 | 920 | it("[promiseApi] validate queryIterator nextItem and hasMoreResults", function(done) { 921 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 922 | createTestResources(client) 923 | .then(function(resources) { 924 | var queryIterator = client.readDocuments(resources.coll._self, {maxItemCount: 2}); 925 | assert.equal(queryIterator.hasMoreResults(), true); 926 | queryIterator.nextItemAsync() 927 | .then(function(response) { 928 | var doc = response.resource; 929 | assert.equal(doc.id, resources.doc1.id, "call queryIterator.nextItem after reset should return first document"); 930 | assert.equal(queryIterator.hasMoreResults(), true); 931 | return queryIterator.nextItemAsync(); 932 | }) 933 | .then(function(response) { 934 | var doc = response.resource; 935 | assert.equal(doc.id, resources.doc2.id, "call queryIterator.nextItem again should return second document"); 936 | assert.equal(queryIterator.hasMoreResults(), true); 937 | return queryIterator.nextItemAsync(); 938 | }) 939 | .then(function(response) { 940 | var doc = response.resource; 941 | assert.equal(doc.id, resources.doc3.id, "call queryIterator.nextItem again should return third document"); 942 | return queryIterator.nextItemAsync(); 943 | }) 944 | .then(function(response) { 945 | var doc = response.resource; 946 | assert.equal(doc, undefined, "queryIterator should return undefined if there is no elements"); 947 | done(); 948 | }) 949 | .fail(function(error){ 950 | console.log("An error has occurred", error, error.stack); 951 | done(); 952 | }); 953 | }) 954 | .fail(function(error){ 955 | console.log("An error has occurred", error, error.stack); 956 | done(); 957 | }); 958 | }); 959 | 960 | it("[promiseApi] validate queryIterator iterator executeNext", function(done) { 961 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 962 | createTestResources(client) 963 | .then(function(resources) { 964 | var queryIterator = client.readDocuments(resources.coll._self, {maxItemCount: 2}); 965 | queryIterator.executeNextAsync() 966 | .then(function(response) { 967 | var docs = response.feed; 968 | assert.equal(docs.length, 2, "first batch size should be 2"); 969 | assert.equal(docs[0].id, resources.doc1.id, "first batch first document should be doc1"); 970 | assert.equal(docs[1].id, resources.doc2.id, "batch first second document should be doc2"); 971 | return queryIterator.executeNextAsync(); 972 | }) 973 | .then(function(response) { 974 | var docs = response.feed; 975 | assert.equal(docs.length, 1, "second batch size should be 2"); 976 | assert.equal(docs[0].id, resources.doc3.id, "second batch element should be doc3"); 977 | done(); 978 | }) 979 | .fail(function(error){ 980 | console.log("An error has occurred", error, error.stack); 981 | done(); 982 | }); 983 | }) 984 | .fail(function(error){ 985 | console.log("An error has occurred", error, error.stack); 986 | done(); 987 | }); 988 | }); 989 | }); 990 | 991 | describe("validate trigger functionality", function(){ 992 | var triggers = [ 993 | { 994 | id: "t1", 995 | body: function() { 996 | var item = getContext().getRequest().getBody(); 997 | item.id = item.id.toUpperCase() + "t1"; 998 | getContext().getRequest().setBody(item); 999 | }, 1000 | triggerType: DocumentBase.TriggerType.Pre, 1001 | triggerOperation: DocumentBase.TriggerOperation.All 1002 | }, 1003 | { 1004 | id: "t2", 1005 | body: "function() { }", // trigger already stringified 1006 | triggerType: DocumentBase.TriggerType.Pre, 1007 | triggerOperation: DocumentBase.TriggerOperation.All 1008 | }, 1009 | { 1010 | id: "t3", 1011 | body: function() { 1012 | var item = getContext().getRequest().getBody(); 1013 | item.id = item.id.toLowerCase() + "t3"; 1014 | getContext().getRequest().setBody(item); 1015 | }, 1016 | triggerType: DocumentBase.TriggerType.Pre, 1017 | triggerOperation: DocumentBase.TriggerOperation.All 1018 | }, 1019 | { 1020 | id: "response1", 1021 | body: function() { 1022 | var prebody = getContext().getRequest().getBody(); 1023 | if (prebody.id !== "TESTING POST TRIGGERt1") throw "id mismatch"; 1024 | var postbody = getContext().getResponse().getBody(); 1025 | if (postbody.id !== "TESTING POST TRIGGERt1") throw "id mismatch"; 1026 | }, 1027 | triggerType: DocumentBase.TriggerType.Post, 1028 | triggerOperation: DocumentBase.TriggerOperation.All 1029 | }, 1030 | { 1031 | id: "triggerOpType", 1032 | body: "function() { }", 1033 | triggerType: DocumentBase.TriggerType.Post, 1034 | triggerOperation: DocumentBase.TriggerOperation.Delete 1035 | } 1036 | ]; 1037 | 1038 | 1039 | var createTriggersImplementation = function(client, collection, index, deferred){ 1040 | if (index === triggers.length) { 1041 | return deferred.resolve(); 1042 | } 1043 | 1044 | client.createTriggerAsync(collection._self, triggers[index]) 1045 | .then(function(trigger) { 1046 | createTriggersImplementation(client, collection, index + 1, deferred); 1047 | }) 1048 | .fail(function(error){ 1049 | console.log(error, error.stack); 1050 | }); 1051 | }; 1052 | 1053 | var createTriggersAsync = function(client, collection, index) { 1054 | var deferred = Q.defer(); 1055 | createTriggersImplementation(client, collection, index, deferred); 1056 | return deferred.promise; 1057 | }; 1058 | 1059 | it("[promiseApi] Should do trigger operations successfully", function(done){ 1060 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 1061 | createParentResourcesAsync(client, {db: true, coll: true}) 1062 | .then(function(resources) { 1063 | var collection = resources.createdCollection; 1064 | createTriggersAsync(client, collection, 0) 1065 | .then(function(){ 1066 | return client.createDocumentAsync(collection._self, { id: "doc1", key: "value" }, { preTriggerInclude: "t1" }); 1067 | }) 1068 | .then(function(response) { 1069 | assert.equal(response.resource.id, "DOC1t1", "id should be capitalized"); 1070 | return client.createDocumentAsync(collection._self, { id: "doc2", key2: "value2" }, { preTriggerInclude: "t2" }); 1071 | }) 1072 | .then(function(response) { 1073 | assert.equal(response.resource.id, "doc2", "id shouldn't change"); 1074 | return client.createDocumentAsync(collection._self, { id: "Doc3", prop: "empty" }, { preTriggerInclude: "t3" }); 1075 | }) 1076 | .then(function(response) { 1077 | assert.equal(response.resource.id, "doc3t3"); 1078 | return client.createDocumentAsync(collection._self, { id: "testing post trigger" }, { postTriggerInclude: "response1", preTriggerInclude: "t1" }); 1079 | }) 1080 | .then(function(response) { 1081 | assert.equal(response.resource.id, "TESTING POST TRIGGERt1"); 1082 | return client.createDocumentAsync(collection._self, { id: "responseheaders" }, { preTriggerInclude: "t1" }); 1083 | }) 1084 | .then(function(response) { 1085 | assert.equal(response.resource.id, "RESPONSEHEADERSt1"); 1086 | return client.createDocumentAsync(collection._self, { id: "Docoptype" }, { postTriggerInclude: "triggerOpType" }); 1087 | }) 1088 | .then(function(response) { 1089 | assert.fail("", "", "request shouldn't succeed"); 1090 | }, 1091 | function(error){ 1092 | done(); 1093 | }) 1094 | .fail(function(error) { 1095 | console.log("error", error, error.stack); 1096 | assert.fail("", "", "an error occurred"); 1097 | done(); 1098 | }); 1099 | }) 1100 | .fail(function(error) { 1101 | console.log("error", error, error.stack); 1102 | assert.fail("", "", "an error occurred"); 1103 | done(); 1104 | }); 1105 | }); 1106 | }); 1107 | 1108 | describe("validate stored procedure functionality", function () { 1109 | it("[promiseApi] Should do stored procedure operations successfully", function (done) { 1110 | var client = new DocumentDBClient(host, {masterKey: masterKey}); 1111 | createParentResourcesAsync(client, {db: true, coll: true}).then(function(resources) { 1112 | var collection = resources.createdCollection; 1113 | var sproc1 = { 1114 | id: "storedProcedure1", 1115 | body: function () { 1116 | for (var i = 0; i < 1000; i++) { 1117 | var item = getContext().getResponse().getBody(); 1118 | if (i > 0 && item !== i - 1) throw "body mismatch"; 1119 | getContext().getResponse().setBody(i); 1120 | } 1121 | } 1122 | }; 1123 | 1124 | client.createStoredProcedureAsync(collection._self, sproc1).then(function (response) { 1125 | return client.executeStoredProcedureAsync(response.resource._self); 1126 | }).then(function(response) { 1127 | assert.equal(response.result, 999); 1128 | var sproc2 = { 1129 | id: "storedProcedure2", 1130 | body: function () { 1131 | for (var i = 0; i < 10; i++) getContext().getResponse().appendValue("Body", i); 1132 | } 1133 | }; 1134 | 1135 | return client.createStoredProcedureAsync(collection._self, sproc2); 1136 | }).then(function(response) { 1137 | return client.executeStoredProcedureAsync(response.resource._self); 1138 | }).then(function(response) { 1139 | assert.equal(response.result, 123456789); 1140 | var sproc3 = { 1141 | id: "storedProcedure3", 1142 | body: function (input) { 1143 | getContext().getResponse().setBody("a" + input.temp); 1144 | } 1145 | }; 1146 | 1147 | return client.createStoredProcedureAsync(collection._self, sproc3); 1148 | }).then(function(response) { 1149 | return client.executeStoredProcedureAsync(response.resource._self, {temp: "so"}); 1150 | }).then(function(response) { 1151 | assert.equal(response.result, "aso"); 1152 | done(); 1153 | }).fail(function(error) { 1154 | console.log("error", error, error.stack); 1155 | assert.fail("", "", "an error occurred"); 1156 | done(); 1157 | }); 1158 | }).fail(function(error) { 1159 | console.log("error", error, error.stack); 1160 | assert.fail("", "", "an error occurred"); 1161 | done(); 1162 | }); 1163 | }); 1164 | }); 1165 | 1166 | describe("Validate Offer CRUD", function () { 1167 | it("[promiseApi] Should do offer CRUD operations successfully", function (done) { 1168 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 1169 | var existingOffer; 1170 | createParentResourcesAsync(client, { db: true, coll: true }) 1171 | .then(function (createdResources) { 1172 | return client.readOffers().toArrayAsync(); 1173 | }).then(function (result) { 1174 | var offers = result.feed; 1175 | assert.equal(offers.length, 1); 1176 | existingOffer = offers[0]; 1177 | assert.equal(existingOffer.offerType, "S1"); // S1 is the default type 1178 | return client.readOfferAsync(existingOffer._self); 1179 | }).then(function (response) { 1180 | var readOffer = response.resource; 1181 | assert.equal(readOffer.id, existingOffer.id); 1182 | assert.equal(readOffer._rid, existingOffer._rid); 1183 | assert.equal(readOffer._self, existingOffer._self); 1184 | assert.equal(readOffer.offerType, existingOffer.offerType); 1185 | // Replace offer. 1186 | readOffer.offerType = "S2"; 1187 | return client.replaceOfferAsync(readOffer._self, readOffer); 1188 | }).then(function (response) { 1189 | var replacedOffer = response.resource; 1190 | assert.equal(replacedOffer.offerType, "S2"); 1191 | // Query for offer. 1192 | var querySpec = { 1193 | query: "select * FROM root r WHERE r.id=@id", 1194 | parameters: [ 1195 | { 1196 | name: "@id", 1197 | value: existingOffer.id 1198 | } 1199 | ] 1200 | }; 1201 | return client.queryOffers(querySpec).toArrayAsync(); 1202 | }).then(function (result) { 1203 | var offers = result.feed; 1204 | assert.equal(offers.length, 1); 1205 | var oneOffer = offers[0]; 1206 | assert.equal(oneOffer.offerType, "S2"); 1207 | done(); 1208 | }).fail(function (error) { 1209 | console.log(error, error.stack); 1210 | done(); 1211 | }); 1212 | }); 1213 | 1214 | it("[promiseApi] Should create Collection with specified offer type successfully", function (done) { 1215 | var client = new DocumentDBClient(host, { masterKey: masterKey }); 1216 | 1217 | client.createDatabaseAsync({ id: "sample database" }) 1218 | .then(function (response) { 1219 | var db = response.resource; 1220 | return client.createCollectionAsync(db._self, { id: "sample coll" }, { offerType: "S2" }); 1221 | }).then(function (response) { 1222 | return client.readOffers().toArrayAsync(); 1223 | }).then(function (result) { 1224 | var offers = result.feed; 1225 | assert.equal(offers.length, 1); 1226 | var existingOffer = offers[0]; 1227 | assert.equal(existingOffer.offerType, "S2"); // S2 is what we created. 1228 | done(); 1229 | }).fail(function (error) { 1230 | console.log(error, error.stack); 1231 | done(); 1232 | }); 1233 | }); 1234 | }); 1235 | }); --------------------------------------------------------------------------------