├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── advanced.js ├── app.config ├── basic.js ├── config.js ├── package.json └── tableSample.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Azure samples 2 | 3 | Thank you for your interest in contributing to Azure samples! 4 | 5 | ## Ways to contribute 6 | 7 | You can contribute to [Azure samples](https://azure.microsoft.com/documentation/samples/) in a few different ways: 8 | 9 | - Submit feedback on [this sample page](https://azure.microsoft.com/documentation/samples/storage-table-node-getting-started/) whether it was helpful or not. 10 | - Submit issues through [issue tracker](https://github.com/Azure-Samples/storage-table-node-getting-started/issues) on GitHub. We are actively monitoring the issues and improving our samples. 11 | - If you wish to make code changes to samples, or contribute something new, please follow the [GitHub Forks / Pull requests model](https://help.github.com/articles/fork-a-repo/): Fork the sample repo, make the change and propose it back by submitting a pull request. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | services: storage 3 | platforms: nodejs 4 | author: minet-MSFT 5 | --- 6 | 7 | # Getting Started with Azure Table Service in Node.js 8 | Demonstrates how to perform common tasks using Azure Table storage and Azure Cosmos DB Table API 9 | including creating a table, CRUD operations, batch operations and different querying techniques. 10 | 11 | If you don't have a Microsoft Azure subscription you can 12 | get a FREE trial account [here](http://go.microsoft.com/fwlink/?LinkId=330212) 13 | 14 | ## Running this sample 15 | 16 | ### Azure Cosmos DB Table API 17 | 18 | 1. Go to your Azure Cosmos DB Table API instance in the Azure Portal and select 19 | "Connection String" in the menu, select the Read-write Keys tab and copy the value 20 | in the "CONNECTION STRING" field. 21 | 2. Open the app.config file and set the configuration for the emulator to false 22 | ("useDevelopmentStorage": false) and set the connection string to the value from step 1 23 | ("connectionString":""). 24 | 3. Run the sample by: node ./tableSample.js 25 | 26 | #### More Information 27 | -[Introduction to Azure Cosmos DB Table API](https://docs.microsoft.com/en-us/azure/cosmos-db/table-introduction) 28 | 29 | ### Azure Table storage 30 | 31 | This sample can be run using either the Azure Storage Emulator that installs as part of this SDK - or by 32 | supply a connection string. 33 | 34 | To run the sample using the Storage Emulator (default option): 35 | 36 | 1. Download and Install the Azure Storage Emulator [here](http://azure.microsoft.com/en-us/downloads/). 37 | 2. Start the Azure Storage Emulator (once only) by pressing the Start button or the Windows key and 38 | searching for it by typing "Azure Storage Emulator". Select it from the list of applications to start it. 39 | 3. Open the app.config file and set the configuration for the emulator ("useDevelopmentStorage":true). 40 | 4. Run the sample by: node ./tableSample.js 41 | 42 | To run the sample using the Storage Service 43 | 44 | 1. Go to your Azure Storage account in the Azure Portal and under "SETTINGS" click on "Access keys". 45 | Copy either key1 or key2's "CONNECTION STRING". 46 | 2. Open the app.config file and set the configuration for the emulator to false ("useDevelopmentStorage":false) 47 | and set the connection string for the storage service ("connectionString":""). 48 | 3. Run the sample by: node ./tableSample.js 49 | 50 | #### More Information 51 | - [What is a Storage Account](http://azure.microsoft.com/en-us/documentation/articles/storage-whatis-account/) 52 | - [Getting Started with Tables](https://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-table-storage/) 53 | - [Table Service Concepts](http://msdn.microsoft.com/en-us/library/dd179463.aspx) 54 | - [Table Service REST API](http://msdn.microsoft.com/en-us/library/dd179423.aspx) 55 | - [Table Service Node API](http://azure.github.io/azure-storage-node/TableService.html) 56 | - [Storage Emulator](http://msdn.microsoft.com/en-us/library/azure/hh403989.aspx) 57 | -------------------------------------------------------------------------------- /advanced.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------- 2 | // Microsoft Developer & Platform Evangelism 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | // 6 | // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 7 | // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 8 | // OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 9 | //---------------------------------------------------------------------------------- 10 | // The example companies, organizations, products, domain names, 11 | // e-mail addresses, logos, people, places, and events depicted 12 | // herein are fictitious. No association with any real company, 13 | // organization, product, domain name, email address, logo, person, 14 | // places, or events is intended or should be inferred. 15 | //---------------------------------------------------------------------------------- 16 | 17 | var fs = require('fs'); 18 | var guid = require('node-uuid'); 19 | var storage = require('azure-storage'); 20 | var config = require('./config.js'); 21 | 22 | var entityGen; 23 | var tableService; 24 | 25 | function AdvancedAzureTableSamples() { 26 | entityGen = storage.TableUtilities.entityGenerator; 27 | tableService = storage.createTableService(config.connectionString); 28 | 29 | scenarios = [ 30 | { 31 | action: listAllTables, 32 | message: 'Azure Table List Sample\n' 33 | }, 34 | { 35 | action: tableOperationsWithSas, 36 | message: 'Azure Table Operations with SAS\n' 37 | } 38 | ]; 39 | 40 | advancedAzureStorageTablesScenarios = [ 41 | { 42 | action: corsRules, 43 | message: 'Table CORS Sample\n' 44 | }, 45 | { 46 | action: serviceProperties, 47 | message: 'Table Service Properties Sample\n' 48 | }, 49 | { 50 | action: tableAcl, 51 | message: 'Table Access Policy Sample\n' 52 | } 53 | ]; 54 | 55 | allScenarios = scenarios 56 | if (!config.connectionString.includes('table.cosmosdb')){ 57 | allScenarios = scenarios.concat(advancedAzureStorageTablesScenarios); 58 | } 59 | return allScenarios; 60 | } 61 | 62 | 63 | function listAllTables(callback) { 64 | tableService.createTableIfNotExists("Advanced" + guid.v1().replace(/-/g, ''), function (error, created) { 65 | if (error) return callback(error); 66 | 67 | tableService.createTableIfNotExists("Advanced" + guid.v1().replace(/-/g, ''), function (error, created) { 68 | if (error) return callback(error); 69 | 70 | listTables('Advanced', tableService, null, { maxResults: 100 }, null, function (error, tables) { 71 | if (error) return callback(error); 72 | 73 | tables.forEach(function (table) { 74 | console.log("Table: " + table); 75 | 76 | tableService.deleteTable(table, null, function (error) { 77 | if (!error) console.log('Table ' + table + ' deleted.'); 78 | 79 | return callback(error); 80 | }) 81 | }) 82 | }) 83 | }) 84 | }) 85 | }; 86 | 87 | function tableOperationsWithSas(callback) { 88 | // Create or reference an existing table 89 | var tableName = "Customers" + guid.v1().replace(/-/g, ''); 90 | tableService.createTableIfNotExists(tableName, function tableCreated(error, createResult) { 91 | if (error) return callback(error); 92 | 93 | if (createResult.isSuccessful) { 94 | console.log("1. Create Table operation executed successfully for: ", tableName); 95 | } 96 | 97 | var expiryDate = new Date(); 98 | 99 | expiryDate.setMinutes(expiryDate.getMinutes() + 30); 100 | 101 | var sharedAccessPolicy = { 102 | AccessPolicy: { 103 | Permissions: storage.TableUtilities.SharedAccessPermissions.QUERY 104 | + storage.TableUtilities.SharedAccessPermissions.ADD 105 | + storage.TableUtilities.SharedAccessPermissions.UPDATE 106 | + storage.TableUtilities.SharedAccessPermissions.DELETE, 107 | Expiry: expiryDate 108 | }, 109 | }; 110 | 111 | var sas = tableService.generateSharedAccessSignature(tableName, sharedAccessPolicy); 112 | 113 | var sharedTableService = storage.createTableServiceWithSas(tableService.host, sas); 114 | 115 | console.log("2. Inserting or updating an entity with Shared Access Signature."); 116 | var customer = createCustomerEntityDescriptor("Harp", "Walter", "Walter@contoso.com", "425-555-0101"); 117 | 118 | sharedTableService.insertOrMergeEntity(tableName, customer, function (error, result, response) { 119 | if (error) return callback(error); 120 | 121 | console.log(" insertOrMergeEntity succeeded."); 122 | 123 | console.log("3. Reading the updated entity with Shared Access Signature."); 124 | 125 | // Demonstrate the most efficient storage query - the point query - where both partition key and row key are specified. 126 | sharedTableService.retrieveEntity(tableName, customer.PartitionKey._, customer.RowKey._, function (error, result) { 127 | if (error) return callback(error); 128 | 129 | console.log(" retrieveEntity succeeded: ", result.PartitionKey._, result.RowKey._, result.email._, result.phone._); 130 | 131 | console.log("4. Deleting the entity with Shared Access Signature. "); 132 | 133 | sharedTableService.deleteEntity(tableName, customer, function entitiesQueried(error, result) { 134 | if (error) return callback(error); 135 | 136 | console.log(" deleteEntity succeeded."); 137 | 138 | console.log('5. Deleting table'); 139 | tableService.deleteTable(tableName, function (error) { 140 | callback(error); 141 | }); 142 | }); 143 | }); 144 | }); 145 | }); 146 | }; 147 | 148 | 149 | // Get Cors properties, change them and revert back to original 150 | function corsRules(callback) { 151 | 152 | console.log('Get service properties'); 153 | tableService.getServiceProperties(function (error, properties) { 154 | if (error) return callback(error); 155 | 156 | console.log('Set Cors rules in the service properties'); 157 | 158 | // Keeps the original Cors rules 159 | var originalCors = properties.Cors; 160 | 161 | properties.Cors = { 162 | CorsRule: [{ 163 | AllowedOrigins: ['*'], 164 | AllowedMethods: ['POST', 'GET', 'HEAD', 'PUT'], 165 | AllowedHeaders: ['*'], 166 | ExposedHeaders: ['*'], 167 | MaxAgeInSeconds: 3600 168 | }] 169 | }; 170 | 171 | tableService.setServiceProperties(properties, function (error) { 172 | if (error) return callback(error); 173 | 174 | console.log('Cors rules set successfuly'); 175 | 176 | // reverts the cors rules back to the original ones so they do not get corrupted by the ones set in this sample 177 | properties.Cors = originalCors; 178 | 179 | tableService.setServiceProperties(properties, function (error) { 180 | return callback(error); 181 | }); 182 | 183 | }); 184 | }); 185 | } 186 | 187 | 188 | // Manage logging and metrics service properties 189 | function serviceProperties(callback) { 190 | // Create a blob client for interacting with the blob service from connection string 191 | // How to create a storage connection string - http://msdn.microsoft.com/en-us/library/azure/ee758697.aspx 192 | var blobService = storage.createBlobService(config.connectionString); 193 | 194 | console.log('Get service properties'); 195 | blobService.getServiceProperties(function (error, properties) { 196 | if (error) return callback(error); 197 | 198 | var originalProperties = properties; 199 | 200 | properties = serviceProperties = { 201 | Logging: { 202 | Version: '1.0', 203 | Delete: true, 204 | Read: true, 205 | Write: true, 206 | RetentionPolicy: { 207 | Enabled: true, 208 | Days: 10, 209 | }, 210 | }, 211 | HourMetrics: { 212 | Version: '1.0', 213 | Enabled: true, 214 | IncludeAPIs: true, 215 | RetentionPolicy: { 216 | Enabled: true, 217 | Days: 10, 218 | }, 219 | }, 220 | MinuteMetrics: { 221 | Version: '1.0', 222 | Enabled: true, 223 | IncludeAPIs: true, 224 | RetentionPolicy: { 225 | Enabled: true, 226 | Days: 10, 227 | }, 228 | } 229 | }; 230 | 231 | console.log('Set service properties'); 232 | blobService.setServiceProperties(properties, function (error) { 233 | if (error) return callback(error); 234 | 235 | // reverts the service properties back to the original ones so they do not get corrupted by the ones set in this sample 236 | blobService.setServiceProperties(originalProperties, function (error) { 237 | return callback(error); 238 | }); 239 | }); 240 | }); 241 | } 242 | 243 | // Retrieve statistics related to replication for the Table service 244 | function serviceStats(callback) { 245 | 246 | console.log('Get service statistics'); 247 | tableService.getServiceStats(function (error, serviceStats){ 248 | if (error) return callback(error); 249 | 250 | callback(null); 251 | }); 252 | 253 | } 254 | 255 | // Manage access policies of the table 256 | function tableAcl(callback) { 257 | var tableName = "AclTable" + guid.v1().replace(/-/g, ''); 258 | console.log('Create table'); 259 | tableService.createTableIfNotExists(tableName, function() { 260 | 261 | // Set access policy 262 | var expiryDate = new Date(); 263 | expiryDate.setMinutes(expiryDate.getMinutes() + 10); 264 | 265 | var sharedAccessPolicy = { 266 | sampleIDForTablePolicy: { 267 | Permissions: storage.TableUtilities.SharedAccessPermissions.PROCESS, 268 | Expiry: expiryDate 269 | } 270 | }; 271 | 272 | console.log('Set table access policy'); 273 | tableService.setTableAcl(tableName, sharedAccessPolicy, function (error, result, response) { 274 | if (error) return callback(error); 275 | 276 | // Get access policy 277 | console.log('Get table access policy'); 278 | tableService.getTableAcl(tableName, function(error, result, response) { 279 | if (error) return callback(error); 280 | 281 | console.log(' Permissions: ' + result.signedIdentifiers.sampleIDForTablePolicy.Permissions); 282 | console.log(' Expiry: ' + result.signedIdentifiers.sampleIDForTablePolicy.Expiry.toISOString()); 283 | 284 | console.log('Delete table'); 285 | tableService.deleteTable(tableName, function () { 286 | callback(error); 287 | }); 288 | }); 289 | }); 290 | }); 291 | } 292 | 293 | 294 | 295 | /** 296 | * Lists tables in the container. 297 | * @ignore 298 | * 299 | * @param {string} prefix The prefix of the table name. 300 | * @param {TableService} tableService The table service client. 301 | * @param {object} token A continuation token returned by a previous listing operation. 302 | * Please use 'null' or 'undefined' if this is the first operation. 303 | * @param {object} [options] The request options. 304 | * @param {int} [options.maxResults] Specifies the maximum number of tables to return per call to Azure ServiceClient. 305 | * This does NOT affect list size returned by this function. (maximum: 5000) 306 | * @param {errorOrResult} callback `error` will contain information 307 | * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`. 308 | * `entries` gives a list of tables and the `continuationToken` is used for the next listing operation. 309 | * `response` will contain information related to this operation. 310 | */ 311 | function listTables(prefix, tableService, token, options, tables, callback) { 312 | tables = tables || []; 313 | 314 | tableService.listTablesSegmentedWithPrefix(prefix, token, options, function (error, result) { 315 | 316 | if (error) return callback(error, null); 317 | 318 | tables.push.apply(tables, result.entries); 319 | 320 | var token = result.continuationToken; 321 | 322 | if (token) { 323 | console.log(' Received a segment of results. There are ' + result.entries.length + ' tables on this segment.'); 324 | listTables(prefix, tableService, token, options, callback); 325 | } else { 326 | console.log(' Completed listing. There are ' + tables.length + ' tables.'); 327 | callback(null, tables); 328 | } 329 | }) 330 | } 331 | 332 | /** 333 | * Creates a customer entity to be used in library calls based on provided parameters 334 | * @ignore 335 | * 336 | * @param {string} partitionKey Last name of the customer 337 | * @param {string} rowKey Name of the customer 338 | * @param {string} email Email of the customer 339 | * @param {string} phone Phone number of the customer 340 | * @return {Object} 341 | */ 342 | function createCustomerEntityDescriptor(partitionKey, rowKey, email, phone) { 343 | var customerEntity = { 344 | PartitionKey: entityGen.String(partitionKey), 345 | RowKey: entityGen.String(rowKey), 346 | email: entityGen.String(email), 347 | phone: entityGen.String(phone) 348 | }; 349 | return customerEntity; 350 | } 351 | 352 | module.exports = AdvancedAzureTableSamples(); -------------------------------------------------------------------------------- /app.config: -------------------------------------------------------------------------------- 1 | { 2 | "useDevelopmentStorage": false, 3 | "connectionString": "", 4 | "sas": "" 5 | } -------------------------------------------------------------------------------- /basic.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------- 2 | // Microsoft Developer & Platform Evangelism 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | // 6 | // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 7 | // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 8 | // OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 9 | //---------------------------------------------------------------------------------- 10 | // The example companies, organizations, products, domain names, 11 | // e-mail addresses, logos, people, places, and events depicted 12 | // herein are fictitious. No association with any real company, 13 | // organization, product, domain name, email address, logo, person, 14 | // places, or events is intended or should be inferred. 15 | //---------------------------------------------------------------------------------- 16 | 17 | var fs = require('fs'); 18 | var guid = require('node-uuid'); 19 | var storage = require('azure-storage'); 20 | var config = require('./config.js'); 21 | 22 | var entityGen; 23 | var storageClient; 24 | var tableName; 25 | 26 | function BasicAzureTableSamples() { 27 | 28 | entityGen = storage.TableUtilities.entityGenerator; 29 | storageClient = storage.createTableService(config.connectionString); 30 | tableName = "Customers" + guid.v1().replace(/-/g, ''); 31 | 32 | return scenarios = [ 33 | { 34 | action: basicTableOperations, 35 | message: 'Azure Table Basic Sample\n' 36 | } 37 | ]; 38 | } 39 | 40 | function basicTableOperations(callback) { 41 | // Create or reference an existing table 42 | storageClient.createTableIfNotExists(tableName, function (error, createResult) { 43 | if (error) return callback(error); 44 | 45 | if (createResult.isSuccessful) { 46 | console.log("1. Create Table operation executed successfully for: ", tableName); 47 | } 48 | 49 | console.log("2. Inserting or updating an entity using insertOrMergeEntity function."); 50 | var customer = createCustomerEntityDescriptor("Harp", "Walter", "Walter@contoso.com", "425-555-0101"); 51 | 52 | storageClient.insertOrMergeEntity(tableName, customer, function (error, result, response) { 53 | if (error) return callback(error); 54 | 55 | console.log(" insertOrMergeEntity succeeded."); 56 | 57 | console.log("3. Reading the updated entity."); 58 | 59 | // Demonstrate the most efficient storage query - the point query - where both partition key and row key are specified. 60 | storageClient.retrieveEntity(tableName, customer.PartitionKey._, customer.RowKey._, function (error, result) { 61 | if (error) return callback(error); 62 | 63 | console.log(" retrieveEntity succeeded: ", result.PartitionKey._, result.RowKey._, result.email._, result.phone._); 64 | 65 | console.log("4. Deleting the entity. "); 66 | 67 | storageClient.deleteEntity(tableName, customer, function entitiesQueried(error, result) { 68 | if (error) return callback(error); 69 | 70 | console.log(" deleteEntity succeeded."); 71 | 72 | // Demonstrates upsert and batch table operations 73 | console.log("5. Inserting a batch of entities. "); 74 | 75 | // create batch operation 76 | var batch = new storage.TableBatch(); 77 | var lastName = "Smith"; 78 | 79 | // The following code generates test data for use during the query samples. 80 | for (var i = 0; i < 100; i++) { 81 | var name = zeroPaddingString(i, 4); 82 | var customerToInsert = createCustomerEntityDescriptor(lastName, name, name + "@contoso.com", "425-555-" + name) 83 | 84 | batch.insertEntity(customerToInsert); 85 | } 86 | 87 | // Demonstrate inserting of a large batch of entities. Some considerations for batch operations: 88 | // 1. You can perform updates, deletes, and inserts in the same single batch operation. 89 | // 2. A single batch operation can include up to 100 entities. 90 | // 3. All entities in a single batch operation must have the same partition key. 91 | // 4. While it is possible to perform a query as a batch operation, it must be the only operation in the batch. 92 | // 5. Batch size must be <= 4MB 93 | storageClient.executeBatch(tableName, batch, function (error, result, response) { 94 | if (error) return callback(error); 95 | 96 | console.log(" Batch insert completed."); 97 | console.log("6. Retrieving entities with surname of Smith and first names > 1 and <= 75"); 98 | 99 | var storageTableQuery = storage.TableQuery; 100 | var segmentSize = 10; 101 | 102 | // Demonstrate a partition range query whereby we are searching within a partition for a set of entities that are within a specific range. 103 | var tableQuery = new storageTableQuery() 104 | .top(segmentSize) 105 | .where('PartitionKey eq ?', lastName) 106 | .and('RowKey gt ?', "0001").and('RowKey le ?', "0075"); 107 | 108 | runPageQuery(tableQuery, null, function (error, result) { 109 | 110 | if (error) return callback(error); 111 | 112 | // Demonstrate a partition scan whereby we are searching for all the entities within a partition. 113 | // Note this is not as efficient as a range scan - but definitely more efficient than a full table scan. 114 | console.log("7. Retrieve entities with surname of %s.", lastName); 115 | 116 | var tableQuery = new storageTableQuery() 117 | .top(segmentSize) 118 | .where('PartitionKey eq ?', lastName); 119 | 120 | runPageQuery(tableQuery, null, function (error) { 121 | 122 | if (error) return callback(error); 123 | 124 | storageClient.deleteTable(tableName, function (error, response) { 125 | if (error) return callback(error); 126 | 127 | console.log(" deleteTable succeeded."); 128 | 129 | callback(); 130 | }); 131 | }); 132 | }); 133 | }); 134 | }); 135 | }); 136 | }); 137 | }); 138 | }; 139 | 140 | /** 141 | * Runs a table query with specific page size and continuationToken 142 | * @ignore 143 | * 144 | * @param {TableQuery} tableQuery Query to execute 145 | * @param {TableContinuationToken} continuationToken Continuation token to continue a query 146 | * @param {function} callback Additional sample operations to run after this one completes 147 | */ 148 | function runPageQuery(tableQuery, continuationToken, callback) { 149 | 150 | storageClient.queryEntities(tableName, tableQuery, continuationToken, function (error, result) { 151 | if (error) return callback(error); 152 | 153 | var entities = result.entries; 154 | entities.forEach(function (entity) { 155 | console.log(" Customer: %s,%s,%s,%s,%s,%s,%s", entity.PartitionKey._, entity.RowKey._, entity.email._, entity.phone._, entity.since._, entity.isEnterprise._, entity.code._) 156 | }); 157 | 158 | continuationToken = result.continuationToken; 159 | if (continuationToken) { 160 | runPageQuery(tableQuery, continuationToken, callback); 161 | } else { 162 | console.log(" Query completed."); 163 | callback(); 164 | } 165 | }); 166 | } 167 | 168 | /** 169 | * Adds paddings to a string. 170 | * @ignore 171 | * 172 | * @param {string} str The input string. 173 | * @param {int} len The length of the string. 174 | * @return {string} 175 | */ 176 | function zeroPaddingString(str, len) { 177 | var paddingStr = '0000000000' + str; 178 | if (paddingStr.length < len) { 179 | return zeroPaddingString(paddingStr, len); 180 | } else { 181 | return paddingStr.substr(-1 * len); 182 | } 183 | } 184 | 185 | 186 | 187 | /** 188 | * Creates a customer entity to be used in library calls based on provided parameters 189 | * @ignore 190 | * 191 | * @param {string} partitionKey Last name of the customer 192 | * @param {string} rowKey Name of the customer 193 | * @param {string} email Email of the customer 194 | * @param {string} phone Phone number of the customer 195 | * @return {Object} 196 | */ 197 | function createCustomerEntityDescriptor(partitionKey, rowKey, email, phone) { 198 | var customerEntity = { 199 | PartitionKey: entityGen.String(partitionKey), 200 | RowKey: entityGen.String(rowKey), 201 | email: entityGen.String(email), 202 | phone: entityGen.String(phone), 203 | code: entityGen.Int32(1), 204 | isEnterprise: entityGen.Boolean(false), 205 | since: entityGen.DateTime(new Date(Date.UTC(2011, 10, 25))), 206 | }; 207 | return customerEntity; 208 | } 209 | 210 | module.exports = BasicAzureTableSamples(); -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------- 2 | // Microsoft Developer & Platform Evangelism 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | // 6 | // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 7 | // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 8 | // OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 9 | //---------------------------------------------------------------------------------- 10 | // The example companies, organizations, products, domain names, 11 | // e-mail addresses, logos, people, places, and events depicted 12 | // herein are fictitious. No association with any real company, 13 | // organization, product, domain name, email address, logo, person, 14 | // places, or events is intended or should be inferred. 15 | //---------------------------------------------------------------------------------- 16 | 17 | var fs = require('fs'); 18 | var storage = require('azure-storage'); 19 | 20 | /** 21 | * Reads the configurations. 22 | * @ignore 23 | * 24 | * @return {Object} 25 | */ 26 | function readConfig() { 27 | var config = JSON.parse(fs.readFileSync('app.config', 'utf8')); 28 | if (config.useDevelopmentStorage) { 29 | config.connectionString = storage.generateDevelopmentStorageCredentials(); 30 | } 31 | return config; 32 | } 33 | 34 | module.exports = readConfig(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "storage-table-node-getting-started", 3 | "version": "0.0.1", 4 | "author": { 5 | "name": "Microsoft Corporation" 6 | }, 7 | "description": "Basic Operations with Azure Storage Table Service", 8 | "tags": [ 9 | "azure", 10 | "storage", 11 | "sample" 12 | ], 13 | "keywords": [ 14 | "node", 15 | "azure", 16 | "storage" 17 | ], 18 | "main": "./tableSample.js", 19 | "engines": { 20 | "node": ">= 0.8.26" 21 | }, 22 | "scripts": { 23 | "start": "node tableSample.js", 24 | "check": "jshint tableSample.js" 25 | }, 26 | "dependencies": { 27 | "azure-storage": "~2.5.0", 28 | "node-uuid": "~1.4.0" 29 | }, 30 | "devDependencies": { 31 | "jshint": "*" 32 | }, 33 | "jshintConfig":{ 34 | "node": true 35 | }, 36 | "homepage": "https://github.com/Azure-Samples/storage-table-node-getting-started", 37 | "repository": { 38 | "type": "git", 39 | "url": "git@github.com:Azure-Samples/storage-table-node-getting-started.git" 40 | }, 41 | "bugs": { 42 | "url": "https://github.com/Azure-Samples/storage-table-node-getting-started/issues" 43 | }, 44 | "readmeFilename": "README.md" 45 | } 46 | -------------------------------------------------------------------------------- /tableSample.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------- 2 | // Microsoft Developer & Platform Evangelism 3 | // 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | // 6 | // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 7 | // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 8 | // OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 9 | //---------------------------------------------------------------------------------- 10 | // The example companies, organizations, products, domain names, 11 | // e-mail addresses, logos, people, places, and events depicted 12 | // herein are fictitious. No association with any real company, 13 | // organization, product, domain name, email address, logo, person, 14 | // places, or events is intended or should be inferred. 15 | //---------------------------------------------------------------------------------- 16 | 17 | var basicScenarios = require('./basic.js'); 18 | var advancedScenarios = require('./advanced.js'); 19 | 20 | runAzureTableSamples(); 21 | 22 | function runAzureTableSamples() { 23 | console.log('\nAzure Cosmos DB Table API and Azure Table storage samples\n'); 24 | 25 | var scenarios = basicScenarios.concat(advancedScenarios); 26 | 27 | var current = 0; 28 | 29 | var callback = function (error) { 30 | if (error) { 31 | throw error; 32 | } else { 33 | if (current < scenarios.length) 34 | console.log(scenarios[current].message); 35 | 36 | current++; 37 | if (current < scenarios.length) { 38 | scenarios[current].action(callback); 39 | } 40 | } 41 | }; 42 | 43 | scenarios[current].action(callback); 44 | } 45 | --------------------------------------------------------------------------------