betterddb 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/src/betterddb.d.ts +137 -0
  2. package/dist/src/betterddb.d.ts.map +1 -0
  3. package/dist/src/betterddb.js +165 -0
  4. package/dist/src/betterddb.js.map +1 -0
  5. package/dist/src/builders/batch-get-builder.d.ts +16 -0
  6. package/dist/src/builders/batch-get-builder.d.ts.map +1 -0
  7. package/dist/src/builders/batch-get-builder.js +54 -0
  8. package/dist/src/builders/batch-get-builder.js.map +1 -0
  9. package/dist/src/builders/create-builder.d.ts +12 -0
  10. package/dist/src/builders/create-builder.d.ts.map +1 -0
  11. package/dist/src/builders/create-builder.js +84 -0
  12. package/dist/src/builders/create-builder.js.map +1 -0
  13. package/dist/src/builders/delete-builder.d.ts +18 -0
  14. package/dist/src/builders/delete-builder.d.ts.map +1 -0
  15. package/dist/src/builders/delete-builder.js +75 -0
  16. package/dist/src/builders/delete-builder.js.map +1 -0
  17. package/dist/src/builders/get-builder.d.ts +18 -0
  18. package/dist/src/builders/get-builder.d.ts.map +1 -0
  19. package/dist/src/builders/get-builder.js +76 -0
  20. package/dist/src/builders/get-builder.js.map +1 -0
  21. package/dist/src/builders/index.d.ts +8 -0
  22. package/dist/src/builders/index.d.ts.map +1 -0
  23. package/{src/builders/index.ts → dist/src/builders/index.js} +1 -0
  24. package/dist/src/builders/index.js.map +1 -0
  25. package/dist/src/builders/query-builder.d.ts +29 -0
  26. package/dist/src/builders/query-builder.d.ts.map +1 -0
  27. package/dist/src/builders/query-builder.js +171 -0
  28. package/dist/src/builders/query-builder.js.map +1 -0
  29. package/dist/src/builders/scan-builder.d.ts +21 -0
  30. package/dist/src/builders/scan-builder.d.ts.map +1 -0
  31. package/dist/src/builders/scan-builder.js +76 -0
  32. package/dist/src/builders/scan-builder.js.map +1 -0
  33. package/dist/src/builders/update-builder.d.ts +37 -0
  34. package/dist/src/builders/update-builder.d.ts.map +1 -0
  35. package/dist/src/builders/update-builder.js +301 -0
  36. package/dist/src/builders/update-builder.js.map +1 -0
  37. package/dist/src/index.d.ts +5 -0
  38. package/dist/src/index.d.ts.map +1 -0
  39. package/{src/index.ts → dist/src/index.js} +1 -0
  40. package/dist/src/index.js.map +1 -0
  41. package/dist/src/operator.d.ts +3 -0
  42. package/dist/src/operator.d.ts.map +1 -0
  43. package/dist/src/operator.js +28 -0
  44. package/dist/src/operator.js.map +1 -0
  45. package/dist/src/types/index.d.ts +2 -0
  46. package/dist/src/types/index.d.ts.map +1 -0
  47. package/{src/types/index.ts → dist/src/types/index.js} +1 -0
  48. package/dist/src/types/index.js.map +1 -0
  49. package/dist/src/types/paginated-result.d.ts +6 -0
  50. package/dist/src/types/paginated-result.d.ts.map +1 -0
  51. package/dist/src/types/paginated-result.js +2 -0
  52. package/dist/src/types/paginated-result.js.map +1 -0
  53. package/dist/tsconfig.tsbuildinfo +1 -0
  54. package/package.json +9 -8
  55. package/.github/workflows/npm-publish.yml +0 -33
  56. package/.github/workflows/test.yml +0 -42
  57. package/CONTRIBUTING.md +0 -225
  58. package/LICENCSE +0 -21
  59. package/babel.config.cjs +0 -6
  60. package/docker-compose.yml +0 -16
  61. package/eslint.config.mjs +0 -29
  62. package/jest.config.cjs +0 -17
  63. package/prettier.config.js +0 -6
  64. package/src/betterddb.ts +0 -267
  65. package/src/builders/batch-get-builder.ts +0 -56
  66. package/src/builders/create-builder.ts +0 -97
  67. package/src/builders/delete-builder.ts +0 -87
  68. package/src/builders/get-builder.ts +0 -78
  69. package/src/builders/query-builder.ts +0 -242
  70. package/src/builders/scan-builder.ts +0 -98
  71. package/src/builders/update-builder.ts +0 -363
  72. package/src/operator.ts +0 -43
  73. package/src/types/paginated-result.ts +0 -6
  74. package/test/batch-get.test.ts +0 -122
  75. package/test/create.test.ts +0 -121
  76. package/test/delete.test.ts +0 -93
  77. package/test/get.test.ts +0 -98
  78. package/test/query.test.ts +0 -206
  79. package/test/scan.test.ts +0 -130
  80. package/test/update.test.ts +0 -355
  81. package/test/utils/table-setup.ts +0 -62
  82. package/tsconfig.json +0 -23
