Skip to content

Commit

Permalink
add support for delete operation in transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
mindler-olli committed Apr 18, 2024
1 parent 47c9ce2 commit ba663e1
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/nodes/TransactItemNode.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { DeleteNode } from "./deleteNode";
import { PutNode } from "./putNode";

export type TransactItemNode = {
readonly kind: "TransactItemNode";
readonly Put?: PutNode;
readonly Delete?: DeleteNode;
};
49 changes: 27 additions & 22 deletions src/queryBuilders/deleteItemQueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,77 +24,77 @@ import {
export interface DeleteItemQueryBuilderInterface<
DDB,
Table extends keyof DDB,
O
O extends DDB[Table]
> {
// conditionExpression
conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: ComparatorExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeFuncExprArg<Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeBeginsWithExprArg<Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeContainsExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeBetweenExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: NotExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: BuilderExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

// orConditionExpression
orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: ComparatorExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeFuncExprArg<Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeBeginsWithExprArg<Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeContainsExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: AttributeBetweenExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: NotExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: BuilderExprArg<DDB, Table, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

returnValues(
option: Extract<ReturnValuesOptions, "NONE" | "ALL_OLD">
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

returnValuesOnConditionCheckFailure(
option: Extract<ReturnValuesOptions, "NONE" | "ALL_OLD">
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

keys<Keys extends PickPk<DDB[Table]> & PickSkRequired<DDB[Table]>>(
pk: Keys
): DeleteItemQueryBuilderInterface<DDB, Table, O>;
): DeleteItemQueryBuilder<DDB, Table, O>;

compile(): DeleteCommand;
execute(): Promise<ExecuteOutput<O>[] | undefined>;
Expand All @@ -117,7 +117,7 @@ export class DeleteItemQueryBuilder<

conditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: ExprArgs<DDB, Table, O, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O> {
): DeleteItemQueryBuilder<DDB, Table, O> {
const eB = new ExpressionBuilder<DDB, Table, O>({
node: { ...this.#props.node.conditionExpression },
});
Expand All @@ -135,7 +135,7 @@ export class DeleteItemQueryBuilder<

orConditionExpression<Key extends ObjectKeyPaths<DDB[Table]>>(
...args: ExprArgs<DDB, Table, O, Key>
): DeleteItemQueryBuilderInterface<DDB, Table, O> {
): DeleteItemQueryBuilder<DDB, Table, O> {
const eB = new ExpressionBuilder<DDB, Table, O>({
node: { ...this.#props.node.conditionExpression },
});
Expand All @@ -153,7 +153,7 @@ export class DeleteItemQueryBuilder<

returnValues(
option: Extract<ReturnValuesOptions, "NONE" | "ALL_OLD">
): DeleteItemQueryBuilderInterface<DDB, Table, O> {
): DeleteItemQueryBuilder<DDB, Table, O> {
return new DeleteItemQueryBuilder<DDB, Table, O>({
...this.#props,
node: {
Expand All @@ -168,7 +168,7 @@ export class DeleteItemQueryBuilder<

returnValuesOnConditionCheckFailure(
option: Extract<ReturnValuesOptions, "NONE" | "ALL_OLD">
): DeleteItemQueryBuilderInterface<DDB, Table, O> {
): DeleteItemQueryBuilder<DDB, Table, O> {
return new DeleteItemQueryBuilder<DDB, Table, O>({
...this.#props,
node: {
Expand Down Expand Up @@ -199,11 +199,16 @@ export class DeleteItemQueryBuilder<
compile = (): DeleteCommand => {
return this.#props.queryCompiler.compile(this.#props.node);
};

execute = async (): Promise<ExecuteOutput<O>[] | undefined> => {
const deleteCommand = this.compile();
const data = await this.#props.ddbClient.send(deleteCommand);
return data.Attributes as any;
};

public get node() {
return this.#props.node;
}
}

preventAwait(
Expand Down
70 changes: 70 additions & 0 deletions src/queryBuilders/transactionBuilder.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,74 @@ describe("TransactionBuilder", () => {

expect(result).toMatchSnapshot();
});

it("handles deletes", async () => {
await tsynamoClient
.putItem("myTable")
.item({ userId: "9999", dataTimestamp: 1 })
.execute();

await tsynamoClient
.putItem("myOtherTable")
.item({ userId: "9999", stringTimestamp: "123" })
.execute();

let foundItem: unknown = await tsynamoClient
.getItem("myTable")
.keys({
userId: "9999",
dataTimestamp: 1,
})
.execute();

expect(foundItem).toBeDefined();

foundItem = await tsynamoClient
.getItem("myOtherTable")
.keys({
userId: "9999",
stringTimestamp: "123",
})
.execute();

expect(foundItem).toBeDefined();

const trx = tsynamoClient.createTransaction();

trx.addItem({
Delete: tsynamoClient.deleteItem("myTable").keys({
userId: "9999",
dataTimestamp: 1,
}),
});

trx.addItem({
Delete: tsynamoClient.deleteItem("myOtherTable").keys({
userId: "9999",
stringTimestamp: "123",
}),
});

await trx.execute();

foundItem = await tsynamoClient
.getItem("myTable")
.keys({
userId: "9999",
dataTimestamp: 1,
})
.execute();

expect(foundItem).toBeUndefined();

foundItem = await tsynamoClient
.getItem("myOtherTable")
.keys({
userId: "9999",
stringTimestamp: "9999",
})
.execute();

expect(foundItem).toBeUndefined();
});
});
14 changes: 11 additions & 3 deletions src/queryBuilders/transactionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
import { TransactionNode } from "../nodes/transactionNode";
import { QueryCompiler } from "../queryCompiler";
import { PutItemQueryBuilder } from "./putItemQueryBuilder";
import { DeleteItemQueryBuilder } from "./deleteItemQueryBuilder";

export interface TransactionBuilderInterface<DDB> {
/**
* TODO: Update, Put, Delete, ConditionCheck
* TODO: Update, ConditionCheck
*/
addItem(item: { Put?: PutItemQueryBuilder<DDB, any, any> }): void;
addItem(item: {
Put?: PutItemQueryBuilder<DDB, any, any>;
Delete?: DeleteItemQueryBuilder<DDB, any, any>;
}): void;

execute(): Promise<void>;
}
Expand All @@ -21,10 +25,14 @@ export class TransactionBuilder<DDB>
this.#props = props;
}

addItem(item: { Put?: PutItemQueryBuilder<DDB, any, any> }) {
addItem(item: {
Put?: PutItemQueryBuilder<DDB, any, any>;
Delete?: DeleteItemQueryBuilder<DDB, any, any>;
}) {
this.#props.node.transactItems.push({
kind: "TransactItemNode",
Put: item.Put?.node,
Delete: item.Delete?.node,
});
}

Expand Down
17 changes: 11 additions & 6 deletions src/queryCompiler/queryCompiler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TransactWriteItem } from "@aws-sdk/client-dynamodb";
import {
DeleteCommand,
DeleteCommandInput,
GetCommand,
PutCommand,
PutCommandInput,
Expand Down Expand Up @@ -180,6 +181,10 @@ export class QueryCompiler {
}

compileDeleteNode(deleteNode: DeleteNode) {
return new DeleteCommand(this.compileDeleteCmdInput(deleteNode));
}

compileDeleteCmdInput(deleteNode: DeleteNode): DeleteCommandInput {
const {
table: tableNode,
returnValues: returnValuesNode,
Expand All @@ -198,7 +203,7 @@ export class QueryCompiler {
attributeNames
);

return new DeleteCommand({
return {
TableName: tableNode.table,
Key: keysNode?.keys,
ReturnValues: returnValuesNode?.option,
Expand All @@ -219,7 +224,7 @@ export class QueryCompiler {
...Object.fromEntries(attributeNames),
}
: undefined,
});
};
}

compileUpdateNode(updateNode: UpdateNode) {
Expand Down Expand Up @@ -279,11 +284,11 @@ export class QueryCompiler {
compiledTransactItem.Put = this.compilePutCmdInput(item.Put);
}

return compiledTransactItem;
});
if (item.Delete) {
compiledTransactItem.Delete = this.compileDeleteCmdInput(item.Delete);
}

console.log("WUT", {
TransactItems: TransactItems.map((x) => x.Put),
return compiledTransactItem;
});

return new TransactWriteCommand({
Expand Down

0 comments on commit ba663e1

Please sign in to comment.