Simplified Azure Table Storage client library for NodeJS.
What is supported:
- creating, deleting and listing tables
- creating, updating, querying and deleting entities
- batch operation support
- generating SAS (Shared Access Signature) and using it for authentication
What will likely be added in the future:
- get and set service properties
Default client uses environment variable to set up the access key and storage URL if possible. It looks for the CLOUD_STORAGE_ACCOUNT
setting with three elements (it is the default format used by Azure Storage):
TableEndpoint=http://accountName.table.core.windows.net/;AccountName=accountName;AccountKey=theKey
No error is returned if this doesn't exists, is incomplete or malformed.
Current version does not support quotes and AccountKey must be the last one to be parsed correctly. This will be fixed in the future.
If the environment variable is not set, the default connection info have to be set using below command to be usable:
var azureTable = require('azure-table-node');
azureTable.setDefaultClient({
accountUrl: 'http://accountName.table.core.windows.net/',
accountName: 'accountName',
accountKey: 'theKey'
});
The same method allows to set other default client settings (see Client settings).
var azureTable = require('azure-table-node');
var defaultClient = azureTable.getDefaultClient();
// use the client to create the table
defaultClient.createTable('tableName', true, cb);
// or insert entity
defaultClient.insert('table', entity, options, cb);
It is possible to create additional clients that are based on other client (or on default settings), but customized and independent. This allows to for example use several table storage accounts but still have one default for convenience.
var azureTable = require('azure-table-node');
var tableClient = azureTable.createClient({
// predefined settings
}, [baseClient]);
Base client is the client on which the new one will be based. If not provided, it is based on the default one.
var client = azureTable.getDefaultClient();
client.insertEntity('testtable', {
PartitionKey: 'tests',
RowKey: 'insert',
value1: 'ABCDEFG'
}, function(err, data) {
// err is null
// data contains etag
});
client.getEntity('testtable', 'tests', 'tests', function(err, data) {
// err is null
// data contains the object with entity
});
client.queryEntities('testtable', {
query: azureTable.Query.create('PartitionKey', '==', 'tests')
limitTo: 20,
onlyFields: ['RowKey', 'value1']
}, function(err, data, continuation) {
// err is null
// data contains the array of objects (entities)
// continuation is undefined or two element array to be passed to next query
});
client.deleteEntity('testtable', {
PartitionKey: 'tests',
RowKey: 'insert',
__etag: 'W/"datetime\'2014-01-23T07%3A34%3A30.4871837Z\'"'
}, function(err, data) {
// err is null
// data is undefined
});
var batchClient = client.startBatch();
batchClient.updateEntity('testtable', {
PartitionKey: 'tests',
RowKey: 'insert1',
value: 11
}, {force: true}).deleteEntity('testtable', {
PartitionKey: 'tests',
RowKey: 'insert2',
__etag: 'W/"datetime\'2014-01-31T10%3A14%3A18.918655Z\'"'
}).commit(function(err, data) {
// err is null
// data to be an array of results
});
Account related:
accountUrl
(string) - URL of the service's endpoint (no default value)accountName
(string) - name of the used account (no default value)accountKey
(string) - base64 encoded account key (no default value), may be null ifsas
is providedsas
(string) - SAS query string that can be used instead of accountKey (in some less trusted environment) (no default value)
Underlying HTTP request related (passed without changes to request module):
timeout
(int) - request timeout in miliseconds (default: 30000)proxy
(string) - proxy URLforever
(bool) - usetrue
to turn advanced socket reuseagent
(Agent) - already created agent object (do not setproxy
,forever
orpool
is set (may not work otherwise)agentOptions
(object) - used to set maxSockets option for forever or standard agentpool
(false|object) - usefalse
to turn off socket reuse
Azure Table Storage related:
metadata
(string) - default metadata level, available values:no
,minimal
,full
(default:minimal
); ifno
is used, you have to take care yourself of changing Date, int64 and binary from strings to proper objectsretry
(false/object/function) - set tofalse
to turn off any retry policy; provide a function for custom retry logic or use object to change parameter of build in retry logic
Retry options:
retries
(int) - a number of retries (default: 3)firstDelay
(int) - delay of the first retry request in ms (default: 2000ms)nextDelayMult
(float) - delay multiplier using previous delay as a base (default: 2); use 1 for linear delayvariability
(float) - random delay multiplier added or subtracted from current delay (default 0.2)transientErrors
(array of ints or strings) - describes situations where retry should be used; if it is int, status code is checked for equality; for string the code element of error or response is checked (default:[500, 501, 502, 503, 'ETIMEDOUT', 'ECONNRESET', 'EADDRINUSE', 'ESOCKETTIMEDOUT']
Custom retry function should support below parameters (in order of appearance):
requestOptions
(object) - if needed it can be edited in place to change request options and headersnextReq
(function) - function to be called to make a request.
The nextReq
function must be called passing additional function retryFn
with below parameters:
err
(object) - null or error object from response (see normal response callback)resp
(object/array) - response object (see normal response callback)nextResp
(function) - function to be called when there is no need for a retry passing (err
andresp
to it)
As by default request headers are not regenerated on retries, the retry time of of the last one cannot be very long, because authentication will fail.
Example retry function which retries every time code
in error is ETIMEDOUT
:
function _retryLogic(requestOptions, nextReq) {
function retryFn(err, resp, nextResp) {
if (err && err.code === 'ETIMEDOUT') {
nextReq(retryFn);
} else {
nextResp(err, resp);
}
}
nextReq(retryFn);
}
In case of reties, the default retry function returns retriesMade
key in error informing about the number of retries made (helps in debugging).
If not explained differently, cb
in API is a functions in format function cb(err, data)
. For queries there may be additional third argument passed if there is a continuation token.
Returns default Client
object. If setDefaultClient()
was not used earlier the client only have default module settings and environment variable applied.
Sets up and returns default Client
object with provided settings
. It is using default settings as a base.
Returns new Client
object using new settings and base
client settings as a fallback. If base
is not provided, uses default client settings.
Returns new Client
object using only provided settings object. Shouldn't be used directly unless you want to provide all options. Use createClient
from main module if possible.
Returns sealed settings object used by this client.
Creates new table. The table
is table name. The options
is optional, but if exists and ignoreIfExists
key equals true
, the error 'table already exists' is ignored. The cb
is a standard callback function.
Removes existing table. The table
is table name. The cb
is a standard callback function.
Returns array with table names (as strings). The options
is optional, but if exists and nextTableName
key is provided, the retrieval will start from last continuation token. The cb
is a standard callback function, but if continuation is required, the third argument will be passed with value for nextTableName
key.
Creates new entity
in table
. The entity
must at least contain PartitionKey
and RowKey
as strings. The options
have one setting supported returnEntity
. If set to true
, it will return the entity in data
element in entity key (etag will be in __etag
property). Otherwise function will return etag in data (as string).
Creates new entity
in table
. If it exists, it will be replaced. The entity
must contain PartitionKey
and RowKey
as strings. The data
contains etag of inserted/replaced entity.
Creates new entity
in table
. If it exists, passed values will be merged with existing ones. The entity
must contain PartitionKey
and RowKey
as strings. The data
contains etag of inserted/merged entity.
Updates entity
in table
. The entity
must contain PartitionKey
and RowKey
as strings and also __etag
if force
is not used. The options
object is optional. Use key force
set to true
to not use etag for optimistic concurrency. The data
in callback contains new etag value.
Merge update of entity
in table
. The entity
must contain PartitionKey
and RowKey
as strings and also __etag
if force
is not used. The options
object is optional. Use key force
set to true
to not use etag for optimistic concurrency. The data
in callback contains new etag value.
Removes entity
from table
. The entity
must contain PartitionKey
and RowKey
as strings and also __etag
if force
is not used. The options
object is optional. Use key force
set to true
to not use etag for optimistic concurrency. The data
in callback will always be undefined.
Retrieves one entity from table
. Entity is located by partitionKey
and rowKey
values as strings. The options
object is optional. Use onlyFields
as array of strings to retrieve only mentioned fields.
Retrieve up to 1000 entities as array. The options
is optional. If not used first 1000 entities of table will be returned (or less if they do not exist). Callback will receive in data
an array of entities. If not everything was returned, the third argument will contain two element array with continuation tokens. The should be used in options to retrieve next part of results.
Options can contain below elements. All are optional:
query
-- theQuery
object for returned entities filtering or string with properly created$filter
query string (for very advanced queries), see Querying EntitieslimitTo
-- integer, if provided it will return no more than this resultsonlyFields
-- array of strings to retrieve only mentioned fieldsforceEtags
-- if set totrue
it will force of etag retrieval (even if full metadata is not set for this client)continuation
-- array with two strings working as continuation token (array is returned as third argument in previous query)
This method will return new object that you use to prepare a batch. All methods available on Client
can be used, but because of the limitations of Azure Table Storage (like only one query in batch) you should limit yourself only to insert, update, merge and delete operations. Do not provide callback functions to those methods. Otherwise the results may not be as expected. After adding all of them (up to 100) call commit()
to send the batch.
Sends the batch request. Requires only callback function. In case of error the callback's first parameter will receive error info for operation that was the reason of the error. If the whole batch was committed, second argument will contain array of responses for each operation.
Generates and returns the SAS (Shared Access Signature) query string to use in requests. The returned query string is already encoded and should be added after the main REST URL and other parameters. The table
is the table for which SAS is generated. The permissions
is a string with up to 4 characters describing permissions allowed on table: r
(get/querying), a
(insert), u
(update), d
(delete). Permissions must be provided in exactly the order mentioned and some operations like upsert may require both insert and update permissions. The expiry
is the Date object with SAS expiration date. The options
is an object with all other optional SAS restrictions:
start
(Date) - date describing time when SAS should start to be validpolicyId
(string) - string with the policy identifierstartPK
(string) - the first partition key that is allowedstartRK
(string) - the first row key that is allowedendPK
(string) - the last partition key that is allowedendRK
(string) - the last row key that is allowed
The Key
part is a string with field name. It can also be a PartitionKey
or RowKey
, but if only one row is going to be returned without additional filters, it is better to use getEntity()
method.
The comparison
only allows 6 standard comparison operators passed as strings: ==
, !=
, <
, >
, >=
, and <=
. Passing anything else will end up throwing exception.
The value
element can be a string, number, boolean or Date
object. Everything else will be converted to string using toString()
.
Creates and returns new Query
object. For convenience it can use where()
parameters. If all three are provided, Query.create('a', '==', 'b')
is equivalent of Query.create().where('a', '==', 'b')
.
Adds first query element. Cannot be used after the first one (will throw exception). Returns Query
object.
Adds next query element using AND clause. Cannot be used as the first one (will throw exception). Returns Query
object.
Adds next query element using OR clause. Cannot be used as the first one (will throw exception). Returns Query
object.
Will negate next element. Returns Query
object.
Run the tests using mocha from main project folder. But before that set the environment variable as some tests are relying on default:
set CLOUD_STORAGE_ACCOUNT=TableEndpoint=http://dummy.table.core.windows.net/;AccountName=dummy;AccountKey=DWFdvtgaJ/4okdYJs1sAr1yyvrRe4dAuY5yPg+R+Wsl5wMiX6QOZ+6egJseLXK8YlDASx6eP0bfWV3rgZlgxYA==
mocha