@@ -1,93 +0,0 @@
1
- // __tests__/delete.test.ts
2
- import { z } from "zod";
3
- import { BetterDDB } from "../src/betterddb";
4
- import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
5
- import { DynamoDB } from "@aws-sdk/client-dynamodb";
6
- import { createTestTable, deleteTestTable } from "./utils/table-setup";
7
- import {
8
- KeySchemaElement,
9
- AttributeDefinition,
10
- GlobalSecondaryIndex,
11
- } from "@aws-sdk/client-dynamodb";
12
- const TEST_TABLE = "delete-test-table";
13
- const ENDPOINT = "http://localhost:4566";
14
- const REGION = "us-east-1";
15
- const ENTITY_TYPE = "USER";
16
- const PRIMARY_KEY = "pk";
17
- const PRIMARY_KEY_TYPE = "S";
18
- const SORT_KEY = "sk";
19
- const SORT_KEY_TYPE = "S";
20
- const GSI_NAME = "EmailIndex";
21
- const GSI_PRIMARY_KEY = "gsi1pk";
22
- const GSI_SORT_KEY = "gsi1sk";
23
- const KEY_SCHEMA = [
24
- { AttributeName: PRIMARY_KEY, KeyType: "HASH" },
25
- { AttributeName: SORT_KEY, KeyType: "RANGE" },
26
- ] as KeySchemaElement[];
27
- const ATTRIBUTE_DEFINITIONS = [
28
- { AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
29
- { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE },
30
- { AttributeName: GSI_PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
31
- { AttributeName: GSI_SORT_KEY, AttributeType: SORT_KEY_TYPE },
32
- ] as AttributeDefinition[];
33
- const GSIS = [
34
- {
35
- IndexName: GSI_NAME,
36
- KeySchema: [
37
- { AttributeName: GSI_PRIMARY_KEY, KeyType: "HASH" },
38
- { AttributeName: GSI_SORT_KEY, KeyType: "RANGE" },
39
- ],
40
- Projection: {
41
- ProjectionType: "ALL",
42
- },
43
- },
44
- ] as GlobalSecondaryIndex[];
45
- const client = DynamoDBDocumentClient.from(
46
- new DynamoDB({
47
- region: REGION,
48
- endpoint: ENDPOINT,
49
- }),
50
- );
51
-
52
- const UserSchema = z.object({
53
- id: z.string(),
54
- name: z.string(),
55
- email: z.string().email(),
56
- });
57
-
58
- type User = z.infer<typeof UserSchema>;
59
-
60
- const userDdb = new BetterDDB<User>({
61
- schema: UserSchema,
62
- tableName: TEST_TABLE,
63
- entityType: ENTITY_TYPE,
64
- keys: {
65
- primary: { name: PRIMARY_KEY, definition: { build: (raw) => raw.id! } },
66
- sort: { name: SORT_KEY, definition: { build: (raw) => raw.email! } },
67
- },
68
- client,
69
- timestamps: true,
70
- });
71
-
72
- beforeAll(async () => {
73
- await createTestTable(TEST_TABLE, KEY_SCHEMA, ATTRIBUTE_DEFINITIONS, GSIS);
74
- await userDdb
75
- .create({ id: "user-123", name: "John Doe", email: "john@example.com" })
76
- .execute();
77
- });
78
-
79
- afterAll(async () => {
80
- await deleteTestTable(TEST_TABLE);
81
- });
82
-
83
- describe("BetterDDB - Delete Operation", () => {
84
- it("should delete an item using DeleteBuilder", async () => {
85
- await userDdb
86
- .delete({ id: "user-123", email: "john@example.com" })
87
- .execute();
88
- const deletedUser = await userDdb
89
- .get({ id: "user-123", email: "john@example.com" })
90
- .execute();
91
- expect(deletedUser).toBeNull();
92
- });
93
- });
package/test/get.test.ts DELETED
@@ -1,98 +0,0 @@
1
- // __tests__/get.test.ts
2
- import { z } from "zod";
3
- import { BetterDDB } from "../src/betterddb";
4
- import { createTestTable, deleteTestTable } from "./utils/table-setup";
5
- import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
6
- import { DynamoDB, GlobalSecondaryIndex } from "@aws-sdk/client-dynamodb";
7
- import {
8
- KeySchemaElement,
9
- AttributeDefinition,
10
- } from "@aws-sdk/client-dynamodb";
11
- const TEST_TABLE = "get-test-table";
12
- const ENDPOINT = "http://localhost:4566";
13
- const REGION = "us-east-1";
14
- const ENTITY_TYPE = "USER";
15
- const PRIMARY_KEY = "pk";
16
- const PRIMARY_KEY_TYPE = "S";
17
- const SORT_KEY = "sk";
18
- const SORT_KEY_TYPE = "S";
19
- const GSI_NAME = "EmailIndex";
20
- const GSI_PRIMARY_KEY = "gsi1pk";
21
- const GSI_SORT_KEY = "gsi1sk";
22
- const KEY_SCHEMA = [
23
- { AttributeName: PRIMARY_KEY, KeyType: "HASH" },
24
- { AttributeName: SORT_KEY, KeyType: "RANGE" },
25
- ] as KeySchemaElement[];
26
- const ATTRIBUTE_DEFINITIONS = [
27
- { AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
28
- { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE },
29
- { AttributeName: GSI_PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
30
- { AttributeName: GSI_SORT_KEY, AttributeType: SORT_KEY_TYPE },
31
- ] as AttributeDefinition[];
32
- const GSIS = [
33
- {
34
- IndexName: GSI_NAME,
35
- KeySchema: [
36
- { AttributeName: GSI_PRIMARY_KEY, KeyType: "HASH" },
37
- { AttributeName: GSI_SORT_KEY, KeyType: "RANGE" },
38
- ],
39
- Projection: {
40
- ProjectionType: "ALL",
41
- },
42
- },
43
- ] as GlobalSecondaryIndex[];
44
-
45
- const client = DynamoDBDocumentClient.from(
46
- new DynamoDB({
47
- region: REGION,
48
- endpoint: ENDPOINT,
49
- }),
50
- );
51
-
52
- const UserSchema = z.object({
53
- id: z.string(),
54
- name: z.string(),
55
- email: z.string().email(),
56
- });
57
-
58
- type User = z.infer<typeof UserSchema>;
59
-
60
- const userDdb = new BetterDDB<User>({
61
- schema: UserSchema,
62
- tableName: TEST_TABLE,
63
- entityType: ENTITY_TYPE,
64
- keys: {
65
- primary: { name: PRIMARY_KEY, definition: { build: (raw) => raw.id! } },
66
- sort: { name: SORT_KEY, definition: { build: (raw) => raw.email! } },
67
- },
68
- client,
69
- timestamps: true,
70
- });
71
-
72
- beforeAll(async () => {
73
- await createTestTable(TEST_TABLE, KEY_SCHEMA, ATTRIBUTE_DEFINITIONS, GSIS);
74
- await userDdb
75
- .create({ id: "user-123", name: "John Doe", email: "john@example.com" })
76
- .execute();
77
- });
78
-
79
- afterAll(async () => {
80
- await deleteTestTable(TEST_TABLE);
81
- });
82
-
83
- describe("BetterDDB - Get Operation", () => {
84
- it("should retrieve an item using GetBuilder", async () => {
85
- const user = await userDdb
86
- .get({ id: "user-123", email: "john@example.com" })
87
- .execute();
88
- expect(user).not.toBeNull();
89
- expect(user?.id).toBe("user-123");
90
- });
91
-
92
- it("should retrieve an item using GetBuilder that does not exist", async () => {
93
- const user = await userDdb
94
- .get({ id: "user-123", email: "jane@example.com" })
95
- .execute();
96
- expect(user).toBeNull();
97
- });
98
- });
@@ -1,206 +0,0 @@
1
- import { z } from "zod";
2
- import { BetterDDB } from "../src/betterddb";
3
- import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
4
- import {
5
- AttributeDefinition,
6
- DynamoDB,
7
- GlobalSecondaryIndex,
8
- KeySchemaElement,
9
- } from "@aws-sdk/client-dynamodb";
10
- import { createTestTable, deleteTestTable } from "./utils/table-setup";
11
-
12
- const TEST_TABLE = "query-test-table";
13
- const ENDPOINT = "http://localhost:4566";
14
- const REGION = "us-east-1";
15
- const ENTITY_TYPE = "USER";
16
- const PRIMARY_KEY = "pk";
17
- const PRIMARY_KEY_TYPE = "S";
18
- const SORT_KEY = "sk";
19
- const SORT_KEY_TYPE = "S";
20
- const GSI_NAME = "EmailIndex";
21
- const GSI_PRIMARY_KEY = "gsi1pk";
22
- const GSI_SORT_KEY = "gsi1sk";
23
- const KEY_SCHEMA = [
24
- { AttributeName: PRIMARY_KEY, KeyType: "HASH" },
25
- { AttributeName: SORT_KEY, KeyType: "RANGE" },
26
- ] as KeySchemaElement[];
27
- const ATTRIBUTE_DEFINITIONS = [
28
- { AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
29
- { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE },
30
- { AttributeName: GSI_PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
31
- { AttributeName: GSI_SORT_KEY, AttributeType: SORT_KEY_TYPE },
32
- ] as AttributeDefinition[];
33
- const GSIS = [
34
- {
35
- IndexName: GSI_NAME,
36
- KeySchema: [
37
- { AttributeName: GSI_PRIMARY_KEY, KeyType: "HASH" },
38
- { AttributeName: GSI_SORT_KEY, KeyType: "RANGE" },
39
- ],
40
- Projection: { ProjectionType: "ALL" },
41
- },
42
- ] as GlobalSecondaryIndex[];
43
-
44
- const client = DynamoDBDocumentClient.from(
45
- new DynamoDB({
46
- region: REGION,
47
- endpoint: ENDPOINT,
48
- }),
49
- );
50
-
51
- const UserSchema = z.object({
52
- id: z.string(),
53
- name: z.string(),
54
- email: z.string().email(),
55
- });
56
-
57
- type User = z.infer<typeof UserSchema>;
58
-
59
- const userDdb = new BetterDDB<User>({
60
- schema: UserSchema,
61
- tableName: TEST_TABLE,
62
- entityType: ENTITY_TYPE,
63
- keys: {
64
- primary: {
65
- name: PRIMARY_KEY,
66
- definition: { build: (raw) => `USER#${raw.id}` },
67
- },
68
- sort: {
69
- name: SORT_KEY,
70
- definition: { build: (raw) => `USER#${raw.email}` },
71
- },
72
- gsis: {
73
- EmailIndex: {
74
- name: "EmailIndex",
75
- primary: {
76
- name: GSI_PRIMARY_KEY,
77
- definition: { build: (raw) => `USER#${raw.email}` },
78
- },
79
- sort: {
80
- name: GSI_SORT_KEY,
81
- definition: { build: (raw) => `USER#${raw.email}` },
82
- },
83
- },
84
- },
85
- },
86
- client,
87
- timestamps: true,
88
- });
89
-
90
- beforeAll(async () => {
91
- await createTestTable(TEST_TABLE, KEY_SCHEMA, ATTRIBUTE_DEFINITIONS, GSIS);
92
-
93
- const items = [
94
- { id: "user-1", name: "Alice", email: "alice@example.com" },
95
- { id: "user-2", name: "Alice B", email: "alice@example.com" },
96
- { id: "user-3", name: "Bob", email: "bob@example.com" },
97
- ];
98
- await Promise.all(items.map((item) => userDdb.create(item).execute()));
99
- });
100
-
101
- afterAll(async () => {
102
- await deleteTestTable(TEST_TABLE);
103
- });
104
-
105
- describe("BetterDDB - Query Operation", () => {
106
- it("should query items using QueryBuilder with filter condition", async () => {
107
- const results = await userDdb
108
- .query({ id: "user-1" })
109
- .filter("name", "begins_with", "Alice")
110
- .limitResults(5)
111
- .execute();
112
- expect(results.items.length).toBeGreaterThanOrEqual(1);
113
- results.items.forEach((result) => {
114
- expect(result.name).toMatch(/^Alice/);
115
- });
116
- });
117
-
118
- it("should query items using QueryBuilder with index", async () => {
119
- const results = await userDdb
120
- .query({ email: "alice@example.com" })
121
- .usingIndex("EmailIndex")
122
- .limitResults(1)
123
- .execute();
124
- expect(results.items.length).toEqual(1);
125
- results.items.forEach((result) => {
126
- expect(result.email).toEqual("alice@example.com");
127
- });
128
- });
129
-
130
- it("should query items using QueryBuilder with a sort key condition", async () => {
131
- // For a complex sort key, users must supply an object.
132
- const results = await userDdb
133
- .query({ id: "user-1" })
134
- .where("begins_with", { email: "alice" })
135
- .execute();
136
- expect(results.items.length).toBeGreaterThanOrEqual(1);
137
- results.items.forEach((result) => {
138
- expect(result.email).toMatch(/^alice/i);
139
- });
140
- });
141
-
142
- it("should return no results if the sort key condition does not match", async () => {
143
- const results = await userDdb
144
- .query({ id: "user-1" })
145
- .where("begins_with", { email: "bob" })
146
- .execute();
147
- expect(results.items.length).toEqual(0);
148
- });
149
-
150
- it("should query items using QueryBuilder with index and additional filter", async () => {
151
- const results = await userDdb
152
- .query({ email: "alice@example.com" })
153
- .usingIndex("EmailIndex")
154
- .filter("name", "begins_with", "Alice")
155
- .execute();
156
- expect(results.items.length).toBeGreaterThanOrEqual(1);
157
- results.items.forEach((result) => {
158
- expect(result.email).toEqual("alice@example.com");
159
- expect(result.name).toMatch(/^Alice/);
160
- });
161
- });
162
-
163
- it('should query items using QueryBuilder with a sort key condition using "between"', async () => {
164
- // Here we use the "between" operator. The sort key build function produces a value like "USER#alice@example.com"
165
- // We provide lower and upper bounds as objects.
166
- const results = await userDdb
167
- .query({ id: "user-1" })
168
- .where("between", [
169
- { email: "alice" }, // Lower bound -> built to "USER#alice"
170
- { email: "alice@example.com" }, // Upper bound -> built to "USER#alice@example.com"
171
- ])
172
- .execute();
173
- expect(results.items.length).toBeGreaterThanOrEqual(1);
174
- results.items.forEach((result) => {
175
- // The built sort key for user-1 is "USER#alice@example.com"
176
- expect(result.email).toMatch(/alice@example\.com/i);
177
- });
178
- });
179
-
180
- it("should query items using QueryBuilder with multiple filter conditions on an index", async () => {
181
- // Query the GSI for email "alice@example.com". Two items match.
182
- // Then apply two filter conditions: name begins_with "Alice" and name contains "B" should only match one.
183
- const results = await userDdb
184
- .query({ email: "alice@example.com" })
185
- .usingIndex("EmailIndex")
186
- .filter("name", "begins_with", "Alice")
187
- .filter("name", "contains", "B")
188
- .execute();
189
- expect(results.items.length).toEqual(1);
190
- results.items.forEach((result) => {
191
- expect(result.name).toMatch(/^Alice/);
192
- expect(result.name).toContain("B");
193
- });
194
- });
195
-
196
- it("should query items using QueryBuilder with where clause on an index", async () => {
197
- // Query the GSI for email "alice@example.com". Two items match.
198
- // Then apply two filter conditions: name begins_with "Alice" and name contains "B" should only match one.
199
- const results = await userDdb
200
- .query({ email: "alice@example.com" })
201
- .usingIndex("EmailIndex")
202
- .where("begins_with", { email: "alice" })
203
- .execute();
204
- expect(results.items.length).toEqual(2);
205
- });
206
- });
package/test/scan.test.ts DELETED
@@ -1,130 +0,0 @@
1
- import { z } from "zod";
2
- import { BetterDDB } from "../src/betterddb";
3
- import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
4
- import { DynamoDB, GlobalSecondaryIndex } from "@aws-sdk/client-dynamodb";
5
- import { createTestTable, deleteTestTable } from "./utils/table-setup";
6
- import {
7
- KeySchemaElement,
8
- AttributeDefinition,
9
- } from "@aws-sdk/client-dynamodb";
10
- const TEST_TABLE = "scan-test-table";
11
- const ENDPOINT = "http://localhost:4566";
12
- const REGION = "us-east-1";
13
- const ENTITY_TYPE = "USER";
14
- const PRIMARY_KEY = "pk";
15
- const PRIMARY_KEY_TYPE = "S";
16
- const SORT_KEY = "sk";
17
- const SORT_KEY_TYPE = "S";
18
- const GSI_NAME = "EmailIndex";
19
- const GSI_PRIMARY_KEY = "gsi1pk";
20
- const GSI_SORT_KEY = "gsi1sk";
21
- const KEY_SCHEMA = [
22
- { AttributeName: PRIMARY_KEY, KeyType: "HASH" },
23
- { AttributeName: SORT_KEY, KeyType: "RANGE" },
24
- ] as KeySchemaElement[];
25
- const ATTRIBUTE_DEFINITIONS = [
26
- { AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
27
- { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE },
28
- { AttributeName: GSI_PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE },
29
- { AttributeName: GSI_SORT_KEY, AttributeType: SORT_KEY_TYPE },
30
- ] as AttributeDefinition[];
31
- const GSIS = [
32
- {
33
- IndexName: GSI_NAME,
34
- KeySchema: [
35
- { AttributeName: GSI_PRIMARY_KEY, KeyType: "HASH" },
36
- { AttributeName: GSI_SORT_KEY, KeyType: "RANGE" },
37
- ],
38
- Projection: {
39
- ProjectionType: "ALL",
40
- },
41
- },
42
- ] as GlobalSecondaryIndex[];
43
- const client = DynamoDBDocumentClient.from(
44
- new DynamoDB({
45
- region: REGION,
46
- endpoint: ENDPOINT,
47
- }),
48
- );
49
-
50
- const UserSchema = z.object({
51
- id: z.string(),
52
- name: z.string(),
53
- email: z.string().email(),
54
- });
55
-
56
- type User = z.infer<typeof UserSchema>;
57
-
58
- const userDdb = new BetterDDB<User>({
59
- schema: UserSchema,
60
- tableName: TEST_TABLE,
61
- entityType: ENTITY_TYPE,
62
- keys: {
63
- primary: {
64
- name: PRIMARY_KEY,
65
- definition: { build: (raw) => `USER#${raw.id}` },
66
- },
67
- sort: {
68
- name: SORT_KEY,
69
- definition: { build: (raw) => `EMAIL#${raw.email}` },
70
- },
71
- },
72
- client,
73
- timestamps: true,
74
- });
75
-
76
- beforeAll(async () => {
77
- await createTestTable(TEST_TABLE, KEY_SCHEMA, ATTRIBUTE_DEFINITIONS, GSIS);
78
- // Insert multiple items.
79
- const items = [
80
- { id: "user-1", name: "Alice", email: "alice@example.com" },
81
- { id: "user-2", name: "Alice B", email: "alice@example.com" },
82
- { id: "user-3", name: "Bob", email: "bob@example.com" },
83
- ];
84
- await Promise.all(items.map((item) => userDdb.create(item).execute()));
85
- });
86
-
87
- afterAll(async () => {
88
- await deleteTestTable(TEST_TABLE);
89
- });
90
-
91
- describe("BetterDDB - Scan Operation", () => {
92
- it("should scan items using ScanBuilder", async () => {
93
- const results = await userDdb
94
- .scan()
95
- .where("email", "begins_with", "a")
96
- .limitResults(10)
97
- .execute();
98
- expect(results.items.length).toBeGreaterThanOrEqual(1);
99
- results.items.forEach((result) => {
100
- expect(result.email).toMatch(/^alice/i);
101
- });
102
- });
103
-
104
- it("should scan items using ScanBuilder with a contains filter", async () => {
105
- // Scan for users whose name contains "Alice"
106
- const results = await userDdb
107
- .scan()
108
- .where("name", "contains", "Alice")
109
- .limitResults(10)
110
- .execute();
111
- expect(results.items.length).toBeGreaterThan(0);
112
- results.items.forEach((result) => {
113
- expect(result.name).toContain("Alice");
114
- });
115
- });
116
-
117
- it("should scan items using ScanBuilder with a between filter on email", async () => {
118
- // Using lexicographical order on the email address:
119
- // 'alice@example.com' should be between "a" and "c".
120
- const results = await userDdb
121
- .scan()
122
- .where("email", "between", ["a", "c"])
123
- .execute();
124
- expect(results.items.length).toBeGreaterThan(0);
125
- results.items.forEach((result) => {
126
- // A simple lexicographical check
127
- expect(result.email >= "a" && result.email <= "c").toBeTruthy();
128
- });
129
- });
130
- });