Skip to content

Commit

Permalink
select attributes recursively
Browse files Browse the repository at this point in the history
  • Loading branch information
mindler-sasu committed Mar 15, 2024
1 parent 1c8a714 commit 7e4ee38
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 14 deletions.
65 changes: 65 additions & 0 deletions src/__snapshots__/tsynamo.integration.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ exports[`tsynamo > query > handles a FilterExpression that uses attribute_exists
"somethingElse": -5,
"userId": "123",
},
{
"dataTimestamp": 996,
"nested": {
"nestedBoolean": true,
"nestedNested": {
"nestedNestedBoolean": true,
},
"nestedString": "llol",
},
"someBoolean": false,
"somethingElse": -9,
"userId": "123",
},
{
"dataTimestamp": 999,
"nested": {
Expand Down Expand Up @@ -187,6 +200,19 @@ exports[`tsynamo > query > handles a query with a NOT FilterExpression 1`] = `
"somethingElse": 10,
"userId": "123",
},
{
"dataTimestamp": 996,
"nested": {
"nestedBoolean": true,
"nestedNested": {
"nestedNestedBoolean": true,
},
"nestedString": "llol",
},
"someBoolean": false,
"somethingElse": -9,
"userId": "123",
},
{
"dataTimestamp": 999,
"nested": {
Expand Down Expand Up @@ -224,6 +250,19 @@ exports[`tsynamo > query > handles a query with a NOT FilterExpression 2`] = `
"somethingElse": 10,
"userId": "123",
},
{
"dataTimestamp": 996,
"nested": {
"nestedBoolean": true,
"nestedNested": {
"nestedNestedBoolean": true,
},
"nestedString": "llol",
},
"someBoolean": false,
"somethingElse": -9,
"userId": "123",
},
]
`;

Expand Down Expand Up @@ -272,6 +311,19 @@ exports[`tsynamo > query > handles a query with a simple KeyCondition 1`] = `
"somethingElse": 10,
"userId": "123",
},
{
"dataTimestamp": 996,
"nested": {
"nestedBoolean": true,
"nestedNested": {
"nestedNestedBoolean": true,
},
"nestedString": "llol",
},
"someBoolean": false,
"somethingElse": -9,
"userId": "123",
},
{
"dataTimestamp": 999,
"nested": {
Expand Down Expand Up @@ -302,6 +354,19 @@ exports[`tsynamo > query > handles a query with multiple expressions 1`] = `

exports[`tsynamo > query > handles conditions on nested keys 1`] = `
[
{
"dataTimestamp": 996,
"nested": {
"nestedBoolean": true,
"nestedNested": {
"nestedNestedBoolean": true,
},
"nestedString": "llol",
},
"someBoolean": false,
"somethingElse": -9,
"userId": "123",
},
{
"dataTimestamp": 999,
"nested": {
Expand Down
42 changes: 40 additions & 2 deletions src/tsynamo.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ interface DDB {
nested: {
nestedString: number;
nestedBoolean: boolean;
nestedNested: {
nestedNestedBoolean: boolean;
};
};
};
myOtherTable: {
Expand Down Expand Up @@ -112,7 +115,23 @@ describe("tsynamo", () => {
);
expect(Object.keys(data!).length).toBe(2);
});
it.todo("handles selecting nested attributes excessively deep");
it("handles selecting nested attributes excessively deep", async () => {
const data = await tsynamoClient
.getItemFrom("myTable")
.keys({
userId: TEST_ITEM_9.userId,
dataTimestamp: TEST_ITEM_9.dataTimestamp,
})
.consistentRead(true)
.attributes(["someBoolean", "nested.nestedNested.nestedNestedBoolean"])
.execute();

expect(data?.someBoolean).toBe(TEST_ITEM_9.someBoolean);
expect(data?.nested?.nestedNested?.nestedNestedBoolean).toBe(
TEST_ITEM_9.nested.nestedNested.nestedNestedBoolean
);
expect(Object.keys(data!).length).toBe(2);
});
it.todo("handles selecting attributes from arrays");

it("can't await instance directly", async () => {
Expand All @@ -139,7 +158,7 @@ describe("tsynamo", () => {
.keyCondition("userId", "=", TEST_ITEM_1.userId)
.execute();

expect(data?.length).toBe(4);
expect(data?.length).toBe(5);
expect(data).toMatchSnapshot();
});

Expand Down Expand Up @@ -356,6 +375,19 @@ const TEST_ITEM_8 = {
nestedBoolean: true,
},
};
const TEST_ITEM_9 = {
userId: "123",
dataTimestamp: 996,
somethingElse: -9,
someBoolean: false,
nested: {
nestedString: "llol",
nestedBoolean: true,
nestedNested: {
nestedNestedBoolean: true,
},
},
};

/**
* Re-create a DynamoDB table called "myTable" with some test data.
Expand Down Expand Up @@ -482,4 +514,10 @@ const setupTestDatabase = async (client: DynamoDBDocumentClient) => {
Item: TEST_ITEM_8,
})
);
await client.send(
new PutCommand({
TableName: "myTable",
Item: TEST_ITEM_9,
})
);
};
34 changes: 22 additions & 12 deletions src/typeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,31 @@ export type SelectAttributesRaw<
> = {
[A in Attributes[number]]: Table[A];
};
export type UnionToIntersection<U> = (
U extends any ? (k: U) => void : never
) extends (k: infer I) => void
? I
: never;

type NestedValue<T, K extends string> = K extends `${infer First}.${infer Rest}`
? First extends keyof T
? { [k in Rest]: NestedValue<T[First], Rest> }
type RecursiveSelectAttributes<Table, Properties> = Properties extends [
infer First,
...infer Rest
]
? First extends keyof Table
? { [key in First]: RecursiveSelectAttributes<Table[First], Rest> }
: never
: K extends keyof T
? T[K]
: never;
: Table;

// TODO make this Recursive
export type SelectAttributes<
Table,
Attributes extends ReadonlyArray<string>
> = {
[A in Attributes[number] as A extends `${infer First}.${infer _}`
? First
: A]: NestedValue<Table, A>;
};
> = IntersectionToSingleObject<
UnionToIntersection<
RecursiveSelectAttributes<Table, ParsePath<Attributes[number]>>
>
>;

type a = ParsePath<"a.b[1].c" | "a.a.b">;

export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends Array<infer U>
Expand All @@ -91,6 +98,9 @@ export type DeepPartial<T> = {
? DeepPartial<T[P]>
: T[P];
};
type IntersectionToSingleObject<T> = T extends infer U
? { [K in keyof U]: U[K] }
: never;

// We first need to parse the path string into a list of Properties,
// Then, we recursively access Properties on the input object.
Expand Down

0 comments on commit 7e4ee38

Please sign in to comment.