Skip to content

Commit

Permalink
make it possible to retrieve types of the returned items when doing a…
Browse files Browse the repository at this point in the history
… read transaction request
  • Loading branch information
mindler-olli committed May 30, 2024
1 parent ca1dd01 commit fff584a
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`ReadTransactionBuilder > handles transaction with gets 1`] = `
[
[
"myTable",
{
"dataTimestamp": 222,
"someBoolean": true,
"somethingElse": 2,
"userId": "123",
},
],
[
"myOtherTable",
{
"userId": "123",
},
],
[
"myTable",
undefined,
],
]
`;
19 changes: 18 additions & 1 deletion src/queryBuilders/readTransactionBuilder.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,24 @@ describe("ReadTransactionBuilder", () => {
}),
});

trx.addItem({
Get: tsynamoClient
.getItem("myOtherTable")
.keys({
userId: "123",
stringTimestamp: "111",
})
.attributes(["userId"]),
});

trx.addItem({
Get: tsynamoClient.getItem("myTable").keys({
userId: "1111111",
dataTimestamp: 2222,
}),
});

const result = await trx.execute();
console.log("result", result);
expect(result).toMatchSnapshot();
});
});
23 changes: 17 additions & 6 deletions src/queryBuilders/readTransactionBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
import { ReadTransactionNode } from "../nodes/readTransactionNode";
import { QueryCompiler } from "../queryCompiler";
import { AllTuples } from "../typeHelpers";
import { GetQueryBuilder } from "./getItemQueryBuilder";

/**
* @todo What to show as return type?
*/
export interface ReadTransactionBuilderInterface<DDB> {
addItem<Table extends keyof DDB, O extends DDB[Table]>(item: {
Get: GetQueryBuilder<DDB, Table, O>;
}): void;

execute(): Promise<unknown[]>;
/**
* The return value is an array of tuples, where the first item
* tells the name of the table, and the right item is the result
* item itself (or undefined if not found). The table can be used
* for discriminated union to determine the actual type of the result
* item.
*/
execute(): Promise<AllTuples<DDB>[]>;
}

export class ReadTransactionBuilder<DDB>
implements ReadTransactionBuilderInterface<DDB>
{
readonly #props: ReadTransactionBuilderProps;
resultTables: string[] = [];

constructor(props: ReadTransactionBuilderProps) {
this.#props = props;
}

addItem(item: { Get: GetQueryBuilder<DDB, any, any> }) {
this.resultTables.push(item.Get.node.table.table);

this.#props.node.transactGetItems.push({
kind: "TransactGetItemNode",
Get: item.Get.node,
});
}

async execute() {
async execute(): Promise<AllTuples<DDB>[]> {
const transactionCommand = this.#props.queryCompiler.compile(
this.#props.node
);

return (
await this.#props.ddbClient.send(transactionCommand)
).Responses?.map((o) => o.Item) as unknown[];
).Responses?.map((o, i) => [
this.resultTables[i],
o.Item,
]) as AllTuples<DDB>[];
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/typeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,20 @@ export type ObjectFullPaths<T> =
never
: // Leaf value reached, don't return anything
never;

/**
* Creates a tuple where the first item is the name of the table
* and the second item is the schema of the table.
*/
type DependentTuple<DDB, Table extends keyof DDB> = [
Table,
ExecuteOutput<DDB[Table]> | undefined
];

/**
* Generates a type that can be used for discriminated union
* when returning data from multiple different tables.
*/
export type AllTuples<DDB> = {
[Table in keyof DDB]: DependentTuple<DDB, Table>;
}[keyof DDB];

0 comments on commit fff584a

Please sign in to comment.