Skip to content

Commit

Permalink
Merge branch 'master' into projectUpdates
Browse files Browse the repository at this point in the history
  • Loading branch information
fishcharlie committed Feb 20, 2020
2 parents b391ac7 + 678959c commit 1aa0c62
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 6 deletions.
4 changes: 4 additions & 0 deletions BREAKING_CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
- `$DELETE` now maps to the correct underlying DynamoDB method instead of the previous behavior of mapping to `$REMOVE`
- `dynamoose.model` has been renamed to `dynamoose.Model`
- `dynamoose.local` has been renamed to `dynamoose.aws.ddb.local`
- `Model.getTableReq` has been renamed to `Model.table.create.request`
- `Model.table.create.request` (formerly `Model.getTableReq`) is now an async function
- `model.originalItem` has been renamed to `model.original` (or `Document.original`)
- `Document.original` formerly (`model.originalItem`) no longer returns the last item saved, but the item first retrieved from DynamoDB
13 changes: 13 additions & 0 deletions docs/api/Document.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,16 @@ myUser.save((error) => {
}
});
```

## document.original()

This function returns the original item that was received from DynamoDB. This function will return a JSON object that represents the original item. In the event no item has been retrieved from DynamoDB `null` will be returned.

```js
const user = await User.get(1);
console.log(user); // {"id": 1, "name": "Bob"}
user.name = "Tim";

console.log(user); // {"id": 1, "name": "Tim"}
console.log(user.original()); // {"id": 1, "name": "Bob"}
```
37 changes: 35 additions & 2 deletions docs/api/Model.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,39 @@ In order to revert to the default and remove custom defaults you can set it to a
dynamoose.Model.defaults = {};
```

## Model.table.create.request()

This function will return the object used to create the table with AWS. You can use this to create the table manually, for things like the Serverless deployment toolkit, or just to peak behind the scenes and see what Dynamoose is doing to create the table.

This function is an async function so you must wait for the promise to resolve before you are able to access the result.

```js
const User = dynamoose.Model("User", {"id": Number, "name": String});

async function printTableRequest() {
console.log(await User.table.create.request());
// {
// "TableName": "User",
// "ProvisionedThroughput": {
// "ReadCapacityUnits": 5,
// "WriteCapacityUnits": 5
// },
// "AttributeDefinitions": [
// {
// "AttributeName": "id",
// "AttributeType": "N"
// }
// ],
// "KeySchema": [
// {
// "AttributeName": "id",
// "KeyType": "HASH"
// }
// ]
// }
}
```

## Model.get(hashKey[, callback])

You can use Model.get to retrieve a document from DynamoDB. This method uses the `getItem` DynamoDB API call to retrieve the object.
Expand Down Expand Up @@ -135,7 +168,7 @@ User.get({"id": 1, "name": "Tim"}, (error, myUser) => {
});
```

### Model.create(document, [settings], [callback])
## Model.create(document, [settings], [callback])

This function lets you create a new document for a given model. This function is almost identical to creating a new document and calling `document.save`, with one key difference, this function will default to setting `overwrite` to false.

Expand All @@ -162,7 +195,7 @@ User.create({"id": 1, "name": "Tim"}, (error, user) => { // If a user with `id=
});
```

### Model.update(keyObj[, updateObj],[ callback])
## Model.update(keyObj[, updateObj],[ callback])

This function lets you update an existing document in the database. You can either pass in one object combining both the hashKey you wish to update along with the update object, or keep them separate by passing in two objects.

Expand Down
6 changes: 6 additions & 0 deletions lib/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ function DocumentCarrier(model) {
const documentObject = Document.isDynamoObject(object) ? aws.converter().unmarshall({...object}) : object;
Object.keys(documentObject).forEach((key) => this[key] = documentObject[key]);
this[internalProperties] = {};
this[internalProperties].originalObject = {...object};
this[internalProperties].originalSettings = {...settings};

if (settings.fromDynamo) {
this[internalProperties].storedInDynamo = true;
Expand Down Expand Up @@ -258,6 +260,10 @@ function DocumentCarrier(model) {
return this;
};

Document.prototype.original = function() {
return this[internalProperties].originalSettings.type === "fromDynamo" ? this[internalProperties].originalObject : null;
};

Document.Model = model;

// TODO: figure out if there is a better way to do this below.
Expand Down
14 changes: 11 additions & 3 deletions lib/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ function Model(name, schema, options = {}) {
setupFlowPromise.then(() => this.ready = true).then(() => {this.pendingTasks.forEach((task) => task()); this.pendingTasks = [];});

this.Document = Document(this);
return this.Document;
const returnObject = this.Document;
returnObject.table = {
"create": {
"request": () => createTableRequest(this)
}
};
return returnObject;
}

// Utility functions
Expand All @@ -58,12 +64,14 @@ async function createTable(model) {
return {"promise": () => Promise.resolve()};
}

const object = {
return aws.ddb().createTable(await createTableRequest(model));
}
async function createTableRequest(model) {
return {
"TableName": model.name,
...getProvisionedThroughput(model),
...await model.schema.getCreateTableAttributeParams()
};
return aws.ddb().createTable(object);
}
function getProvisionedThroughput(model) {
if (model.options.throughput === "ON_DEMAND") {
Expand Down
31 changes: 30 additions & 1 deletion test/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe("Document", () => {
});
});

describe("save", () => {
describe("document.save", () => {
let User, user, putParams = [], putItemFunction;
beforeEach(() => {
Model.defaults = {
Expand Down Expand Up @@ -933,6 +933,35 @@ describe("Document", () => {
});
});

describe("document.original", () => {
let model;
beforeEach(() => {
model = new Model("User", {"id": Number}, {"create": false, "waitForActive": false});
});
afterEach(() => {
model = null;
});

it("Should be a function", () => {
expect(new model({}).original).to.be.a("function");
});

it("Should return null if not retrieving from database", () => {
expect(new model({}).original()).to.eql(null);
});

it("Should return original object if retrieving from database", () => {
expect(new model({"id": 1}, {"type": "fromDynamo"}).original()).to.eql({"id": 1});
});

it("Should return original object if retrieving from database even after modifying document", () => {
const document = new model({"id": 1}, {"type": "fromDynamo"});
document.id = 2;
expect(document.original()).to.eql({"id": 1});
expect({...document}).to.eql({"id": 2});
});
});

describe("conformToSchema", () => {
beforeEach(() => {
Model.defaults = {
Expand Down
28 changes: 28 additions & 0 deletions test/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,34 @@ describe("Model", () => {
});
});
});

describe("Model.table.create.request", () => {
it("Should be a function", () => {
expect(new dynamoose.Model("User", {"id": String}).table.create.request).to.be.a("function");
});

it("Should return correct result", async () => {
expect(await new dynamoose.Model("User", {"id": String}).table.create.request()).to.eql({
"TableName": "User",
"ProvisionedThroughput": {
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
},
"AttributeDefinitions": [
{
"AttributeName": "id",
"AttributeType": "S"
}
],
"KeySchema": [
{
"AttributeName": "id",
"KeyType": "HASH"
}
]
});
});
});
});

describe("model", () => {
Expand Down

0 comments on commit 1aa0c62

Please sign in to comment.