From efe9e989c260a89d397d7c315417b84edafcf03e Mon Sep 17 00:00:00 2001 From: sasumaki Date: Thu, 6 Jun 2024 16:50:04 +0300 Subject: [PATCH 1/3] fix delte and put item typing when no returnValues set --- ...deleteItemQueryBuilder.integration.test.ts | 36 +++++++++++++++++++ src/queryBuilders/deleteItemQueryBuilder.ts | 25 ++++++------- src/queryBuilders/expressionBuilder.ts | 7 ++-- .../putItemQueryBuilder.integration.test.ts | 12 +++++++ src/queryBuilders/putItemQueryBuilder.ts | 27 ++++++-------- src/queryCreator.ts | 12 +++---- 6 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts b/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts index 916cfa1..93b63fb 100644 --- a/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts +++ b/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts @@ -86,4 +86,40 @@ describe("DeleteItemQueryBuilder", () => { expect(res).toBeDefined(); }); + it("doesn't return values if no returnValues is specified", async () => { + await tsynamoClient + .putItem("myTable") + .item({ + userId: "1", + dataTimestamp: 2, + }) + .execute(); + + const res = await tsynamoClient + .deleteItem("myTable") + .keys({ userId: "1", dataTimestamp: 2 }) + .execute(); + + expectTypeOf(res).toBeNever(); + + expect(res).toBeUndefined(); + }); + it("does return values if returnValues is specified", async () => { + await tsynamoClient + .putItem("myTable") + .item({ + userId: "1", + dataTimestamp: 2, + }) + .execute(); + + const res = await tsynamoClient + .deleteItem("myTable") + .keys({ userId: "1", dataTimestamp: 2 }) + .returnValues("ALL_OLD") + .execute(); + + expectTypeOf(res).not.toBeNever(); + expect(res).toBeDefined(); + }); }); diff --git a/src/queryBuilders/deleteItemQueryBuilder.ts b/src/queryBuilders/deleteItemQueryBuilder.ts index e74aa81..44a29aa 100644 --- a/src/queryBuilders/deleteItemQueryBuilder.ts +++ b/src/queryBuilders/deleteItemQueryBuilder.ts @@ -24,7 +24,7 @@ import { export interface DeleteItemQueryBuilderInterface< DDB, Table extends keyof DDB, - O extends DDB[Table] + O > { // conditionExpression conditionExpression>( @@ -86,28 +86,25 @@ export interface DeleteItemQueryBuilderInterface< returnValues( option: Extract - ): DeleteItemQueryBuilder; + ): DeleteItemQueryBuilder>; returnValuesOnConditionCheckFailure( option: Extract - ): DeleteItemQueryBuilder; + ): DeleteItemQueryBuilder>; keys & PickSkRequired>( pk: Keys ): DeleteItemQueryBuilder; compile(): DeleteCommand; - execute(): Promise[] | undefined>; + execute(): Promise; } /** * @todo support ReturnValuesOnConditionCheckFailure */ -export class DeleteItemQueryBuilder< - DDB, - Table extends keyof DDB, - O extends DDB[Table] -> implements DeleteItemQueryBuilderInterface +export class DeleteItemQueryBuilder + implements DeleteItemQueryBuilderInterface { readonly #props: DeleteItemQueryBuilderProps; @@ -153,8 +150,8 @@ export class DeleteItemQueryBuilder< returnValues( option: Extract - ): DeleteItemQueryBuilder { - return new DeleteItemQueryBuilder({ + ): DeleteItemQueryBuilder> { + return new DeleteItemQueryBuilder({ ...this.#props, node: { ...this.#props.node, @@ -168,8 +165,8 @@ export class DeleteItemQueryBuilder< returnValuesOnConditionCheckFailure( option: Extract - ): DeleteItemQueryBuilder { - return new DeleteItemQueryBuilder({ + ): DeleteItemQueryBuilder> { + return new DeleteItemQueryBuilder({ ...this.#props, node: { ...this.#props.node, @@ -200,7 +197,7 @@ export class DeleteItemQueryBuilder< return this.#props.queryCompiler.compile(this.#props.node); }; - execute = async (): Promise[] | undefined> => { + execute = async (): Promise => { const deleteCommand = this.compile(); const data = await this.#props.ddbClient.send(deleteCommand); return data.Attributes as any; diff --git a/src/queryBuilders/expressionBuilder.ts b/src/queryBuilders/expressionBuilder.ts index 2d7d963..2d20d37 100644 --- a/src/queryBuilders/expressionBuilder.ts +++ b/src/queryBuilders/expressionBuilder.ts @@ -210,11 +210,8 @@ export type ExprArgs< | AttributeBetweenExprArg | BuilderExprArg | NotExprArg; -export class ExpressionBuilder< - DDB, - Table extends keyof DDB, - O extends DDB[Table] -> implements ExpressionBuilderInterface +export class ExpressionBuilder + implements ExpressionBuilderInterface { readonly #props: ExpressionBuilderProps; diff --git a/src/queryBuilders/putItemQueryBuilder.integration.test.ts b/src/queryBuilders/putItemQueryBuilder.integration.test.ts index cf06626..4433c04 100644 --- a/src/queryBuilders/putItemQueryBuilder.integration.test.ts +++ b/src/queryBuilders/putItemQueryBuilder.integration.test.ts @@ -44,6 +44,16 @@ describe("PutItemQueryBuilder", () => { expect(result).toEqual(itemToPut); }); + it("doesnt return values without returnValues", async () => { + let result = await tsynamoClient + .putItem("myTable") + .item(itemToPut) + .execute(); + + expectTypeOf(result).toBeNever(); + expect(result).toBeUndefined(); + }); + it("handles ReturnValues option", async () => { let result = await tsynamoClient .putItem("myTable") @@ -51,6 +61,8 @@ describe("PutItemQueryBuilder", () => { .returnValues("ALL_OLD") .execute(); + expectTypeOf(result).not.toBeNever(); + expect(result).toBeUndefined(); result = await tsynamoClient diff --git a/src/queryBuilders/putItemQueryBuilder.ts b/src/queryBuilders/putItemQueryBuilder.ts index 06fa3c4..d634599 100644 --- a/src/queryBuilders/putItemQueryBuilder.ts +++ b/src/queryBuilders/putItemQueryBuilder.ts @@ -16,11 +16,7 @@ import { NotExprArg, } from "./expressionBuilder"; -export interface PutItemQueryBuilderInterface< - DDB, - Table extends keyof DDB, - O extends DDB[Table] -> { +export interface PutItemQueryBuilderInterface { // conditionExpression conditionExpression>( ...args: ComparatorExprArg @@ -81,21 +77,18 @@ export interface PutItemQueryBuilderInterface< returnValues( option: Extract - ): PutItemQueryBuilder; + ): PutItemQueryBuilder>; - item>( + item>( item: Item ): PutItemQueryBuilder; compile(): PutCommand; - execute(): Promise[] | undefined>; + execute(): Promise; } -export class PutItemQueryBuilder< - DDB, - Table extends keyof DDB, - O extends DDB[Table] -> implements PutItemQueryBuilderInterface +export class PutItemQueryBuilder + implements PutItemQueryBuilderInterface { readonly #props: PutItemQueryBuilderProps; @@ -139,7 +132,7 @@ export class PutItemQueryBuilder< }); } - item>( + item>( item: Item ): PutItemQueryBuilder { return new PutItemQueryBuilder({ @@ -156,8 +149,8 @@ export class PutItemQueryBuilder< returnValues( option: Extract - ): PutItemQueryBuilder { - return new PutItemQueryBuilder({ + ): PutItemQueryBuilder> { + return new PutItemQueryBuilder({ ...this.#props, node: { ...this.#props.node, @@ -173,7 +166,7 @@ export class PutItemQueryBuilder< return this.#props.queryCompiler.compile(this.#props.node); }; - execute = async (): Promise[] | undefined> => { + execute = async (): Promise => { const putCommand = this.compile(); const data = await this.#props.ddbClient.send(putCommand); return data.Attributes as any; diff --git a/src/queryCreator.ts b/src/queryCreator.ts index dfc8982..70e6239 100644 --- a/src/queryCreator.ts +++ b/src/queryCreator.ts @@ -71,10 +71,10 @@ export class QueryCreator { * * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/PutItemCommand/ */ - putItem( + putItem
( table: Table - ): PutItemQueryBuilder { - return new PutItemQueryBuilder({ + ): PutItemQueryBuilder { + return new PutItemQueryBuilder({ node: { kind: "PutNode", table: { @@ -97,10 +97,10 @@ export class QueryCreator { * * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/DeleteItemCommand/ */ - deleteItem
( + deleteItem
( table: Table - ): DeleteItemQueryBuilder { - return new DeleteItemQueryBuilder({ + ): DeleteItemQueryBuilder { + return new DeleteItemQueryBuilder({ node: { kind: "DeleteNode", table: { From bd2c65957c54f6f9e71b2c5947e6af7fbb0c96db Mon Sep 17 00:00:00 2001 From: sasumaki Date: Thu, 6 Jun 2024 16:57:08 +0300 Subject: [PATCH 2/3] fix when set to NONE --- ...deleteItemQueryBuilder.integration.test.ts | 12 +++++- src/queryBuilders/deleteItemQueryBuilder.ts | 42 +++++++++++++------ .../putItemQueryBuilder.integration.test.ts | 11 ++++- src/queryBuilders/putItemQueryBuilder.ts | 20 ++++++--- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts b/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts index 93b63fb..daa0ea4 100644 --- a/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts +++ b/src/queryBuilders/deleteItemQueryBuilder.integration.test.ts @@ -86,7 +86,7 @@ describe("DeleteItemQueryBuilder", () => { expect(res).toBeDefined(); }); - it("doesn't return values if no returnValues is specified", async () => { + it("doesn't return values if no returnValues is specified or its set to NONE", async () => { await tsynamoClient .putItem("myTable") .item({ @@ -101,8 +101,16 @@ describe("DeleteItemQueryBuilder", () => { .execute(); expectTypeOf(res).toBeNever(); - expect(res).toBeUndefined(); + + const res2 = await tsynamoClient + .deleteItem("myTable") + .keys({ userId: "1", dataTimestamp: 2 }) + .returnValues("NONE") + .execute(); + + expectTypeOf(res2).toBeNever(); + expect(res2).toBeUndefined(); }); it("does return values if returnValues is specified", async () => { await tsynamoClient diff --git a/src/queryBuilders/deleteItemQueryBuilder.ts b/src/queryBuilders/deleteItemQueryBuilder.ts index 44a29aa..793721a 100644 --- a/src/queryBuilders/deleteItemQueryBuilder.ts +++ b/src/queryBuilders/deleteItemQueryBuilder.ts @@ -84,13 +84,21 @@ export interface DeleteItemQueryBuilderInterface< ...args: BuilderExprArg ): DeleteItemQueryBuilder; - returnValues( - option: Extract - ): DeleteItemQueryBuilder>; - - returnValuesOnConditionCheckFailure( - option: Extract - ): DeleteItemQueryBuilder>; + returnValues( + option: Extract + ): DeleteItemQueryBuilder< + DDB, + Table, + "NONE" extends Choice ? O : ExecuteOutput + >; + + returnValuesOnConditionCheckFailure( + option: Extract + ): DeleteItemQueryBuilder< + DDB, + Table, + "NONE" extends Choice ? O : ExecuteOutput + >; keys & PickSkRequired>( pk: Keys @@ -148,9 +156,13 @@ export class DeleteItemQueryBuilder }); } - returnValues( - option: Extract - ): DeleteItemQueryBuilder> { + returnValues( + option: Extract + ): DeleteItemQueryBuilder< + DDB, + Table, + "NONE" extends Choice ? O : ExecuteOutput + > { return new DeleteItemQueryBuilder({ ...this.#props, node: { @@ -163,9 +175,13 @@ export class DeleteItemQueryBuilder }); } - returnValuesOnConditionCheckFailure( - option: Extract - ): DeleteItemQueryBuilder> { + returnValuesOnConditionCheckFailure( + option: Extract + ): DeleteItemQueryBuilder< + DDB, + Table, + "NONE" extends Choice ? O : ExecuteOutput + > { return new DeleteItemQueryBuilder({ ...this.#props, node: { diff --git a/src/queryBuilders/putItemQueryBuilder.integration.test.ts b/src/queryBuilders/putItemQueryBuilder.integration.test.ts index 4433c04..b1af9eb 100644 --- a/src/queryBuilders/putItemQueryBuilder.integration.test.ts +++ b/src/queryBuilders/putItemQueryBuilder.integration.test.ts @@ -44,7 +44,7 @@ describe("PutItemQueryBuilder", () => { expect(result).toEqual(itemToPut); }); - it("doesnt return values without returnValues", async () => { + it("doesnt return values without returnValues or when its set to NONE", async () => { let result = await tsynamoClient .putItem("myTable") .item(itemToPut) @@ -52,6 +52,15 @@ describe("PutItemQueryBuilder", () => { expectTypeOf(result).toBeNever(); expect(result).toBeUndefined(); + + let result2 = await tsynamoClient + .putItem("myTable") + .item(itemToPut) + .returnValues("NONE") + .execute(); + + expectTypeOf(result2).toBeNever(); + expect(result2).toBeUndefined(); }); it("handles ReturnValues option", async () => { diff --git a/src/queryBuilders/putItemQueryBuilder.ts b/src/queryBuilders/putItemQueryBuilder.ts index d634599..445819d 100644 --- a/src/queryBuilders/putItemQueryBuilder.ts +++ b/src/queryBuilders/putItemQueryBuilder.ts @@ -75,9 +75,13 @@ export interface PutItemQueryBuilderInterface { ...args: BuilderExprArg ): PutItemQueryBuilder; - returnValues( - option: Extract - ): PutItemQueryBuilder>; + returnValues( + option: Extract + ): PutItemQueryBuilder< + DDB, + Table, + "NONE" extends Choice ? O : ExecuteOutput + >; item>( item: Item @@ -147,9 +151,13 @@ export class PutItemQueryBuilder }); } - returnValues( - option: Extract - ): PutItemQueryBuilder> { + returnValues( + option: Extract + ): PutItemQueryBuilder< + DDB, + Table, + "NONE" extends Choice ? O : ExecuteOutput + > { return new PutItemQueryBuilder({ ...this.#props, node: { From fb72f4f8c5ff03f956fb724c6139e27fcb76bf84 Mon Sep 17 00:00:00 2001 From: sasumaki Date: Wed, 12 Jun 2024 14:33:16 +0300 Subject: [PATCH 3/3] :fish: --- src/queryBuilders/putItemQueryBuilder.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/queryBuilders/putItemQueryBuilder.ts b/src/queryBuilders/putItemQueryBuilder.ts index 587c1c5..c08d89b 100644 --- a/src/queryBuilders/putItemQueryBuilder.ts +++ b/src/queryBuilders/putItemQueryBuilder.ts @@ -16,11 +16,7 @@ import { NotExprArg, } from "./expressionBuilder"; -export interface PutItemQueryBuilderInterface< - DDB, - Table extends keyof DDB, - O extends DDB[Table] -> { +export interface PutItemQueryBuilderInterface { /** * A condition that must be satisfied in order for a PutItem operation to be executed. *