123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- var AWS = require('../core');
- var Translator = require('./translator');
- var DynamoDBSet = require('./set');
- /**
- * The document client simplifies working with items in Amazon DynamoDB
- * by abstracting away the notion of attribute values. This abstraction
- * annotates native JavaScript types supplied as input parameters, as well
- * as converts annotated response data to native JavaScript types.
- *
- * ## Marshalling Input and Unmarshalling Response Data
- *
- * The document client affords developers the use of native JavaScript types
- * instead of `AttributeValue`s to simplify the JavaScript development
- * experience with Amazon DynamoDB. JavaScript objects passed in as parameters
- * are marshalled into `AttributeValue` shapes required by Amazon DynamoDB.
- * Responses from DynamoDB are unmarshalled into plain JavaScript objects
- * by the `DocumentClient`. The `DocumentClient`, does not accept
- * `AttributeValue`s in favor of native JavaScript types.
- *
- * | JavaScript Type | DynamoDB AttributeValue |
- * |:----------------------------------------------------------------------:|-------------------------|
- * | String | S |
- * | Number | N |
- * | Boolean | BOOL |
- * | null | NULL |
- * | Array | L |
- * | Object | M |
- * | Buffer, File, Blob, ArrayBuffer, DataView, and JavaScript typed arrays | B |
- *
- * ## Support for Sets
- *
- * The `DocumentClient` offers a convenient way to create sets from
- * JavaScript Arrays. The type of set is inferred from the first element
- * in the array. DynamoDB supports string, number, and binary sets. To
- * learn more about supported types see the
- * [Amazon DynamoDB Data Model Documentation](http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html)
- * For more information see {AWS.DynamoDB.DocumentClient.createSet}
- *
- */
- AWS.DynamoDB.DocumentClient = AWS.util.inherit({
- /**
- * Creates a DynamoDB document client with a set of configuration options.
- *
- * @option options params [map] An optional map of parameters to bind to every
- * request sent by this service object.
- * @option options service [AWS.DynamoDB] An optional pre-configured instance
- * of the AWS.DynamoDB service object. This instance's config will be
- * copied to a new instance used by this client. You should not need to
- * retain a reference to the input object, and may destroy it or allow it
- * to be garbage collected.
- * @option options convertEmptyValues [Boolean] set to true if you would like
- * the document client to convert empty values (0-length strings, binary
- * buffers, and sets) to be converted to NULL types when persisting to
- * DynamoDB.
- * @option options wrapNumbers [Boolean] Set to true to return numbers as a
- * NumberValue object instead of converting them to native JavaScript numbers.
- * This allows for the safe round-trip transport of numbers of arbitrary size.
- * @see AWS.DynamoDB.constructor
- *
- */
- constructor: function DocumentClient(options) {
- var self = this;
- self.options = options || {};
- self.configure(self.options);
- },
- /**
- * @api private
- */
- configure: function configure(options) {
- var self = this;
- self.service = options.service;
- self.bindServiceObject(options);
- self.attrValue = options.attrValue =
- self.service.api.operations.putItem.input.members.Item.value.shape;
- },
- /**
- * @api private
- */
- bindServiceObject: function bindServiceObject(options) {
- var self = this;
- options = options || {};
- if (!self.service) {
- self.service = new AWS.DynamoDB(options);
- } else {
- var config = AWS.util.copy(self.service.config);
- self.service = new self.service.constructor.__super__(config);
- self.service.config.params =
- AWS.util.merge(self.service.config.params || {}, options.params);
- }
- },
- /**
- * @api private
- */
- makeServiceRequest: function(operation, params, callback) {
- var self = this;
- var request = self.service[operation](params);
- self.setupRequest(request);
- self.setupResponse(request);
- if (typeof callback === 'function') {
- request.send(callback);
- }
- return request;
- },
- /**
- * @api private
- */
- serviceClientOperationsMap: {
- batchGet: 'batchGetItem',
- batchWrite: 'batchWriteItem',
- delete: 'deleteItem',
- get: 'getItem',
- put: 'putItem',
- query: 'query',
- scan: 'scan',
- update: 'updateItem',
- transactGet: 'transactGetItems',
- transactWrite: 'transactWriteItems'
- },
- /**
- * Returns the attributes of one or more items from one or more tables
- * by delegating to `AWS.DynamoDB.batchGetItem()`.
- *
- * Supply the same parameters as {AWS.DynamoDB.batchGetItem} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.batchGetItem
- * @example Get items from multiple tables
- * var params = {
- * RequestItems: {
- * 'Table-1': {
- * Keys: [
- * {
- * HashKey: 'haskey',
- * NumberRangeKey: 1
- * }
- * ]
- * },
- * 'Table-2': {
- * Keys: [
- * { foo: 'bar' },
- * ]
- * }
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.batchGet(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- batchGet: function(params, callback) {
- var operation = this.serviceClientOperationsMap['batchGet'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Puts or deletes multiple items in one or more tables by delegating
- * to `AWS.DynamoDB.batchWriteItem()`.
- *
- * Supply the same parameters as {AWS.DynamoDB.batchWriteItem} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.batchWriteItem
- * @example Write to and delete from a table
- * var params = {
- * RequestItems: {
- * 'Table-1': [
- * {
- * DeleteRequest: {
- * Key: { HashKey: 'someKey' }
- * }
- * },
- * {
- * PutRequest: {
- * Item: {
- * HashKey: 'anotherKey',
- * NumAttribute: 1,
- * BoolAttribute: true,
- * ListAttribute: [1, 'two', false],
- * MapAttribute: { foo: 'bar' }
- * }
- * }
- * }
- * ]
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.batchWrite(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- batchWrite: function(params, callback) {
- var operation = this.serviceClientOperationsMap['batchWrite'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Deletes a single item in a table by primary key by delegating to
- * `AWS.DynamoDB.deleteItem()`
- *
- * Supply the same parameters as {AWS.DynamoDB.deleteItem} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.deleteItem
- * @example Delete an item from a table
- * var params = {
- * TableName : 'Table',
- * Key: {
- * HashKey: 'hashkey',
- * NumberRangeKey: 1
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.delete(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- delete: function(params, callback) {
- var operation = this.serviceClientOperationsMap['delete'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Returns a set of attributes for the item with the given primary key
- * by delegating to `AWS.DynamoDB.getItem()`.
- *
- * Supply the same parameters as {AWS.DynamoDB.getItem} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.getItem
- * @example Get an item from a table
- * var params = {
- * TableName : 'Table',
- * Key: {
- * HashKey: 'hashkey'
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.get(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- get: function(params, callback) {
- var operation = this.serviceClientOperationsMap['get'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Creates a new item, or replaces an old item with a new item by
- * delegating to `AWS.DynamoDB.putItem()`.
- *
- * Supply the same parameters as {AWS.DynamoDB.putItem} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.putItem
- * @example Create a new item in a table
- * var params = {
- * TableName : 'Table',
- * Item: {
- * HashKey: 'haskey',
- * NumAttribute: 1,
- * BoolAttribute: true,
- * ListAttribute: [1, 'two', false],
- * MapAttribute: { foo: 'bar'},
- * NullAttribute: null
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.put(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- put: function(params, callback) {
- var operation = this.serviceClientOperationsMap['put'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Edits an existing item's attributes, or adds a new item to the table if
- * it does not already exist by delegating to `AWS.DynamoDB.updateItem()`.
- *
- * Supply the same parameters as {AWS.DynamoDB.updateItem} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.updateItem
- * @example Update an item with expressions
- * var params = {
- * TableName: 'Table',
- * Key: { HashKey : 'hashkey' },
- * UpdateExpression: 'set #a = :x + :y',
- * ConditionExpression: '#a < :MAX',
- * ExpressionAttributeNames: {'#a' : 'Sum'},
- * ExpressionAttributeValues: {
- * ':x' : 20,
- * ':y' : 45,
- * ':MAX' : 100,
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.update(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- update: function(params, callback) {
- var operation = this.serviceClientOperationsMap['update'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Returns one or more items and item attributes by accessing every item
- * in a table or a secondary index.
- *
- * Supply the same parameters as {AWS.DynamoDB.scan} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.scan
- * @example Scan the table with a filter expression
- * var params = {
- * TableName : 'Table',
- * FilterExpression : 'Year = :this_year',
- * ExpressionAttributeValues : {':this_year' : 2015}
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.scan(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- scan: function(params, callback) {
- var operation = this.serviceClientOperationsMap['scan'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Directly access items from a table by primary key or a secondary index.
- *
- * Supply the same parameters as {AWS.DynamoDB.query} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.query
- * @example Query an index
- * var params = {
- * TableName: 'Table',
- * IndexName: 'Index',
- * KeyConditionExpression: 'HashKey = :hkey and RangeKey > :rkey',
- * ExpressionAttributeValues: {
- * ':hkey': 'key',
- * ':rkey': 2015
- * }
- * };
- *
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * documentClient.query(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- query: function(params, callback) {
- var operation = this.serviceClientOperationsMap['query'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Synchronous write operation that groups up to 100 action requests.
- *
- * Supply the same parameters as {AWS.DynamoDB.transactWriteItems} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.transactWriteItems
- * @example Get items from multiple tables
- * var params = {
- * TransactItems: [{
- * Put: {
- * TableName : 'Table0',
- * Item: {
- * HashKey: 'haskey',
- * NumAttribute: 1,
- * BoolAttribute: true,
- * ListAttribute: [1, 'two', false],
- * MapAttribute: { foo: 'bar'},
- * NullAttribute: null
- * }
- * }
- * }, {
- * Update: {
- * TableName: 'Table1',
- * Key: { HashKey : 'hashkey' },
- * UpdateExpression: 'set #a = :x + :y',
- * ConditionExpression: '#a < :MAX',
- * ExpressionAttributeNames: {'#a' : 'Sum'},
- * ExpressionAttributeValues: {
- * ':x' : 20,
- * ':y' : 45,
- * ':MAX' : 100,
- * }
- * }
- * }]
- * };
- *
- * documentClient.transactWrite(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- */
- transactWrite: function(params, callback) {
- var operation = this.serviceClientOperationsMap['transactWrite'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Atomically retrieves multiple items from one or more tables (but not from indexes)
- * in a single account and region.
- *
- * Supply the same parameters as {AWS.DynamoDB.transactGetItems} with
- * `AttributeValue`s substituted by native JavaScript types.
- *
- * @see AWS.DynamoDB.transactGetItems
- * @example Get items from multiple tables
- * var params = {
- * TransactItems: [{
- * Get: {
- * TableName : 'Table0',
- * Key: {
- * HashKey: 'hashkey0'
- * }
- * }
- * }, {
- * Get: {
- * TableName : 'Table1',
- * Key: {
- * HashKey: 'hashkey1'
- * }
- * }
- * }]
- * };
- *
- * documentClient.transactGet(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- */
- transactGet: function(params, callback) {
- var operation = this.serviceClientOperationsMap['transactGet'];
- return this.makeServiceRequest(operation, params, callback);
- },
- /**
- * Creates a set of elements inferring the type of set from
- * the type of the first element. Amazon DynamoDB currently supports
- * the number sets, string sets, and binary sets. For more information
- * about DynamoDB data types see the documentation on the
- * [Amazon DynamoDB Data Model](http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html#DataModel.DataTypes).
- *
- * @param list [Array] Collection to represent your DynamoDB Set
- * @param options [map]
- * * **validate** [Boolean] set to true if you want to validate the type
- * of each element in the set. Defaults to `false`.
- * @example Creating a number set
- * var documentClient = new AWS.DynamoDB.DocumentClient();
- *
- * var params = {
- * Item: {
- * hashkey: 'hashkey'
- * numbers: documentClient.createSet([1, 2, 3]);
- * }
- * };
- *
- * documentClient.put(params, function(err, data) {
- * if (err) console.log(err);
- * else console.log(data);
- * });
- *
- */
- createSet: function(list, options) {
- options = options || {};
- return new DynamoDBSet(list, options);
- },
- /**
- * @api private
- */
- getTranslator: function() {
- return new Translator(this.options);
- },
- /**
- * @api private
- */
- setupRequest: function setupRequest(request) {
- var self = this;
- var translator = self.getTranslator();
- var operation = request.operation;
- var inputShape = request.service.api.operations[operation].input;
- request._events.validate.unshift(function(req) {
- req.rawParams = AWS.util.copy(req.params);
- req.params = translator.translateInput(req.rawParams, inputShape);
- });
- },
- /**
- * @api private
- */
- setupResponse: function setupResponse(request) {
- var self = this;
- var translator = self.getTranslator();
- var outputShape = self.service.api.operations[request.operation].output;
- request.on('extractData', function(response) {
- response.data = translator.translateOutput(response.data, outputShape);
- });
- var response = request.response;
- response.nextPage = function(cb) {
- var resp = this;
- var req = resp.request;
- var config;
- var service = req.service;
- var operation = req.operation;
- try {
- config = service.paginationConfig(operation, true);
- } catch (e) { resp.error = e; }
- if (!resp.hasNextPage()) {
- if (cb) cb(resp.error, null);
- else if (resp.error) throw resp.error;
- return null;
- }
- var params = AWS.util.copy(req.rawParams);
- if (!resp.nextPageTokens) {
- return cb ? cb(null, null) : null;
- } else {
- var inputTokens = config.inputToken;
- if (typeof inputTokens === 'string') inputTokens = [inputTokens];
- for (var i = 0; i < inputTokens.length; i++) {
- params[inputTokens[i]] = resp.nextPageTokens[i];
- }
- return self[operation](params, cb);
- }
- };
- }
- });
- /**
- * @api private
- */
- module.exports = AWS.DynamoDB.DocumentClient;
|