@aurios/mizzle 1.1.2 → 1.1.4
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.
- package/.turbo/turbo-build.log +37 -0
- package/LICENSE +21 -0
- package/README.md +166 -57
- package/dist/chunk-AQVECMXP.js +1 -0
- package/dist/chunk-DU7UPWBW.js +1 -0
- package/dist/chunk-GPYZK4WY.js +1 -0
- package/dist/chunk-NPPZW6VT.js +1 -0
- package/dist/chunk-TOYV2M4M.js +1 -0
- package/dist/chunk-UM3YF5EC.js +1 -0
- package/dist/columns.d.ts +1 -0
- package/dist/columns.js +1 -0
- package/dist/db-zHIHBm1E.d.ts +815 -0
- package/dist/db.d.ts +3 -0
- package/dist/db.js +1 -0
- package/dist/diff.d.ts +18 -0
- package/dist/diff.js +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +1 -0
- package/dist/introspection.d.ts +7 -0
- package/dist/introspection.js +1 -0
- package/dist/operators-BVreW0ky.d.ts +719 -0
- package/dist/snapshot.d.ts +24 -0
- package/dist/snapshot.js +1 -0
- package/dist/table.d.ts +1 -0
- package/dist/table.js +1 -0
- package/dist/transaction-RE7LXTGV.js +1 -0
- package/package.json +82 -66
- package/src/builders/base.ts +53 -56
- package/src/builders/batch-get.ts +63 -58
- package/src/builders/batch-write.ts +81 -78
- package/src/builders/delete.ts +46 -53
- package/src/builders/insert.ts +158 -150
- package/src/builders/query-promise.ts +26 -35
- package/src/builders/relational-builder.ts +214 -191
- package/src/builders/select.ts +250 -237
- package/src/builders/transaction.ts +170 -152
- package/src/builders/update.ts +197 -192
- package/src/columns/binary-set.ts +29 -38
- package/src/columns/binary.ts +25 -35
- package/src/columns/boolean.ts +25 -30
- package/src/columns/date.ts +57 -64
- package/src/columns/index.ts +15 -15
- package/src/columns/json.ts +39 -48
- package/src/columns/list.ts +26 -36
- package/src/columns/map.ts +26 -34
- package/src/columns/number-set.ts +29 -38
- package/src/columns/number.ts +33 -40
- package/src/columns/string-set.ts +38 -47
- package/src/columns/string.ts +37 -49
- package/src/columns/uuid.ts +26 -33
- package/src/core/client.ts +9 -9
- package/src/core/column-builder.ts +194 -220
- package/src/core/column.ts +127 -135
- package/src/core/diff.ts +40 -34
- package/src/core/errors.ts +20 -17
- package/src/core/introspection.ts +62 -58
- package/src/core/operations.ts +17 -23
- package/src/core/parser.ts +82 -89
- package/src/core/relations.ts +164 -154
- package/src/core/retry.ts +52 -52
- package/src/core/snapshot.ts +131 -130
- package/src/core/strategies.ts +222 -218
- package/src/core/table.ts +189 -202
- package/src/core/validation.ts +52 -52
- package/src/db.ts +211 -209
- package/src/expressions/actions.ts +26 -26
- package/src/expressions/builder.ts +62 -54
- package/src/expressions/operators.ts +48 -48
- package/src/expressions/update-builder.ts +78 -76
- package/src/index.ts +1 -1
- package/src/indexes.ts +8 -8
- package/test/batch-resilience.test.ts +138 -0
- package/test/builders/delete.test.ts +100 -0
- package/test/builders/insert.test.ts +216 -0
- package/test/builders/relational-types.test.ts +55 -0
- package/test/builders/relational.integration.test.ts +291 -0
- package/test/builders/relational.test.ts +66 -0
- package/test/builders/select.test.ts +411 -0
- package/test/builders/transaction-errors.test.ts +46 -0
- package/test/builders/transaction-execution.test.ts +99 -0
- package/test/builders/transaction-proxy.test.ts +41 -0
- package/test/builders/update-expression.test.ts +106 -0
- package/test/builders/update.test.ts +179 -0
- package/test/core/diff.test.ts +152 -0
- package/test/core/expressions.test.ts +64 -0
- package/test/core/introspection.test.ts +47 -0
- package/test/core/parser.test.ts +69 -0
- package/test/core/snapshot-gen.test.ts +155 -0
- package/test/core/snapshot.test.ts +52 -0
- package/test/date-column.test.ts +159 -0
- package/test/fluent-writes.integration.test.ts +148 -0
- package/test/integration-retry.test.ts +77 -0
- package/test/integration.test.ts +105 -0
- package/test/item-size-error.test.ts +16 -0
- package/test/item-size-validation.test.ts +82 -0
- package/test/item-size.test.ts +47 -0
- package/test/iterator-pagination.integration.test.ts +132 -0
- package/test/jsdoc-builders.test.ts +55 -0
- package/test/jsdoc-schema.test.ts +107 -0
- package/test/json-column.test.ts +51 -0
- package/test/metadata.test.ts +54 -0
- package/test/mizzle-package.test.ts +20 -0
- package/test/relational-centralized.test.ts +83 -0
- package/test/relational-definition.test.ts +75 -0
- package/test/relational-init.test.ts +30 -0
- package/test/relational-proxy.test.ts +52 -0
- package/test/relations.test.ts +45 -0
- package/test/resilience-config.test.ts +34 -0
- package/test/retry-handler.test.ts +63 -0
- package/test/transaction.integration.test.ts +153 -0
- package/test/unified-select.integration.test.ts +153 -0
- package/test/unified-update.integration.test.ts +139 -0
- package/test/update.integration.test.ts +132 -0
- package/tsconfig.json +12 -8
- package/tsup.config.ts +11 -11
- package/vitest.config.ts +8 -0
package/src/builders/select.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
QueryCommand,
|
|
4
|
-
ScanCommand,
|
|
5
|
-
} from "@aws-sdk/lib-dynamodb";
|
|
6
|
-
import { ENTITY_SYMBOLS } from "@mizzle/shared";
|
|
1
|
+
import { GetCommand, QueryCommand, ScanCommand } from "@aws-sdk/lib-dynamodb";
|
|
2
|
+
import { ENTITY_SYMBOLS } from "@repo/shared";
|
|
7
3
|
import { Column } from "../core/column";
|
|
8
4
|
import type { SelectedFields as SelectedFieldsBase } from "../core/operations";
|
|
9
|
-
import {
|
|
10
|
-
type Expression,
|
|
11
|
-
} from "../expressions/operators";
|
|
5
|
+
import { type Expression } from "../expressions/operators";
|
|
12
6
|
import { Entity, type InferSelectModel, type PhysicalTable } from "../core/table";
|
|
13
7
|
import { BaseBuilder } from "./base";
|
|
14
8
|
import type { StrategyResolution } from "../core/strategies";
|
|
@@ -18,262 +12,281 @@ import { buildExpression } from "../expressions/builder";
|
|
|
18
12
|
export type SelectedFields = SelectedFieldsBase<Column, PhysicalTable>;
|
|
19
13
|
|
|
20
14
|
export class SelectBuilder<TSelection extends SelectedFields | undefined> {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
constructor(
|
|
16
|
+
private client: IMizzleClient,
|
|
17
|
+
private fields?: TSelection,
|
|
18
|
+
) {}
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Specifies the entity to select from.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const results = await db.select().from(users).execute();
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @param entity The Mizzle entity (table) to query.
|
|
29
|
+
* @returns A SelectBase instance to further chain the query.
|
|
30
|
+
*/
|
|
31
|
+
from<TEntity extends Entity>(entity: TEntity) {
|
|
32
|
+
return new SelectBase(entity, this.client, this.fields);
|
|
33
|
+
}
|
|
40
34
|
}
|
|
41
35
|
|
|
42
36
|
export class SelectBase<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
TEntity extends Entity,
|
|
38
|
+
TSelection extends SelectedFields | undefined = undefined,
|
|
39
|
+
TResult = TSelection extends undefined ? InferSelectModel<TEntity> : Record<string, unknown>,
|
|
46
40
|
> extends BaseBuilder<TEntity, TResult[]> {
|
|
47
|
-
|
|
41
|
+
static readonly [ENTITY_SYMBOLS.ENTITY_KIND]: string = "SelectBase";
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
private _whereClause?: Expression;
|
|
44
|
+
private _limitVal?: number;
|
|
45
|
+
private _pageSizeVal?: number;
|
|
46
|
+
private _consistentReadVal?: boolean;
|
|
47
|
+
private _sortForward: boolean = true;
|
|
48
|
+
private _forcedIndexName?: string;
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
constructor(
|
|
51
|
+
entity: TEntity,
|
|
52
|
+
client: IMizzleClient,
|
|
53
|
+
private fields?: TSelection,
|
|
54
|
+
) {
|
|
55
|
+
super(entity, client);
|
|
56
|
+
}
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Adds a filter criteria to the query.
|
|
60
|
+
*
|
|
61
|
+
* For DynamoDB, this will be used as a `KeyConditionExpression` if the
|
|
62
|
+
* primary keys are provided, otherwise it will be used as a `FilterExpression`.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { eq, and, gt } from "@aurios/mizzle";
|
|
67
|
+
*
|
|
68
|
+
* const results = await db.select()
|
|
69
|
+
* .from(users)
|
|
70
|
+
* .where(and(eq(users.id, 1), gt(users.age, 18)))
|
|
71
|
+
* .execute();
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @param expression The expression to filter by.
|
|
75
|
+
* @returns The current builder instance for chaining.
|
|
76
|
+
*/
|
|
77
|
+
where(expression: Expression): this {
|
|
78
|
+
this._whereClause = expression;
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
87
81
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Limits the total number of items returned by the query.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const results = await db.select().from(users).limit(10).execute();
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param val The maximum number of items to return.
|
|
91
|
+
* @returns The current builder instance for chaining.
|
|
92
|
+
*/
|
|
93
|
+
limit(val: number): this {
|
|
94
|
+
this._limitVal = val;
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
103
97
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Sets the page size for the underlying DynamoDB requests.
|
|
100
|
+
* Use this with `.iterator()` to control how many items are fetched in each network request.
|
|
101
|
+
*
|
|
102
|
+
* @param val The number of items per page.
|
|
103
|
+
* @returns The current builder instance for chaining.
|
|
104
|
+
*/
|
|
105
|
+
pageSize(val: number): this {
|
|
106
|
+
this._pageSizeVal = val;
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
115
109
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Enables or disables consistent reads for this query.
|
|
112
|
+
*
|
|
113
|
+
* @param enabled Whether consistent read is enabled. Defaults to true.
|
|
114
|
+
* @returns The current builder instance for chaining.
|
|
115
|
+
*/
|
|
116
|
+
consistentRead(enabled: boolean = true): this {
|
|
117
|
+
this._consistentReadVal = enabled;
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
126
120
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Specifies the sort order for the query (only applicable for `Query` operations).
|
|
123
|
+
*
|
|
124
|
+
* @param forward If true (default), results are sorted in ascending order. If false, descending.
|
|
125
|
+
* @returns The current builder instance for chaining.
|
|
126
|
+
*/
|
|
127
|
+
sort(forward: boolean): this {
|
|
128
|
+
this._sortForward = forward;
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Forces the use of a specific Global Secondary Index (GSI) or Local Secondary Index (LSI).
|
|
134
|
+
*
|
|
135
|
+
* @param name The name of the index to use.
|
|
136
|
+
* @returns The current builder instance for chaining.
|
|
137
|
+
*/
|
|
138
|
+
index(name: string): this {
|
|
139
|
+
this._forcedIndexName = name;
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
148
142
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Returns an async iterator that automatically handles pagination.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* for await (const user of db.select().from(users).iterator()) {
|
|
149
|
+
* console.log(user.name);
|
|
150
|
+
* }
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @returns An AsyncIterableIterator for the query results.
|
|
154
|
+
*/
|
|
155
|
+
iterator(): AsyncIterableIterator<TResult> {
|
|
156
|
+
return async function* (this: SelectBase<TEntity, TSelection, TResult>) {
|
|
157
|
+
let lastEvaluatedKey: Record<string, unknown> | undefined;
|
|
158
|
+
let count = 0;
|
|
165
159
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
for (const item of result.items) {
|
|
170
|
-
yield item;
|
|
171
|
-
count++;
|
|
172
|
-
if (this._limitVal !== undefined && count >= this._limitVal) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
lastEvaluatedKey = result.lastEvaluatedKey;
|
|
178
|
-
} while (lastEvaluatedKey);
|
|
179
|
-
}).bind(this)();
|
|
180
|
-
}
|
|
160
|
+
do {
|
|
161
|
+
const result = await this.fetchPage(lastEvaluatedKey);
|
|
181
162
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
} else if (resolution.hasPartitionKey || resolution.indexName) {
|
|
189
|
-
return await this.executeQuery(resolution, exclusiveStartKey);
|
|
190
|
-
} else {
|
|
191
|
-
return await this.executeScan(exclusiveStartKey);
|
|
163
|
+
for (const item of result.items) {
|
|
164
|
+
yield item;
|
|
165
|
+
count++;
|
|
166
|
+
if (this._limitVal !== undefined && count >= this._limitVal) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
192
169
|
}
|
|
193
|
-
}
|
|
194
170
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* @throws Error if the query fails.
|
|
200
|
-
*/
|
|
201
|
-
override async execute(): Promise<TResult[]> {
|
|
202
|
-
const { items } = await this.fetchPage();
|
|
203
|
-
return items;
|
|
204
|
-
}
|
|
171
|
+
lastEvaluatedKey = result.lastEvaluatedKey;
|
|
172
|
+
} while (lastEvaluatedKey);
|
|
173
|
+
}.bind(this)();
|
|
174
|
+
}
|
|
205
175
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
ConsistentRead: this._consistentReadVal,
|
|
211
|
-
});
|
|
176
|
+
private async fetchPage(
|
|
177
|
+
exclusiveStartKey?: Record<string, unknown>,
|
|
178
|
+
): Promise<{ items: TResult[]; lastEvaluatedKey?: Record<string, unknown> }> {
|
|
179
|
+
const resolution = this.resolveKeys(this._whereClause, undefined, this._forcedIndexName);
|
|
212
180
|
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
if (
|
|
182
|
+
resolution.hasPartitionKey &&
|
|
183
|
+
resolution.hasSortKey &&
|
|
184
|
+
!resolution.indexName &&
|
|
185
|
+
!exclusiveStartKey
|
|
186
|
+
) {
|
|
187
|
+
const items = await this.executeGet(resolution.keys);
|
|
188
|
+
return { items };
|
|
189
|
+
} else if (resolution.hasPartitionKey || resolution.indexName) {
|
|
190
|
+
return await this.executeQuery(resolution, exclusiveStartKey);
|
|
191
|
+
} else {
|
|
192
|
+
return await this.executeScan(exclusiveStartKey);
|
|
215
193
|
}
|
|
194
|
+
}
|
|
216
195
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Executes the query and returns all matching items.
|
|
198
|
+
*
|
|
199
|
+
* @returns A promise that resolves to an array of items.
|
|
200
|
+
* @throws Error if the query fails.
|
|
201
|
+
*/
|
|
202
|
+
override async execute(): Promise<TResult[]> {
|
|
203
|
+
const { items } = await this.fetchPage();
|
|
204
|
+
return items;
|
|
205
|
+
}
|
|
222
206
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const keyConditionExpression = keyParts.join(" AND ");
|
|
230
|
-
|
|
231
|
-
// DynamoDB does NOT allow primary key attributes in FilterExpression
|
|
232
|
-
const filterExpression = this._whereClause
|
|
233
|
-
? buildExpression(this._whereClause, addName, addValue, keyAttrNames)
|
|
234
|
-
: undefined;
|
|
207
|
+
private async executeGet(keys: Record<string, unknown>): Promise<TResult[]> {
|
|
208
|
+
const command = new GetCommand({
|
|
209
|
+
TableName: this.tableName,
|
|
210
|
+
Key: keys,
|
|
211
|
+
ConsistentRead: this._consistentReadVal,
|
|
212
|
+
});
|
|
235
213
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
KeyConditionExpression: keyConditionExpression,
|
|
240
|
-
FilterExpression: filterExpression || undefined,
|
|
241
|
-
ExpressionAttributeNames: Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : undefined,
|
|
242
|
-
ExpressionAttributeValues: Object.keys(expressionAttributeValues).length > 0 ? expressionAttributeValues : undefined,
|
|
243
|
-
Limit: this._pageSizeVal ?? this._limitVal,
|
|
244
|
-
ScanIndexForward: this._sortForward,
|
|
245
|
-
ConsistentRead: resolution.indexName ? undefined : this._consistentReadVal,
|
|
246
|
-
ExclusiveStartKey: exclusiveStartKey,
|
|
247
|
-
});
|
|
214
|
+
const result = (await this.client.send(command)) as any;
|
|
215
|
+
return result.Item ? ([this.mapToLogical(result.Item)] as TResult[]) : [];
|
|
216
|
+
}
|
|
248
217
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
218
|
+
private async executeQuery(
|
|
219
|
+
resolution: StrategyResolution,
|
|
220
|
+
exclusiveStartKey?: Record<string, unknown>,
|
|
221
|
+
): Promise<{ items: TResult[]; lastEvaluatedKey?: Record<string, unknown> }> {
|
|
222
|
+
const { expressionAttributeNames, expressionAttributeValues, addName, addValue } =
|
|
223
|
+
this.createExpressionContext();
|
|
224
|
+
|
|
225
|
+
const keyParts: string[] = [];
|
|
226
|
+
const keyAttrNames = new Set<string>();
|
|
227
|
+
for (const [key, value] of Object.entries(resolution.keys)) {
|
|
228
|
+
keyParts.push(`${addName(key)} = ${addValue(value)}`);
|
|
229
|
+
keyAttrNames.add(key);
|
|
254
230
|
}
|
|
231
|
+
const keyConditionExpression = keyParts.join(" AND ");
|
|
255
232
|
|
|
256
|
-
|
|
257
|
-
|
|
233
|
+
// DynamoDB does NOT allow primary key attributes in FilterExpression
|
|
234
|
+
const filterExpression = this._whereClause
|
|
235
|
+
? buildExpression(this._whereClause, addName, addValue, keyAttrNames)
|
|
236
|
+
: undefined;
|
|
258
237
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
238
|
+
const command = new QueryCommand({
|
|
239
|
+
TableName: this.tableName,
|
|
240
|
+
IndexName: resolution.indexName,
|
|
241
|
+
KeyConditionExpression: keyConditionExpression,
|
|
242
|
+
FilterExpression: filterExpression || undefined,
|
|
243
|
+
ExpressionAttributeNames:
|
|
244
|
+
Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : undefined,
|
|
245
|
+
ExpressionAttributeValues:
|
|
246
|
+
Object.keys(expressionAttributeValues).length > 0 ? expressionAttributeValues : undefined,
|
|
247
|
+
Limit: this._pageSizeVal ?? this._limitVal,
|
|
248
|
+
ScanIndexForward: this._sortForward,
|
|
249
|
+
ConsistentRead: resolution.indexName ? undefined : this._consistentReadVal,
|
|
250
|
+
ExclusiveStartKey: exclusiveStartKey,
|
|
251
|
+
});
|
|
262
252
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
});
|
|
253
|
+
const response = (await this.client.send(command)) as any;
|
|
254
|
+
return {
|
|
255
|
+
items: (response.Items || []).map((item: Record<string, unknown>) =>
|
|
256
|
+
this.mapToLogical(item),
|
|
257
|
+
) as TResult[],
|
|
258
|
+
lastEvaluatedKey: response.LastEvaluatedKey,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
272
261
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
262
|
+
private async executeScan(
|
|
263
|
+
exclusiveStartKey?: Record<string, unknown>,
|
|
264
|
+
): Promise<{ items: TResult[]; lastEvaluatedKey?: Record<string, unknown> }> {
|
|
265
|
+
const { expressionAttributeNames, expressionAttributeValues, addName, addValue } =
|
|
266
|
+
this.createExpressionContext();
|
|
267
|
+
|
|
268
|
+
const filterExpression = this._whereClause
|
|
269
|
+
? buildExpression(this._whereClause, addName, addValue)
|
|
270
|
+
: undefined;
|
|
271
|
+
|
|
272
|
+
const command = new ScanCommand({
|
|
273
|
+
TableName: this.tableName,
|
|
274
|
+
FilterExpression: filterExpression,
|
|
275
|
+
ExpressionAttributeNames:
|
|
276
|
+
Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : undefined,
|
|
277
|
+
ExpressionAttributeValues:
|
|
278
|
+
Object.keys(expressionAttributeValues).length > 0 ? expressionAttributeValues : undefined,
|
|
279
|
+
Limit: this._pageSizeVal ?? this._limitVal,
|
|
280
|
+
ConsistentRead: this._consistentReadVal,
|
|
281
|
+
ExclusiveStartKey: exclusiveStartKey,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const response = (await this.client.send(command)) as any;
|
|
285
|
+
return {
|
|
286
|
+
items: (response.Items || []).map((item: Record<string, unknown>) =>
|
|
287
|
+
this.mapToLogical(item),
|
|
288
|
+
) as TResult[],
|
|
289
|
+
lastEvaluatedKey: response.LastEvaluatedKey,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
279
292
|
}
|