crud-query-parser 0.1.0 → 1.0.0
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/README.md +138 -35
- package/dist/adapters/array/index.d.mts +90 -0
- package/dist/adapters/array/index.d.ts +90 -0
- package/dist/adapters/array/index.js +2 -0
- package/dist/adapters/array/index.js.map +1 -0
- package/dist/adapters/array/index.mjs +2 -0
- package/dist/adapters/array/index.mjs.map +1 -0
- package/dist/adapters/dynamodb/index.d.mts +239 -0
- package/dist/adapters/dynamodb/index.d.ts +239 -0
- package/dist/adapters/dynamodb/index.js +2 -0
- package/dist/adapters/dynamodb/index.js.map +1 -0
- package/dist/adapters/dynamodb/index.mjs +2 -0
- package/dist/adapters/dynamodb/index.mjs.map +1 -0
- package/dist/adapters/mongodb/index.d.mts +163 -0
- package/dist/adapters/mongodb/index.d.ts +163 -0
- package/dist/adapters/mongodb/index.js +2 -0
- package/dist/adapters/mongodb/index.js.map +1 -0
- package/dist/adapters/mongodb/index.mjs +2 -0
- package/dist/adapters/mongodb/index.mjs.map +1 -0
- package/dist/adapters/typeorm/index.d.mts +4 -4
- package/dist/adapters/typeorm/index.d.ts +4 -4
- package/dist/adapters/typeorm/index.js +1 -1
- package/dist/adapters/typeorm/index.js.map +1 -1
- package/dist/adapters/typeorm/index.mjs +1 -1
- package/dist/adapters/typeorm/index.mjs.map +1 -1
- package/dist/{crud-request-x16CuDRF.d.mts → crud-request-DLo0ZuzD.d.mts} +41 -1
- package/dist/{crud-request-x16CuDRF.d.ts → crud-request-DLo0ZuzD.d.ts} +41 -1
- package/dist/{crud-request-where.builder-BwWLx0Bh.d.mts → crud-request-where.builder-CBx-JZhl.d.mts} +1 -1
- package/dist/{crud-request-where.builder-B5241Aht.d.ts → crud-request-where.builder-CqbP5LT9.d.ts} +1 -1
- package/dist/filters/index.d.mts +1 -1
- package/dist/filters/index.d.ts +1 -1
- package/dist/filters/index.js +1 -1
- package/dist/filters/index.js.map +1 -1
- package/dist/filters/index.mjs +1 -1
- package/dist/filters/index.mjs.map +1 -1
- package/dist/helpers/express/index.d.mts +30 -0
- package/dist/helpers/express/index.d.ts +30 -0
- package/dist/helpers/express/index.js +2 -0
- package/dist/helpers/express/index.js.map +1 -0
- package/dist/helpers/express/index.mjs +2 -0
- package/dist/helpers/express/index.mjs.map +1 -0
- package/dist/helpers/nestjs/index.d.mts +4 -3
- package/dist/helpers/nestjs/index.d.ts +4 -3
- package/dist/helpers/nestjs/index.js +1 -1
- package/dist/helpers/nestjs/index.js.map +1 -1
- package/dist/helpers/nestjs/index.mjs +1 -1
- package/dist/helpers/nestjs/index.mjs.map +1 -1
- package/dist/index.d.mts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/parsers/crud/index.d.mts +44 -5
- package/dist/parsers/crud/index.d.ts +44 -5
- package/dist/parsers/crud/index.js +1 -1
- package/dist/parsers/crud/index.js.map +1 -1
- package/dist/parsers/crud/index.mjs +1 -1
- package/dist/parsers/crud/index.mjs.map +1 -1
- package/dist/{query-adapter-CEcyFcWr.d.ts → query-adapter-CZhPC1aq.d.ts} +3 -3
- package/dist/{query-adapter-CeTK3yxp.d.mts → query-adapter-sgeUb8CV.d.mts} +3 -3
- package/dist/{request-parser-BxVulcsX.d.ts → request-parser-Cr3cxMRw.d.ts} +4 -4
- package/dist/{request-parser-BMkszvGr.d.mts → request-parser-DzuXbRsB.d.mts} +4 -4
- package/package.json +83 -5
@@ -0,0 +1,239 @@
|
|
1
|
+
import { DynamoDBClient, GetItemInput, ScanInput, QueryInput, AttributeValue } from '@aws-sdk/client-dynamodb';
|
2
|
+
import { g as CrudRequestWhereField, F as FieldPath, C as CrudRequest, P as ParsedRequestSelect, c as CrudRequestOrder, d as CrudRequestWhere } from '../../crud-request-DLo0ZuzD.mjs';
|
3
|
+
import { Q as QueryAdapter, G as GetManyResult } from '../../query-adapter-sgeUb8CV.mjs';
|
4
|
+
|
5
|
+
interface DynamoDBQueryAdapterOptions {
|
6
|
+
/**
|
7
|
+
* The DynamoDB client
|
8
|
+
*/
|
9
|
+
client: DynamoDBClient;
|
10
|
+
/**
|
11
|
+
* The DynamoDB table name
|
12
|
+
*/
|
13
|
+
tableName: string;
|
14
|
+
/**
|
15
|
+
* The table partition key
|
16
|
+
*/
|
17
|
+
partitionKey: string;
|
18
|
+
/**
|
19
|
+
* The table sort key
|
20
|
+
*/
|
21
|
+
sortKey?: string;
|
22
|
+
/**
|
23
|
+
* Whether the count will be disabled in getMany(). Disabling count saves read capacity units.
|
24
|
+
*/
|
25
|
+
disableCount?: boolean;
|
26
|
+
/**
|
27
|
+
* Whether a Scan command should not run when a GetItem or Query command are not possible
|
28
|
+
*/
|
29
|
+
disableScan?: boolean;
|
30
|
+
}
|
31
|
+
/**
|
32
|
+
* Represents a generic DynamoDB query
|
33
|
+
*/
|
34
|
+
type DynamoDBQuery = Partial<GetItemInput> & Partial<ScanInput> & Partial<QueryInput>;
|
35
|
+
/**
|
36
|
+
* Represents a command input that is either a DynamoDB GetItem, DynamoDB Query or a DynamoDB Scan
|
37
|
+
*/
|
38
|
+
type GetOrQueryOrScanInput = {
|
39
|
+
count: GetItemInput;
|
40
|
+
full: GetItemInput;
|
41
|
+
type: 'get';
|
42
|
+
} | {
|
43
|
+
count: QueryInput;
|
44
|
+
full: QueryInput;
|
45
|
+
type: 'query';
|
46
|
+
} | {
|
47
|
+
count: ScanInput;
|
48
|
+
full: ScanInput;
|
49
|
+
type: 'scan';
|
50
|
+
};
|
51
|
+
interface DynamoDBQueryContext {
|
52
|
+
/**
|
53
|
+
* Whether the query should split the primary keys from the filter expressions to the key parameter
|
54
|
+
*/
|
55
|
+
allowKeySplitting?: boolean;
|
56
|
+
/**
|
57
|
+
* The key parameter
|
58
|
+
*/
|
59
|
+
key?: CrudRequestWhereField[];
|
60
|
+
}
|
61
|
+
/**
|
62
|
+
* Adapts queries to DynamoDB query builder object.
|
63
|
+
*
|
64
|
+
* Not supported:
|
65
|
+
* - Ordering by any other field except the sort key
|
66
|
+
* - Page
|
67
|
+
* - Offset
|
68
|
+
* - Relations
|
69
|
+
*
|
70
|
+
* The ordering only works for the sort key and in query operations.
|
71
|
+
* It's ignored in scan operations.
|
72
|
+
*/
|
73
|
+
declare class DynamoDBQueryAdapter implements QueryAdapter<DynamoDBQuery> {
|
74
|
+
protected readonly options: DynamoDBQueryAdapterOptions;
|
75
|
+
protected readonly partitionKey: FieldPath;
|
76
|
+
protected readonly sortKey?: FieldPath;
|
77
|
+
constructor(options: DynamoDBQueryAdapterOptions);
|
78
|
+
/**
|
79
|
+
* @inheritDoc
|
80
|
+
*/
|
81
|
+
build(baseQuery: DynamoDBQuery, request: CrudRequest): DynamoDBQuery;
|
82
|
+
/**
|
83
|
+
* @inheritDoc
|
84
|
+
*/
|
85
|
+
getMany<E>(baseQuery: DynamoDBQuery, request: CrudRequest): Promise<GetManyResult<E>>;
|
86
|
+
/**
|
87
|
+
* @inheritDoc
|
88
|
+
*/
|
89
|
+
getOne<E>(baseQuery: DynamoDBQuery, request: CrudRequest): Promise<E | null>;
|
90
|
+
/**
|
91
|
+
* Creates a DynamoDB Query input
|
92
|
+
*
|
93
|
+
* @param baseQuery The base query
|
94
|
+
* @param request The crud request
|
95
|
+
*/
|
96
|
+
buildQuery(baseQuery: Partial<QueryInput>, request: CrudRequest): QueryInput;
|
97
|
+
/**
|
98
|
+
* Creates a DynamoDB Scan input
|
99
|
+
*
|
100
|
+
* @param baseQuery The base query
|
101
|
+
* @param request The crud request
|
102
|
+
*/
|
103
|
+
buildScan(baseQuery: Partial<ScanInput>, request: CrudRequest): ScanInput;
|
104
|
+
/**
|
105
|
+
* Creates a DynamoDB GetItem input
|
106
|
+
*
|
107
|
+
* @param baseQuery The base query
|
108
|
+
* @param request The crud request
|
109
|
+
*/
|
110
|
+
buildGetItem(baseQuery: Partial<GetItemInput>, request: CrudRequest): GetItemInput;
|
111
|
+
/**
|
112
|
+
* Creates a DynamoDB GetItem, Query or Scan input, based on whether the partition key and sort key are present in the where conditions
|
113
|
+
*
|
114
|
+
* @param baseInput The base query
|
115
|
+
* @param request The crud request
|
116
|
+
*/
|
117
|
+
protected buildBaseGetOrQueryOrScan(baseInput: DynamoDBQuery, request: CrudRequest): GetOrQueryOrScanInput;
|
118
|
+
/**
|
119
|
+
* Fetches data through a GetItem, Query or Scan command. Optionally fetches the count too.
|
120
|
+
*
|
121
|
+
* @param mixed The GetItem, Query or Scan input
|
122
|
+
* @param fetchCount Whether it should fetch the total number of items too.
|
123
|
+
*/
|
124
|
+
protected fetchDataAndCount<E>(mixed: GetOrQueryOrScanInput, fetchCount: boolean): Promise<[E[], number?]>;
|
125
|
+
/**
|
126
|
+
* Gets the command to run based on the key combination available.
|
127
|
+
*
|
128
|
+
* If the complete primary key is available, it results in GetItem.
|
129
|
+
* If only the partition key is available but not the sort key, it results in Query.
|
130
|
+
* If no keys are available, it resutls in Scan.
|
131
|
+
*
|
132
|
+
* @param input The DynamoDB query
|
133
|
+
* @param keys The primary keys
|
134
|
+
*/
|
135
|
+
protected getAvailableCommandByKey(input: DynamoDBQuery, keys: CrudRequestWhereField[] | undefined): 'get' | 'query' | 'scan';
|
136
|
+
/**
|
137
|
+
* Adapts the key conditions into a key expression
|
138
|
+
*
|
139
|
+
* @param query The DynamoDB query
|
140
|
+
* @param keys The key conditions
|
141
|
+
*/
|
142
|
+
protected adaptQueryKeyExpression(query: Partial<QueryInput>, keys: CrudRequestWhereField[]): void;
|
143
|
+
/**
|
144
|
+
* Adapts the key conditions into a filter expression
|
145
|
+
*
|
146
|
+
* @param query The DynamoDB query
|
147
|
+
* @param keys The key conditions
|
148
|
+
*/
|
149
|
+
protected adaptFilterKeyExpression(query: Partial<ScanInput>, keys: CrudRequestWhereField[]): void;
|
150
|
+
/**
|
151
|
+
* Adapts the key conditions into a key object
|
152
|
+
*
|
153
|
+
* @param query The DynamoDB query
|
154
|
+
* @param keys The key conditions
|
155
|
+
*/
|
156
|
+
protected adaptGetItemKey(query: Partial<GetItemInput>, keys: CrudRequestWhereField[]): void;
|
157
|
+
/**
|
158
|
+
* Adapts a list of select fields into a projection expression
|
159
|
+
*
|
160
|
+
* @param query The DynamoDB query
|
161
|
+
* @param select The select fields
|
162
|
+
*/
|
163
|
+
protected adaptProjection(query: DynamoDBQuery, select: ParsedRequestSelect): void;
|
164
|
+
/**
|
165
|
+
* Adapts the order field that matches the sort key to a DynamoDB Query
|
166
|
+
*
|
167
|
+
* @param query The DynamoDB query
|
168
|
+
* @param order The order fields
|
169
|
+
*/
|
170
|
+
protected adaptOrder(query: DynamoDBQuery, order: CrudRequestOrder[]): void;
|
171
|
+
/**
|
172
|
+
* Adapts a where condition into a DynamoDB filter
|
173
|
+
*
|
174
|
+
* @param query The DynamoDB query
|
175
|
+
* @param ctx The builder context
|
176
|
+
* @param where The where condition
|
177
|
+
*/
|
178
|
+
protected adaptFilter(query: DynamoDBQuery, ctx: DynamoDBQueryContext, where: CrudRequestWhere): void;
|
179
|
+
/**
|
180
|
+
* Adapts the limit
|
181
|
+
*
|
182
|
+
* @param query The DynamoDB query
|
183
|
+
* @param limit The limit value
|
184
|
+
*/
|
185
|
+
protected adaptLimit(query: DynamoDBQuery, limit: number | undefined): void;
|
186
|
+
/**
|
187
|
+
* Maps a where condition into a filter expression
|
188
|
+
*
|
189
|
+
* @param query The DynamoDB query
|
190
|
+
* @param ctx The query builder context
|
191
|
+
* @param where The where condition
|
192
|
+
* @param isTopLevelAnd Whether this is the top level AND condition
|
193
|
+
*/
|
194
|
+
protected mapWhere(query: DynamoDBQuery, ctx: DynamoDBQueryContext, where: CrudRequestWhere, isTopLevelAnd?: boolean): string | undefined;
|
195
|
+
/**
|
196
|
+
* Maps a where condition into an expression and its parameters
|
197
|
+
*
|
198
|
+
* @param query The DynamoDB query
|
199
|
+
* @param where The where condition
|
200
|
+
*/
|
201
|
+
protected mapWhereOperators(query: DynamoDBQuery, where: CrudRequestWhereField): {
|
202
|
+
where: string;
|
203
|
+
params: Record<string, any>;
|
204
|
+
};
|
205
|
+
/**
|
206
|
+
* Generates the attribute name and registers an attribute to the query
|
207
|
+
*
|
208
|
+
* @param query The DynamoDB query
|
209
|
+
* @param field The field path
|
210
|
+
*/
|
211
|
+
protected registerAttribute(query: DynamoDBQuery, field: FieldPath): string;
|
212
|
+
/**
|
213
|
+
* Creates a unique query parameter name based on a field
|
214
|
+
*
|
215
|
+
* @param query The DynamoDB query
|
216
|
+
* @param name The parameter name, which should start with ":"
|
217
|
+
*/
|
218
|
+
protected createUniqueParam(query: DynamoDBQuery, name: string): string;
|
219
|
+
/**
|
220
|
+
* Wraps an expression with parenthesis
|
221
|
+
*
|
222
|
+
* @param expression The filter expression
|
223
|
+
*/
|
224
|
+
protected wrapParenthesis(expression: string): string;
|
225
|
+
/**
|
226
|
+
* Converts an object into DynamoDB's attribute key-value structure
|
227
|
+
*
|
228
|
+
* @param data The object
|
229
|
+
*/
|
230
|
+
protected marshall<T>(data: T): Record<string, AttributeValue>;
|
231
|
+
/**
|
232
|
+
* Converts a DynamoDB's attribute key-value structure into an object
|
233
|
+
*
|
234
|
+
* @param data The attribute key-value
|
235
|
+
*/
|
236
|
+
protected unmarshall<T>(data: Record<string, AttributeValue>): T;
|
237
|
+
}
|
238
|
+
|
239
|
+
export { type DynamoDBQuery, DynamoDBQueryAdapter, type DynamoDBQueryAdapterOptions, type DynamoDBQueryContext, type GetOrQueryOrScanInput };
|
@@ -0,0 +1,239 @@
|
|
1
|
+
import { DynamoDBClient, GetItemInput, ScanInput, QueryInput, AttributeValue } from '@aws-sdk/client-dynamodb';
|
2
|
+
import { g as CrudRequestWhereField, F as FieldPath, C as CrudRequest, P as ParsedRequestSelect, c as CrudRequestOrder, d as CrudRequestWhere } from '../../crud-request-DLo0ZuzD.js';
|
3
|
+
import { Q as QueryAdapter, G as GetManyResult } from '../../query-adapter-CZhPC1aq.js';
|
4
|
+
|
5
|
+
interface DynamoDBQueryAdapterOptions {
|
6
|
+
/**
|
7
|
+
* The DynamoDB client
|
8
|
+
*/
|
9
|
+
client: DynamoDBClient;
|
10
|
+
/**
|
11
|
+
* The DynamoDB table name
|
12
|
+
*/
|
13
|
+
tableName: string;
|
14
|
+
/**
|
15
|
+
* The table partition key
|
16
|
+
*/
|
17
|
+
partitionKey: string;
|
18
|
+
/**
|
19
|
+
* The table sort key
|
20
|
+
*/
|
21
|
+
sortKey?: string;
|
22
|
+
/**
|
23
|
+
* Whether the count will be disabled in getMany(). Disabling count saves read capacity units.
|
24
|
+
*/
|
25
|
+
disableCount?: boolean;
|
26
|
+
/**
|
27
|
+
* Whether a Scan command should not run when a GetItem or Query command are not possible
|
28
|
+
*/
|
29
|
+
disableScan?: boolean;
|
30
|
+
}
|
31
|
+
/**
|
32
|
+
* Represents a generic DynamoDB query
|
33
|
+
*/
|
34
|
+
type DynamoDBQuery = Partial<GetItemInput> & Partial<ScanInput> & Partial<QueryInput>;
|
35
|
+
/**
|
36
|
+
* Represents a command input that is either a DynamoDB GetItem, DynamoDB Query or a DynamoDB Scan
|
37
|
+
*/
|
38
|
+
type GetOrQueryOrScanInput = {
|
39
|
+
count: GetItemInput;
|
40
|
+
full: GetItemInput;
|
41
|
+
type: 'get';
|
42
|
+
} | {
|
43
|
+
count: QueryInput;
|
44
|
+
full: QueryInput;
|
45
|
+
type: 'query';
|
46
|
+
} | {
|
47
|
+
count: ScanInput;
|
48
|
+
full: ScanInput;
|
49
|
+
type: 'scan';
|
50
|
+
};
|
51
|
+
interface DynamoDBQueryContext {
|
52
|
+
/**
|
53
|
+
* Whether the query should split the primary keys from the filter expressions to the key parameter
|
54
|
+
*/
|
55
|
+
allowKeySplitting?: boolean;
|
56
|
+
/**
|
57
|
+
* The key parameter
|
58
|
+
*/
|
59
|
+
key?: CrudRequestWhereField[];
|
60
|
+
}
|
61
|
+
/**
|
62
|
+
* Adapts queries to DynamoDB query builder object.
|
63
|
+
*
|
64
|
+
* Not supported:
|
65
|
+
* - Ordering by any other field except the sort key
|
66
|
+
* - Page
|
67
|
+
* - Offset
|
68
|
+
* - Relations
|
69
|
+
*
|
70
|
+
* The ordering only works for the sort key and in query operations.
|
71
|
+
* It's ignored in scan operations.
|
72
|
+
*/
|
73
|
+
declare class DynamoDBQueryAdapter implements QueryAdapter<DynamoDBQuery> {
|
74
|
+
protected readonly options: DynamoDBQueryAdapterOptions;
|
75
|
+
protected readonly partitionKey: FieldPath;
|
76
|
+
protected readonly sortKey?: FieldPath;
|
77
|
+
constructor(options: DynamoDBQueryAdapterOptions);
|
78
|
+
/**
|
79
|
+
* @inheritDoc
|
80
|
+
*/
|
81
|
+
build(baseQuery: DynamoDBQuery, request: CrudRequest): DynamoDBQuery;
|
82
|
+
/**
|
83
|
+
* @inheritDoc
|
84
|
+
*/
|
85
|
+
getMany<E>(baseQuery: DynamoDBQuery, request: CrudRequest): Promise<GetManyResult<E>>;
|
86
|
+
/**
|
87
|
+
* @inheritDoc
|
88
|
+
*/
|
89
|
+
getOne<E>(baseQuery: DynamoDBQuery, request: CrudRequest): Promise<E | null>;
|
90
|
+
/**
|
91
|
+
* Creates a DynamoDB Query input
|
92
|
+
*
|
93
|
+
* @param baseQuery The base query
|
94
|
+
* @param request The crud request
|
95
|
+
*/
|
96
|
+
buildQuery(baseQuery: Partial<QueryInput>, request: CrudRequest): QueryInput;
|
97
|
+
/**
|
98
|
+
* Creates a DynamoDB Scan input
|
99
|
+
*
|
100
|
+
* @param baseQuery The base query
|
101
|
+
* @param request The crud request
|
102
|
+
*/
|
103
|
+
buildScan(baseQuery: Partial<ScanInput>, request: CrudRequest): ScanInput;
|
104
|
+
/**
|
105
|
+
* Creates a DynamoDB GetItem input
|
106
|
+
*
|
107
|
+
* @param baseQuery The base query
|
108
|
+
* @param request The crud request
|
109
|
+
*/
|
110
|
+
buildGetItem(baseQuery: Partial<GetItemInput>, request: CrudRequest): GetItemInput;
|
111
|
+
/**
|
112
|
+
* Creates a DynamoDB GetItem, Query or Scan input, based on whether the partition key and sort key are present in the where conditions
|
113
|
+
*
|
114
|
+
* @param baseInput The base query
|
115
|
+
* @param request The crud request
|
116
|
+
*/
|
117
|
+
protected buildBaseGetOrQueryOrScan(baseInput: DynamoDBQuery, request: CrudRequest): GetOrQueryOrScanInput;
|
118
|
+
/**
|
119
|
+
* Fetches data through a GetItem, Query or Scan command. Optionally fetches the count too.
|
120
|
+
*
|
121
|
+
* @param mixed The GetItem, Query or Scan input
|
122
|
+
* @param fetchCount Whether it should fetch the total number of items too.
|
123
|
+
*/
|
124
|
+
protected fetchDataAndCount<E>(mixed: GetOrQueryOrScanInput, fetchCount: boolean): Promise<[E[], number?]>;
|
125
|
+
/**
|
126
|
+
* Gets the command to run based on the key combination available.
|
127
|
+
*
|
128
|
+
* If the complete primary key is available, it results in GetItem.
|
129
|
+
* If only the partition key is available but not the sort key, it results in Query.
|
130
|
+
* If no keys are available, it resutls in Scan.
|
131
|
+
*
|
132
|
+
* @param input The DynamoDB query
|
133
|
+
* @param keys The primary keys
|
134
|
+
*/
|
135
|
+
protected getAvailableCommandByKey(input: DynamoDBQuery, keys: CrudRequestWhereField[] | undefined): 'get' | 'query' | 'scan';
|
136
|
+
/**
|
137
|
+
* Adapts the key conditions into a key expression
|
138
|
+
*
|
139
|
+
* @param query The DynamoDB query
|
140
|
+
* @param keys The key conditions
|
141
|
+
*/
|
142
|
+
protected adaptQueryKeyExpression(query: Partial<QueryInput>, keys: CrudRequestWhereField[]): void;
|
143
|
+
/**
|
144
|
+
* Adapts the key conditions into a filter expression
|
145
|
+
*
|
146
|
+
* @param query The DynamoDB query
|
147
|
+
* @param keys The key conditions
|
148
|
+
*/
|
149
|
+
protected adaptFilterKeyExpression(query: Partial<ScanInput>, keys: CrudRequestWhereField[]): void;
|
150
|
+
/**
|
151
|
+
* Adapts the key conditions into a key object
|
152
|
+
*
|
153
|
+
* @param query The DynamoDB query
|
154
|
+
* @param keys The key conditions
|
155
|
+
*/
|
156
|
+
protected adaptGetItemKey(query: Partial<GetItemInput>, keys: CrudRequestWhereField[]): void;
|
157
|
+
/**
|
158
|
+
* Adapts a list of select fields into a projection expression
|
159
|
+
*
|
160
|
+
* @param query The DynamoDB query
|
161
|
+
* @param select The select fields
|
162
|
+
*/
|
163
|
+
protected adaptProjection(query: DynamoDBQuery, select: ParsedRequestSelect): void;
|
164
|
+
/**
|
165
|
+
* Adapts the order field that matches the sort key to a DynamoDB Query
|
166
|
+
*
|
167
|
+
* @param query The DynamoDB query
|
168
|
+
* @param order The order fields
|
169
|
+
*/
|
170
|
+
protected adaptOrder(query: DynamoDBQuery, order: CrudRequestOrder[]): void;
|
171
|
+
/**
|
172
|
+
* Adapts a where condition into a DynamoDB filter
|
173
|
+
*
|
174
|
+
* @param query The DynamoDB query
|
175
|
+
* @param ctx The builder context
|
176
|
+
* @param where The where condition
|
177
|
+
*/
|
178
|
+
protected adaptFilter(query: DynamoDBQuery, ctx: DynamoDBQueryContext, where: CrudRequestWhere): void;
|
179
|
+
/**
|
180
|
+
* Adapts the limit
|
181
|
+
*
|
182
|
+
* @param query The DynamoDB query
|
183
|
+
* @param limit The limit value
|
184
|
+
*/
|
185
|
+
protected adaptLimit(query: DynamoDBQuery, limit: number | undefined): void;
|
186
|
+
/**
|
187
|
+
* Maps a where condition into a filter expression
|
188
|
+
*
|
189
|
+
* @param query The DynamoDB query
|
190
|
+
* @param ctx The query builder context
|
191
|
+
* @param where The where condition
|
192
|
+
* @param isTopLevelAnd Whether this is the top level AND condition
|
193
|
+
*/
|
194
|
+
protected mapWhere(query: DynamoDBQuery, ctx: DynamoDBQueryContext, where: CrudRequestWhere, isTopLevelAnd?: boolean): string | undefined;
|
195
|
+
/**
|
196
|
+
* Maps a where condition into an expression and its parameters
|
197
|
+
*
|
198
|
+
* @param query The DynamoDB query
|
199
|
+
* @param where The where condition
|
200
|
+
*/
|
201
|
+
protected mapWhereOperators(query: DynamoDBQuery, where: CrudRequestWhereField): {
|
202
|
+
where: string;
|
203
|
+
params: Record<string, any>;
|
204
|
+
};
|
205
|
+
/**
|
206
|
+
* Generates the attribute name and registers an attribute to the query
|
207
|
+
*
|
208
|
+
* @param query The DynamoDB query
|
209
|
+
* @param field The field path
|
210
|
+
*/
|
211
|
+
protected registerAttribute(query: DynamoDBQuery, field: FieldPath): string;
|
212
|
+
/**
|
213
|
+
* Creates a unique query parameter name based on a field
|
214
|
+
*
|
215
|
+
* @param query The DynamoDB query
|
216
|
+
* @param name The parameter name, which should start with ":"
|
217
|
+
*/
|
218
|
+
protected createUniqueParam(query: DynamoDBQuery, name: string): string;
|
219
|
+
/**
|
220
|
+
* Wraps an expression with parenthesis
|
221
|
+
*
|
222
|
+
* @param expression The filter expression
|
223
|
+
*/
|
224
|
+
protected wrapParenthesis(expression: string): string;
|
225
|
+
/**
|
226
|
+
* Converts an object into DynamoDB's attribute key-value structure
|
227
|
+
*
|
228
|
+
* @param data The object
|
229
|
+
*/
|
230
|
+
protected marshall<T>(data: T): Record<string, AttributeValue>;
|
231
|
+
/**
|
232
|
+
* Converts a DynamoDB's attribute key-value structure into an object
|
233
|
+
*
|
234
|
+
* @param data The attribute key-value
|
235
|
+
*/
|
236
|
+
protected unmarshall<T>(data: Record<string, AttributeValue>): T;
|
237
|
+
}
|
238
|
+
|
239
|
+
export { type DynamoDBQuery, DynamoDBQueryAdapter, type DynamoDBQueryAdapterOptions, type DynamoDBQueryContext, type GetOrQueryOrScanInput };
|
@@ -0,0 +1,2 @@
|
|
1
|
+
"use strict";var m=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var u=(o,e)=>m(o,"name",{value:e,configurable:!0});var x=(o,e)=>{for(var n in e)m(o,n,{get:e[n],enumerable:!0})},I=(o,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of w(e))!T.call(o,r)&&r!==n&&m(o,r,{get:()=>e[r],enumerable:!(t=D(e,r))||t.enumerable});return o};var S=o=>I(m({},"__esModule",{value:!0}),o);var Q={};x(Q,{DynamoDBQueryAdapter:()=>b});module.exports=S(Q);var p=require("@aws-sdk/client-dynamodb"),d=require("@aws-sdk/util-dynamodb");function y(o,e,n=0){if(!Array.isArray(e)||e.length<n)throw new Error(`${o} must be an array with at least ${n} items`);return e}u(y,"ensureArray");function h(o,e){if(E(e)&&e!==!0)throw new Error(`${o} must be true, null or undefined`)}u(h,"ensureEmpty");function E(o){return o!=null}u(E,"isValid");function g(o){return typeof o=="string"?o.split("."):o}u(g,"pathParse");function c(o,e){return o.length!==e.length?!1:o.every((n,t)=>e[t]===n)}u(c,"pathEquals");function N(o,e,n,t){let r=o.length,i=t??e,s=i>0?Math.floor(n/i)+1:1,a=i>0?Math.ceil(e/i):0;return{data:o,count:r,total:e,page:s,pageCount:a}}u(N,"createGetManyResult");var b=class{constructor(e){this.options=e;this.partitionKey=g(e.partitionKey),this.sortKey=e.sortKey?g(e.sortKey):void 0}static{u(this,"DynamoDBQueryAdapter")}partitionKey;sortKey;build(e,n){let{full:t}=this.buildBaseGetOrQueryOrScan(e,n);return t}async getMany(e,n){let t=this.buildBaseGetOrQueryOrScan(e,n),[r,i]=await this.fetchDataAndCount(t,!0),s=n.limit||e.Limit;return N(r,i||0,0,s)}async getOne(e,n){let t=this.buildBaseGetOrQueryOrScan(e,{...n,limit:1}),[r]=await this.fetchDataAndCount(t,!1);return r.length===0?null:r[0]}buildQuery(e,n){let t={...e,TableName:e.TableName||this.options.tableName},r={allowKeySplitting:!0};return this.adaptProjection(t,n.select),this.adaptFilter(t,r,n.where),this.adaptOrder(t,n.order),this.adaptLimit(t,n.limit),r.key&&this.adaptQueryKeyExpression(t,r.key),t}buildScan(e,n){let t={...e,TableName:e.TableName||this.options.tableName},r={allowKeySplitting:!1};return this.adaptProjection(t,n.select),this.adaptFilter(t,r,n.where),this.adaptLimit(t,n.limit),t}buildGetItem(e,n){let t={...e,TableName:e.TableName||this.options.tableName,Key:e.Key},r={allowKeySplitting:!0};return this.adaptProjection(t,n.select),this.adaptFilter({},r,n.where),r.key&&this.adaptGetItemKey(t,r.key),t}buildBaseGetOrQueryOrScan(e,n){let t={...e,TableName:e.TableName||this.options.tableName},r={allowKeySplitting:!0};this.adaptFilter(t,r,n.where);let i=u(a=>{let l={...t,ExpressionAttributeNames:{...t.ExpressionAttributeNames},ExpressionAttributeValues:{...t.ExpressionAttributeValues},Select:"COUNT"};return this.adaptProjection(t,n.select),this.adaptOrder(t,n.order),this.adaptLimit(t,n.limit),{count:l,full:t,type:a}},"mapResult");if(t.Key)return i("get");if(t.KeyConditionExpression)return i("query");let s=this.getAvailableCommandByKey(t,r.key);return s==="get"&&r.key?(this.adaptGetItemKey(t,r.key),i("get")):s==="query"&&r.key?(this.adaptQueryKeyExpression(t,r.key),i("query")):(r.key&&this.adaptFilterKeyExpression(t,r.key),i("scan"))}async fetchDataAndCount(e,n){if(e.type==="get"){let r=await this.options.client.send(new p.GetItemCommand(e.full));return r.Item?[[this.unmarshall(r.Item)],1]:[[],0]}let t=n&&!this.options.disableCount;if(e.type==="query"){let[r,i]=await Promise.all([this.options.client.send(new p.QueryCommand(e.full)),t?this.options.client.send(new p.QueryCommand(e.count)):void 0]);return[(r.Items||[]).map(a=>this.unmarshall(a)),i?.Count]}if(e.type==="scan"&&!this.options.disableScan){let[r,i]=await Promise.all([this.options.client.send(new p.ScanCommand(e.full)),t?this.options.client.send(new p.ScanCommand(e.count)):void 0]);return[(r.Items||[]).map(a=>this.unmarshall(a)),i?.Count]}throw new Error("The partition key is missing in the query. Scan is disabled")}getAvailableCommandByKey(e,n){if(!n)return"scan";let t=!1,r=!this.sortKey;for(let i of n){let s=i.operator==="eq";c(i.field,this.partitionKey)&&s&&(t=!0),this.sortKey&&c(i.field,this.sortKey)&&s&&(r=!0)}return t&&r&&!e.FilterExpression?"get":t?"query":"scan"}adaptQueryKeyExpression(e,n){let t=[];for(let r of n){let i=this.mapWhereOperators(e,r);e.ExpressionAttributeValues={...e.ExpressionAttributeValues||{},...this.marshall(i.params)},t.push(i.where)}e.KeyConditionExpression=t.join(" AND ")}adaptFilterKeyExpression(e,n){let t=[];for(let r of n){let i=this.mapWhereOperators(e,r);e.ExpressionAttributeValues={...e.ExpressionAttributeValues||{},...this.marshall(i.params)},t.push(i.where)}e.FilterExpression?e.FilterExpression=t.join(" AND ")+" AND "+this.wrapParenthesis(e.FilterExpression):e.FilterExpression=t.join(" AND ")}adaptGetItemKey(e,n){let t=e.Key?this.unmarshall(e.Key):{};for(let r of n)r.operator==="eq"&&(t[r.field.join(".")]=r.value);e.Key=this.marshall(t)}adaptProjection(e,n){if(n.length===0)return;let t=e.ProjectionExpression?.split(",").map(i=>i.trim()).filter(i=>!!i)||[],r=n.map(i=>this.registerAttribute(e,i.field));e.ProjectionExpression=[...new Set([...t,...r])].join(", ")}adaptOrder(e,n){let t=this.sortKey;if(!t)return;let r=n.find(i=>c(i.field,t));r&&(e.ScanIndexForward=r.order==="ASC")}adaptFilter(e,n,t){let r=this.mapWhere(e,n,t,!0);if(!r)return;let i=e.FilterExpression;e.FilterExpression=i?`${this.wrapParenthesis(i)} AND ${this.wrapParenthesis(r)}`:r}adaptLimit(e,n){n&&(e.Limit=n)}mapWhere(e,n,t,r=!1){if(t.and&&t.and.length>0)return t.and.length===1?this.mapWhere(e,n,t.and[0],r):this.wrapParenthesis(t.and.map(i=>this.mapWhere(e,n,i,r)).filter(i=>!!i).join(" AND "));if(t.or&&t.or.length>0)return t.or.length===1?this.mapWhere(e,n,t.or[0],r):this.wrapParenthesis(t.or.map(i=>this.mapWhere(e,n,i,!1)).filter(i=>!!i).join(" OR "));if(t.field){if(r&&n.allowKeySplitting&&(c(this.partitionKey,t.field)&&t.operator==="eq"||this.sortKey&&c(this.sortKey,t.field))){n.key=n.key||[],n.key.push(t);return}let i=this.mapWhereOperators(e,t);return e.ExpressionAttributeValues={...e.ExpressionAttributeValues||{},...this.marshall(i.params)},i.where}}mapWhereOperators(e,n){let t=this.registerAttribute(e,n.field),r=this.createUniqueParam(e,t.replace("#",":")),i=n.value;switch(n.operator){case"eq":return{where:`${t} = ${r}`,params:{[r]:i}};case"neq":return{where:`${t} <> ${r}`,params:{[r]:i}};case"lt":return{where:`${t} < ${r}`,params:{[r]:i}};case"lte":return{where:`${t} <= ${r}`,params:{[r]:i}};case"gt":return{where:`${t} > ${r}`,params:{[r]:i}};case"gte":return{where:`${t} >= ${r}`,params:{[r]:i}};case"starts":return{where:`begins_with(${t}, ${r})`,params:{[r]:i}};case"contains":return{where:`contains(${t}, ${r})`,params:{[r]:i}};case"not_contains":return{where:`NOT contains(${t}, ${r})`,params:{[r]:i}};case"between":let s=y("BETWEEN operator",i,2);return{where:`${t} BETWEEN ${r}_start AND ${r}_end`,params:{[`${r}_start`]:s[0],[`${r}_end`]:s[1]}};case"in":return i=y("IN operator",i,1),{where:`${t} IN (${i.map((a,l)=>r+"_"+l).join(", ")})`,params:i.reduce((a,l,f)=>({...a,[r+"_"+f]:l}),{})};case"not_in":return i=y("NOT IN operator",i,1),{where:`NOT (${t} IN (${i.map((a,l)=>r+"_"+l).join(", ")}))`,params:i.reduce((a,l,f)=>({...a,[r+"_"+f]:l}),{})};case"is_null":return h("IS NULL operator",i),{where:`(attribute_not_exists(${t}) OR ${t} = :null)`,params:{":null":null}};case"not_null":return h("NOT NULL operator",i),{where:`(attribute_exists(${t}) AND ${t} <> :null)`,params:{":null":null}}}throw new Error(`Operator not supported in DynamoDB "${n.operator}"`)}registerAttribute(e,n){let t=n.join("."),r="#"+t.replace(/[^A-Za-z0-9_]/g,"_"),i=r,s=1,a=e.ExpressionAttributeNames||{};for(;a[i]&&a[i]!==t;)i=r+s.toString(),s++;return a[i]=t,e.ExpressionAttributeNames=a,i}createUniqueParam(e,n){let t=n,r=1;for(;e.ExpressionAttributeValues?.[t];)t=n+r.toString(),r++;return t}wrapParenthesis(e){return e?e.startsWith("(")&&e.endsWith(")")?e:`(${e})`:""}marshall(e){return(0,d.marshall)(e)}unmarshall(e){return(0,d.unmarshall)(e)}};0&&(module.exports={DynamoDBQueryAdapter});
|
2
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/dynamodb/index.ts","../../../src/adapters/dynamodb/dynamodb.query-adapter.ts","../../../src/utils/functions.ts","../../../src/utils/field-path.ts","../../../src/utils/objects.ts"],"sourcesContent":["\r\nexport * from './dynamodb.query-adapter';\r\n","import {\r\n AttributeValue,\r\n DynamoDBClient,\r\n GetItemCommand,\r\n GetItemInput,\r\n QueryCommand,\r\n QueryInput,\r\n ScanCommand,\r\n ScanInput,\r\n} from '@aws-sdk/client-dynamodb';\r\nimport { marshall, unmarshall } from '@aws-sdk/util-dynamodb';\r\nimport { CrudRequestWhere, CrudRequestWhereField, CrudRequestWhereOperator } from '../../models/crud-request-where';\r\nimport { CrudRequest, CrudRequestOrder, ParsedRequestSelect } from '../../models/crud-request';\r\nimport { QueryAdapter } from '../../models/query-adapter';\r\nimport { GetManyResult } from '../../models/get-many-result';\r\nimport { FieldPath } from '../../models/field-path';\r\nimport { pathEquals, pathParse } from '../../utils/field-path';\r\nimport { ensureArray, ensureEmpty } from '../../utils/functions';\r\nimport { createGetManyResult } from '../../utils/objects';\r\n\r\nexport interface DynamoDBQueryAdapterOptions {\r\n /**\r\n * The DynamoDB client\r\n */\r\n client: DynamoDBClient;\r\n\r\n /**\r\n * The DynamoDB table name\r\n */\r\n tableName: string;\r\n\r\n /**\r\n * The table partition key\r\n */\r\n partitionKey: string;\r\n\r\n /**\r\n * The table sort key\r\n */\r\n sortKey?: string;\r\n\r\n /**\r\n * Whether the count will be disabled in getMany(). Disabling count saves read capacity units.\r\n */\r\n disableCount?: boolean;\r\n\r\n /**\r\n * Whether a Scan command should not run when a GetItem or Query command are not possible\r\n */\r\n disableScan?: boolean;\r\n}\r\n\r\n/**\r\n * Represents a generic DynamoDB query\r\n */\r\nexport type DynamoDBQuery = Partial<GetItemInput> & Partial<ScanInput> & Partial<QueryInput>;\r\n\r\n/**\r\n * Represents a command input that is either a DynamoDB GetItem, DynamoDB Query or a DynamoDB Scan\r\n */\r\nexport type GetOrQueryOrScanInput =\r\n { count: GetItemInput, full: GetItemInput, type: 'get' } |\r\n { count: QueryInput, full: QueryInput, type: 'query' } |\r\n { count: ScanInput, full: ScanInput, type: 'scan' };\r\n\r\nexport interface DynamoDBQueryContext {\r\n /**\r\n * Whether the query should split the primary keys from the filter expressions to the key parameter\r\n */\r\n allowKeySplitting?: boolean;\r\n\r\n /**\r\n * The key parameter\r\n */\r\n key?: CrudRequestWhereField[];\r\n}\r\n\r\n/**\r\n * Adapts queries to DynamoDB query builder object.\r\n *\r\n * Not supported:\r\n * - Ordering by any other field except the sort key\r\n * - Page\r\n * - Offset\r\n * - Relations\r\n *\r\n * The ordering only works for the sort key and in query operations.\r\n * It's ignored in scan operations.\r\n */\r\nexport class DynamoDBQueryAdapter implements QueryAdapter<DynamoDBQuery> {\r\n\r\n protected readonly partitionKey: FieldPath;\r\n protected readonly sortKey?: FieldPath;\r\n\r\n constructor(\r\n protected readonly options: DynamoDBQueryAdapterOptions,\r\n ) {\r\n this.partitionKey = pathParse(options.partitionKey);\r\n this.sortKey = options.sortKey ? pathParse(options.sortKey) : undefined;\r\n }\r\n\r\n /**\r\n * @inheritDoc\r\n */\r\n public build(baseQuery: DynamoDBQuery, request: CrudRequest): DynamoDBQuery {\r\n const { full } = this.buildBaseGetOrQueryOrScan(baseQuery, request);\r\n\r\n return full;\r\n }\r\n\r\n /**\r\n * @inheritDoc\r\n */\r\n public async getMany<E>(baseQuery: DynamoDBQuery, request: CrudRequest): Promise<GetManyResult<E>> {\r\n const input = this.buildBaseGetOrQueryOrScan(baseQuery, request);\r\n\r\n const [data, total] = await this.fetchDataAndCount<E>(input, true);\r\n\r\n const limit = request.limit || baseQuery.Limit;\r\n\r\n return createGetManyResult(data, total || 0, 0, limit);\r\n }\r\n\r\n /**\r\n * @inheritDoc\r\n */\r\n public async getOne<E>(baseQuery: DynamoDBQuery, request: CrudRequest): Promise<E | null> {\r\n const input = this.buildBaseGetOrQueryOrScan(baseQuery, { ...request, limit: 1 });\r\n\r\n const [data] = await this.fetchDataAndCount<E>(input, false);\r\n\r\n if (data.length === 0)\r\n return null;\r\n\r\n return data[0];\r\n }\r\n\r\n /**\r\n * Creates a DynamoDB Query input\r\n *\r\n * @param baseQuery The base query\r\n * @param request The crud request\r\n */\r\n public buildQuery(baseQuery: Partial<QueryInput>, request: CrudRequest): QueryInput {\r\n const query: QueryInput = {\r\n ...baseQuery,\r\n TableName: baseQuery.TableName || this.options.tableName,\r\n };\r\n const ctx: DynamoDBQueryContext = { allowKeySplitting: true };\r\n\r\n this.adaptProjection(query, request.select);\r\n this.adaptFilter(query, ctx, request.where);\r\n this.adaptOrder(query, request.order);\r\n this.adaptLimit(query, request.limit);\r\n\r\n if (ctx.key)\r\n this.adaptQueryKeyExpression(query, ctx.key);\r\n\r\n return query;\r\n }\r\n\r\n /**\r\n * Creates a DynamoDB Scan input\r\n *\r\n * @param baseQuery The base query\r\n * @param request The crud request\r\n */\r\n public buildScan(baseQuery: Partial<ScanInput>, request: CrudRequest): ScanInput {\r\n const scan: ScanInput = {\r\n ...baseQuery,\r\n TableName: baseQuery.TableName || this.options.tableName,\r\n };\r\n const ctx: DynamoDBQueryContext = { allowKeySplitting: false };\r\n\r\n this.adaptProjection(scan, request.select);\r\n this.adaptFilter(scan, ctx, request.where);\r\n this.adaptLimit(scan, request.limit);\r\n\r\n return scan;\r\n }\r\n\r\n /**\r\n * Creates a DynamoDB GetItem input\r\n *\r\n * @param baseQuery The base query\r\n * @param request The crud request\r\n */\r\n public buildGetItem(baseQuery: Partial<GetItemInput>, request: CrudRequest): GetItemInput {\r\n const query: GetItemInput = {\r\n ...baseQuery,\r\n TableName: baseQuery.TableName || this.options.tableName,\r\n Key: baseQuery.Key,\r\n };\r\n const ctx: DynamoDBQueryContext = { allowKeySplitting: true };\r\n\r\n this.adaptProjection(query, request.select);\r\n this.adaptFilter({}, ctx, request.where);\r\n\r\n if (ctx.key)\r\n this.adaptGetItemKey(query, ctx.key);\r\n\r\n return query;\r\n }\r\n\r\n /**\r\n * Creates a DynamoDB GetItem, Query or Scan input, based on whether the partition key and sort key are present in the where conditions\r\n *\r\n * @param baseInput The base query\r\n * @param request The crud request\r\n */\r\n protected buildBaseGetOrQueryOrScan(\r\n baseInput: DynamoDBQuery,\r\n request: CrudRequest,\r\n ): GetOrQueryOrScanInput {\r\n const input: DynamoDBQuery = {\r\n ...baseInput,\r\n TableName: baseInput.TableName || this.options.tableName,\r\n };\r\n const ctx: DynamoDBQueryContext = { allowKeySplitting: true };\r\n\r\n this.adaptFilter(input, ctx, request.where);\r\n\r\n const mapResult = (type: 'get' | 'query' | 'scan'): GetOrQueryOrScanInput => {\r\n const count = {\r\n ...input,\r\n ExpressionAttributeNames: { ...input.ExpressionAttributeNames },\r\n ExpressionAttributeValues: { ...input.ExpressionAttributeValues },\r\n Select: 'COUNT',\r\n };\r\n\r\n this.adaptProjection(input, request.select);\r\n this.adaptOrder(input, request.order);\r\n this.adaptLimit(input, request.limit);\r\n\r\n return { count: count as any, full: input as any, type };\r\n };\r\n\r\n // In case there is an existing GetItem key\r\n if (input.Key)\r\n return mapResult('get');\r\n\r\n // In case there is an existing Query key\r\n if (input.KeyConditionExpression)\r\n return mapResult('query');\r\n\r\n const operation = this.getAvailableCommandByKey(input, ctx.key);\r\n\r\n // GetItem\r\n if (operation === 'get' && ctx.key) {\r\n this.adaptGetItemKey(input, ctx.key);\r\n\r\n return mapResult('get');\r\n }\r\n\r\n // Query\r\n if (operation === 'query' && ctx.key) {\r\n this.adaptQueryKeyExpression(input, ctx.key);\r\n\r\n return mapResult('query');\r\n }\r\n\r\n // In case there are keys, we'll add them back to the filter expression\r\n if (ctx.key)\r\n this.adaptFilterKeyExpression(input, ctx.key);\r\n\r\n // Scan\r\n return mapResult('scan');\r\n }\r\n\r\n /**\r\n * Fetches data through a GetItem, Query or Scan command. Optionally fetches the count too.\r\n *\r\n * @param mixed The GetItem, Query or Scan input\r\n * @param fetchCount Whether it should fetch the total number of items too.\r\n */\r\n protected async fetchDataAndCount<E>(mixed: GetOrQueryOrScanInput, fetchCount: boolean): Promise<[E[], number?]> {\r\n if (mixed.type === 'get') {\r\n const result = await this.options.client.send(new GetItemCommand(mixed.full));\r\n\r\n if (!result.Item)\r\n return [[], 0];\r\n\r\n return [[this.unmarshall<E>(result.Item)], 1];\r\n }\r\n\r\n const shouldFetchCount = fetchCount && !this.options.disableCount;\r\n\r\n if (mixed.type === 'query') {\r\n const [output, count] = await Promise.all([\r\n this.options.client.send(new QueryCommand(mixed.full)),\r\n shouldFetchCount ? this.options.client.send(new QueryCommand(mixed.count)) : undefined,\r\n ]);\r\n\r\n const items = (output.Items || []).map(item => this.unmarshall<E>(item));\r\n\r\n return [items, count?.Count];\r\n }\r\n\r\n if (mixed.type === 'scan' && !this.options.disableScan) {\r\n const [output, count] = await Promise.all([\r\n this.options.client.send(new ScanCommand(mixed.full)),\r\n shouldFetchCount ? this.options.client.send(new ScanCommand(mixed.count)) : undefined,\r\n ]);\r\n\r\n const items = (output.Items || []).map(item => this.unmarshall<E>(item));\r\n\r\n return [items, count?.Count];\r\n }\r\n\r\n throw new Error('The partition key is missing in the query. Scan is disabled');\r\n }\r\n\r\n /**\r\n * Gets the command to run based on the key combination available.\r\n *\r\n * If the complete primary key is available, it results in GetItem.\r\n * If only the partition key is available but not the sort key, it results in Query.\r\n * If no keys are available, it resutls in Scan.\r\n *\r\n * @param input The DynamoDB query\r\n * @param keys The primary keys\r\n */\r\n protected getAvailableCommandByKey(input: DynamoDBQuery, keys: CrudRequestWhereField[] | undefined): 'get' | 'query' | 'scan' {\r\n if (!keys)\r\n return 'scan';\r\n\r\n let hasPartitionKeyEq: boolean = false;\r\n let hasSortKeyEq: boolean = !this.sortKey;\r\n\r\n for (const where of keys) {\r\n const isEq = where.operator === CrudRequestWhereOperator.EQ;\r\n\r\n // Partition Key\r\n if (pathEquals(where.field, this.partitionKey) && isEq)\r\n hasPartitionKeyEq = true;\r\n\r\n // Sort Key\r\n if (this.sortKey && pathEquals(where.field, this.sortKey) && isEq)\r\n hasSortKeyEq = true;\r\n }\r\n\r\n if (hasPartitionKeyEq && hasSortKeyEq && !input.FilterExpression)\r\n return 'get';\r\n\r\n if (hasPartitionKeyEq)\r\n return 'query';\r\n\r\n return 'scan';\r\n }\r\n\r\n /**\r\n * Adapts the key conditions into a key expression\r\n *\r\n * @param query The DynamoDB query\r\n * @param keys The key conditions\r\n */\r\n protected adaptQueryKeyExpression(query: Partial<QueryInput>, keys: CrudRequestWhereField[]): void {\r\n const condition: string[] = [];\r\n\r\n for (const where of keys) {\r\n const result = this.mapWhereOperators(query, where);\r\n\r\n query.ExpressionAttributeValues = {\r\n ...(query.ExpressionAttributeValues || {}),\r\n ...this.marshall(result.params),\r\n };\r\n\r\n condition.push(result.where);\r\n }\r\n\r\n query.KeyConditionExpression = condition.join(' AND ');\r\n }\r\n\r\n /**\r\n * Adapts the key conditions into a filter expression\r\n *\r\n * @param query The DynamoDB query\r\n * @param keys The key conditions\r\n */\r\n protected adaptFilterKeyExpression(query: Partial<ScanInput>, keys: CrudRequestWhereField[]): void {\r\n const condition: string[] = [];\r\n\r\n for (const where of keys) {\r\n const result = this.mapWhereOperators(query, where);\r\n\r\n query.ExpressionAttributeValues = {\r\n ...(query.ExpressionAttributeValues || {}),\r\n ...this.marshall(result.params),\r\n };\r\n\r\n condition.push(result.where);\r\n }\r\n\r\n if (query.FilterExpression)\r\n query.FilterExpression = condition.join(' AND ') + ' AND ' + this.wrapParenthesis(query.FilterExpression);\r\n else\r\n query.FilterExpression = condition.join(' AND ');\r\n }\r\n\r\n /**\r\n * Adapts the key conditions into a key object\r\n *\r\n * @param query The DynamoDB query\r\n * @param keys The key conditions\r\n */\r\n protected adaptGetItemKey(query: Partial<GetItemInput>, keys: CrudRequestWhereField[]): void {\r\n const key: Record<string, unknown> = query.Key ? this.unmarshall(query.Key) : {};\r\n\r\n for (const where of keys) {\r\n if (where.operator !== CrudRequestWhereOperator.EQ)\r\n continue;\r\n\r\n key[where.field.join('.')] = where.value;\r\n }\r\n\r\n query.Key = this.marshall(key);\r\n }\r\n\r\n /**\r\n * Adapts a list of select fields into a projection expression\r\n *\r\n * @param query The DynamoDB query\r\n * @param select The select fields\r\n */\r\n protected adaptProjection(query: DynamoDBQuery, select: ParsedRequestSelect): void {\r\n if (select.length === 0)\r\n return;\r\n\r\n const existing = query.ProjectionExpression?.split(',').map(exp => exp.trim()).filter(exp => !!exp) || [];\r\n const attributes = select.map(f => this.registerAttribute(query, f.field));\r\n\r\n query.ProjectionExpression = [...new Set([...existing, ...attributes])].join(', ');\r\n }\r\n\r\n /**\r\n * Adapts the order field that matches the sort key to a DynamoDB Query\r\n *\r\n * @param query The DynamoDB query\r\n * @param order The order fields\r\n */\r\n protected adaptOrder(query: DynamoDBQuery, order: CrudRequestOrder[]): void {\r\n const sortKey = this.sortKey;\r\n\r\n if (!sortKey)\r\n return;\r\n\r\n const sort = order.find(o => pathEquals(o.field, sortKey));\r\n\r\n if (!sort)\r\n return;\r\n\r\n query.ScanIndexForward = sort.order === 'ASC';\r\n }\r\n\r\n /**\r\n * Adapts a where condition into a DynamoDB filter\r\n *\r\n * @param query The DynamoDB query\r\n * @param ctx The builder context\r\n * @param where The where condition\r\n */\r\n protected adaptFilter(query: DynamoDBQuery, ctx: DynamoDBQueryContext, where: CrudRequestWhere): void {\r\n const filter = this.mapWhere(query, ctx, where, true);\r\n\r\n if (!filter)\r\n return;\r\n\r\n const existingFilter = query.FilterExpression;\r\n\r\n query.FilterExpression = existingFilter ?\r\n `${this.wrapParenthesis(existingFilter)} AND ${this.wrapParenthesis(filter)}` : filter;\r\n }\r\n\r\n /**\r\n * Adapts the limit\r\n *\r\n * @param query The DynamoDB query\r\n * @param limit The limit value\r\n */\r\n protected adaptLimit(query: DynamoDBQuery, limit: number | undefined): void {\r\n if (limit)\r\n query.Limit = limit;\r\n }\r\n\r\n /**\r\n * Maps a where condition into a filter expression\r\n *\r\n * @param query The DynamoDB query\r\n * @param ctx The query builder context\r\n * @param where The where condition\r\n * @param isTopLevelAnd Whether this is the top level AND condition\r\n */\r\n protected mapWhere(\r\n query: DynamoDBQuery,\r\n ctx: DynamoDBQueryContext,\r\n where: CrudRequestWhere,\r\n isTopLevelAnd: boolean = false,\r\n ): string | undefined {\r\n // AND\r\n if (where.and && where.and.length > 0) {\r\n if (where.and.length === 1)\r\n return this.mapWhere(query, ctx, where.and[0], isTopLevelAnd);\r\n\r\n return this.wrapParenthesis(\r\n where.and\r\n .map(item => this.mapWhere(query, ctx, item, isTopLevelAnd))\r\n .filter(query => !!query)\r\n .join(' AND ')\r\n );\r\n }\r\n\r\n // OR\r\n if (where.or && where.or.length > 0) {\r\n if (where.or.length === 1)\r\n return this.mapWhere(query, ctx, where.or[0], isTopLevelAnd);\r\n\r\n return this.wrapParenthesis(\r\n where.or\r\n .map(item => this.mapWhere(query, ctx, item, false))\r\n .filter(query => !!query)\r\n .join(' OR ')\r\n );\r\n }\r\n\r\n // Condition\r\n if (where.field) {\r\n // Checks whether this field is in the top-level AND condition and is a primary key\r\n if (isTopLevelAnd && ctx.allowKeySplitting) {\r\n const isPrimaryKey =\r\n (pathEquals(this.partitionKey, where.field) && where.operator === CrudRequestWhereOperator.EQ)\r\n || (this.sortKey && pathEquals(this.sortKey, where.field));\r\n\r\n if (isPrimaryKey) {\r\n ctx.key = ctx.key || [];\r\n ctx.key.push(where);\r\n\r\n return undefined;\r\n }\r\n }\r\n\r\n const result = this.mapWhereOperators(query, where);\r\n\r\n query.ExpressionAttributeValues = {\r\n ...(query.ExpressionAttributeValues || {}),\r\n ...this.marshall(result.params),\r\n };\r\n\r\n return result.where;\r\n }\r\n }\r\n\r\n /**\r\n * Maps a where condition into an expression and its parameters\r\n *\r\n * @param query The DynamoDB query\r\n * @param where The where condition\r\n */\r\n protected mapWhereOperators(\r\n query: DynamoDBQuery,\r\n where: CrudRequestWhereField,\r\n ): { where: string, params: Record<string, any> } {\r\n const field = this.registerAttribute(query, where.field);\r\n const param = this.createUniqueParam(query, field.replace('#', ':'));\r\n\r\n let value = where.value;\r\n\r\n switch (where.operator) {\r\n case CrudRequestWhereOperator.EQ:\r\n return { where: `${field} = ${param}`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.NEQ:\r\n return { where: `${field} <> ${param}`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.LT:\r\n return { where: `${field} < ${param}`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.LTE:\r\n return { where: `${field} <= ${param}`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.GT:\r\n return { where: `${field} > ${param}`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.GTE:\r\n return { where: `${field} >= ${param}`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.STARTS:\r\n return { where: `begins_with(${field}, ${param})`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.CONTAINS:\r\n return { where: `contains(${field}, ${param})`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.NOT_CONTAINS:\r\n return { where: `NOT contains(${field}, ${param})`, params: { [param]: value } };\r\n\r\n case CrudRequestWhereOperator.BETWEEN:\r\n const arr = ensureArray('BETWEEN operator', value, 2);\r\n\r\n return {\r\n where: `${field} BETWEEN ${param}_start AND ${param}_end`,\r\n params: { [`${param}_start`]: arr[0], [`${param}_end`]: arr[1] },\r\n };\r\n\r\n case CrudRequestWhereOperator.IN:\r\n value = ensureArray('IN operator', value, 1);\r\n\r\n return {\r\n where: `${field} IN (${value.map((_, i) => param + '_' + i).join(', ')})`,\r\n params: value.reduce((prev, val, i) => ({\r\n ...prev,\r\n [param + '_' + i]: val,\r\n }), {}),\r\n };\r\n\r\n case CrudRequestWhereOperator.NOT_IN:\r\n value = ensureArray('NOT IN operator', value, 1);\r\n\r\n return {\r\n where: `NOT (${field} IN (${value.map((_, i) => param + '_' + i).join(', ')}))`,\r\n params: value.reduce((prev, val, i) => ({\r\n ...prev,\r\n [param + '_' + i]: val,\r\n }), {}),\r\n };\r\n\r\n case CrudRequestWhereOperator.IS_NULL:\r\n ensureEmpty('IS NULL operator', value);\r\n\r\n return { where: `(attribute_not_exists(${field}) OR ${field} = :null)`, params: { ':null': null } };\r\n\r\n case CrudRequestWhereOperator.NOT_NULL:\r\n ensureEmpty('NOT NULL operator', value);\r\n\r\n return { where: `(attribute_exists(${field}) AND ${field} <> :null)`, params: { ':null': null } };\r\n }\r\n\r\n throw new Error(`Operator not supported in DynamoDB \"${where.operator}\"`);\r\n }\r\n\r\n /**\r\n * Generates the attribute name and registers an attribute to the query\r\n *\r\n * @param query The DynamoDB query\r\n * @param field The field path\r\n */\r\n protected registerAttribute(query: DynamoDBQuery, field: FieldPath): string {\r\n const fieldName = field.join('.');\r\n const baseName = '#' + fieldName.replace(/[^A-Za-z0-9_]/g, '_');\r\n\r\n let attributeName = baseName;\r\n let interaction = 1;\r\n\r\n const names = query.ExpressionAttributeNames || {};\r\n\r\n // This avoids attribute name conflicts\r\n while (names[attributeName] && names[attributeName] !== fieldName) {\r\n attributeName = baseName + interaction.toString();\r\n interaction++;\r\n }\r\n\r\n names[attributeName] = fieldName;\r\n query.ExpressionAttributeNames = names;\r\n\r\n return attributeName;\r\n }\r\n\r\n /**\r\n * Creates a unique query parameter name based on a field\r\n *\r\n * @param query The DynamoDB query\r\n * @param name The parameter name, which should start with \":\"\r\n */\r\n protected createUniqueParam(query: DynamoDBQuery, name: string): string {\r\n let param = name;\r\n let iteration: number = 1;\r\n\r\n while (query.ExpressionAttributeValues?.[param]) {\r\n param = name + iteration.toString();\r\n iteration++;\r\n }\r\n\r\n return param;\r\n }\r\n\r\n /**\r\n * Wraps an expression with parenthesis\r\n *\r\n * @param expression The filter expression\r\n */\r\n protected wrapParenthesis(expression: string): string {\r\n if (!expression)\r\n return '';\r\n\r\n if (expression.startsWith('(') && expression.endsWith(')'))\r\n return expression;\r\n\r\n return `(${expression})`;\r\n }\r\n\r\n /**\r\n * Converts an object into DynamoDB's attribute key-value structure\r\n *\r\n * @param data The object\r\n */\r\n protected marshall<T>(data: T): Record<string, AttributeValue> {\r\n return marshall(data);\r\n }\r\n\r\n /**\r\n * Converts a DynamoDB's attribute key-value structure into an object\r\n *\r\n * @param data The attribute key-value\r\n */\r\n protected unmarshall<T>(data: Record<string, AttributeValue>): T {\r\n return unmarshall(data) as T;\r\n }\r\n\r\n}\r\n","export function ensurePrimitive(fieldName: string, data: any): number | string | boolean | Date {\r\n if (typeof data === 'number' || typeof data === 'string' || typeof data === 'boolean' || data instanceof Date)\r\n return data;\r\n\r\n throw new Error(`${fieldName} must be a string, number or boolean`);\r\n}\r\n\r\nexport function ensurePrimitiveOrNull(fieldName: string, data: any): number | string | boolean | Date | undefined | null {\r\n if (data === null || data === undefined)\r\n return data;\r\n\r\n if (typeof data === 'number' || typeof data === 'string' || typeof data === 'boolean' || data instanceof Date)\r\n return data;\r\n\r\n throw new Error(`${fieldName} must be a string, number, boolean or null`);\r\n}\r\n\r\nexport function ensureString(fieldName: string, data: any): string {\r\n if (typeof data === 'string')\r\n return data;\r\n\r\n throw new Error(`${fieldName} must be a string`);\r\n}\r\n\r\nexport function ensureArray<T>(fieldName: string, data: T[] | any, minLength: number = 0): T[] {\r\n if (!Array.isArray(data) || data.length < minLength)\r\n throw new Error(`${fieldName} must be an array with at least ${minLength} items`);\r\n\r\n return data;\r\n}\r\n\r\nexport function ensureEmpty(fieldName: string, data: any) {\r\n if (isValid(data) && data !== true)\r\n throw new Error(`${fieldName} must be true, null or undefined`);\r\n}\r\n\r\nexport function isValid<T>(value: T | undefined | null): value is T {\r\n return value !== null && value !== undefined;\r\n}\r\n\r\nexport function getOffset(offset: number | undefined, limit?: number, page?: number): number {\r\n return offset ?? (limit && page ? limit * (page - 1) : 0);\r\n}\r\n\r\nexport interface Type<T> extends Function { new (... args: any[]): T; }\r\n\r\nexport function createInstance<T extends object>(clazzOrInstance: T | Type<T> | undefined): T | undefined {\r\n if (typeof clazzOrInstance === 'function')\r\n return new clazzOrInstance();\r\n\r\n if (typeof clazzOrInstance === 'object')\r\n return clazzOrInstance as T;\r\n\r\n return undefined;\r\n}\r\n\r\nexport function escapeRegex(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n}\r\n","import { isValid } from './functions';\r\n\r\n/**\r\n * Parses a path by splitting it by dots\r\n *\r\n * @param value The full path as a string or the parts already split\r\n */\r\nexport function pathParse(value: string | string[]): string[] {\r\n if (typeof value === 'string')\r\n return value.split('.');\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Checks whether two field paths are equal\r\n *\r\n * E.g. [\"path\", \"to\", \"field\"] is equal to [\"path\", \"to\", \"field\"] but not [\"something\", \"else\"]\r\n */\r\nexport function pathEquals(path1: string[], path2: string[]): boolean {\r\n if (path1.length !== path2.length)\r\n return false;\r\n\r\n return path1.every((p1, i) => path2[i] === p1);\r\n}\r\n\r\n/**\r\n * Checks whether a path starts with another path.\r\n *\r\n * E.g. [\"path\", \"to\", \"field\"] starts with [\"path\"] or [\"path\", \"to\"] but not [\"something\", \"else\"]\r\n */\r\nexport function pathStartsWith(path: string[], start: string[]): boolean {\r\n if (path.length < start.length)\r\n return false;\r\n\r\n return start.every((start, i) => path[i] === start);\r\n}\r\n\r\n/**\r\n * Checks whether the base of a path matches.\r\n *\r\n * E.g. [\"path\", \"to\", \"field\"] has a base of [\"path\", \"to\"] but not [\"path\"]\r\n */\r\nexport function pathHasBase(path: string[], base: string[]): boolean {\r\n if (path.length - 1 !== base.length)\r\n return false;\r\n\r\n return base.every((start, i) => path[i] === start);\r\n}\r\n\r\n/**\r\n * Breaks a path into the base part and the field name part\r\n *\r\n * @param path The full path\r\n */\r\nexport function pathGetBaseAndName(path: string[]): [string[], string] {\r\n if (path.length === 0)\r\n throw new Error('Cannot break an empty path');\r\n\r\n const base = [...path];\r\n const name = base.pop()!;\r\n\r\n return [base, name];\r\n}\r\n\r\n\r\n/**\r\n * Gets the last part of the path: the field name\r\n *\r\n * @param path The full path\r\n */\r\nexport function pathGetFieldName(path: string[]): string {\r\n return path.length > 0 ? path[path.length - 1] : '';\r\n}\r\n\r\n/**\r\n * Sets a value for the given path\r\n *\r\n * @param obj The root object\r\n * @param field The full field path\r\n */\r\nexport function pathGetValue(obj: object, field: string[]): any {\r\n let value: any = obj;\r\n\r\n for (let i = 0; i < field.length; i++) {\r\n const name = field[i];\r\n\r\n if (!isValid(value))\r\n return undefined;\r\n\r\n if (typeof value !== 'object')\r\n throw new Error(`Cannot get ${name} as it is not an object (got ${typeof value})`);\r\n\r\n value = value[name];\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Sets a value for the given path\r\n *\r\n * @param obj The root object\r\n * @param field The full field path\r\n * @param value The value to be set\r\n */\r\nexport function pathSetValue(obj: object, field: string[], value: any): void {\r\n let self: any = obj;\r\n\r\n for (let i = 0; i < field.length; i++) {\r\n const name = field[i];\r\n\r\n if (typeof self !== 'object')\r\n throw new Error(`Cannot set ${name} as it is not an object (got ${typeof self})`);\r\n\r\n const isLast = i === field.length - 1;\r\n\r\n if (isLast)\r\n self[name] = value;\r\n else if (!isValid(self[name]))\r\n self = self[name] = {};\r\n else\r\n self = self[name];\r\n }\r\n}\r\n","import { GetManyResult } from '../models/get-many-result';\r\nimport { CrudRequest } from '../models/crud-request';\r\n\r\n/**\r\n * Creates a CrudRequest object, filling required missing properties with empty values\r\n */\r\nexport function createCrudRequest(crudRequest?: Partial<CrudRequest>): CrudRequest {\r\n return {\r\n select: [],\r\n relations: [],\r\n order: [],\r\n where: { and: [] },\r\n ...crudRequest,\r\n };\r\n}\r\n\r\n/**\r\n * Creates a GetManyResult object\r\n *\r\n * @param data The entity list to be returned\r\n * @param total The total amount of entities in the database\r\n * @param offset The offset used for querying\r\n * @param limit The limit used for querying\r\n */\r\nexport function createGetManyResult<T>(data: T[], total: number, offset: number, limit?: number): GetManyResult<T> {\r\n const count = data.length;\r\n const actualLimit = limit ?? total;\r\n const page = actualLimit > 0 ? Math.floor(offset / actualLimit) + 1 : 1;\r\n const pageCount = actualLimit > 0 ? Math.ceil(total / actualLimit) : 0;\r\n\r\n return {\r\n data,\r\n count,\r\n total,\r\n page,\r\n pageCount,\r\n };\r\n}\r\n"],"mappings":"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","names":["dynamodb_exports","__export","DynamoDBQueryAdapter","__toCommonJS","import_client_dynamodb","import_util_dynamodb","ensureArray","fieldName","data","minLength","__name","ensureEmpty","isValid","value","pathParse","value","__name","pathEquals","path1","path2","p1","i","createGetManyResult","data","total","offset","limit","count","actualLimit","page","pageCount","__name","DynamoDBQueryAdapter","options","pathParse","__name","baseQuery","request","full","input","data","total","limit","createGetManyResult","query","ctx","scan","baseInput","mapResult","type","count","operation","mixed","fetchCount","result","shouldFetchCount","output","item","keys","hasPartitionKeyEq","hasSortKeyEq","where","isEq","pathEquals","condition","key","select","existing","exp","attributes","f","order","sortKey","sort","o","filter","existingFilter","isTopLevelAnd","field","param","value","arr","ensureArray","_","i","prev","val","ensureEmpty","fieldName","baseName","attributeName","interaction","names","name","iteration","expression"]}
|
@@ -0,0 +1,2 @@
|
|
1
|
+
var N=Object.defineProperty;var u=(o,t)=>N(o,"name",{value:t,configurable:!0});import{GetItemCommand as D,QueryCommand as g,ScanCommand as b}from"@aws-sdk/client-dynamodb";import{marshall as w,unmarshall as T}from"@aws-sdk/util-dynamodb";function c(o,t,i=0){if(!Array.isArray(t)||t.length<i)throw new Error(`${o} must be an array with at least ${i} items`);return t}u(c,"ensureArray");function y(o,t){if(f(t)&&t!==!0)throw new Error(`${o} must be true, null or undefined`)}u(y,"ensureEmpty");function f(o){return o!=null}u(f,"isValid");function d(o){return typeof o=="string"?o.split("."):o}u(d,"pathParse");function p(o,t){return o.length!==t.length?!1:o.every((i,e)=>t[e]===i)}u(p,"pathEquals");function h(o,t,i,e){let r=o.length,n=e??t,s=n>0?Math.floor(i/n)+1:1,a=n>0?Math.ceil(t/n):0;return{data:o,count:r,total:t,page:s,pageCount:a}}u(h,"createGetManyResult");var E=class{constructor(t){this.options=t;this.partitionKey=d(t.partitionKey),this.sortKey=t.sortKey?d(t.sortKey):void 0}static{u(this,"DynamoDBQueryAdapter")}partitionKey;sortKey;build(t,i){let{full:e}=this.buildBaseGetOrQueryOrScan(t,i);return e}async getMany(t,i){let e=this.buildBaseGetOrQueryOrScan(t,i),[r,n]=await this.fetchDataAndCount(e,!0),s=i.limit||t.Limit;return h(r,n||0,0,s)}async getOne(t,i){let e=this.buildBaseGetOrQueryOrScan(t,{...i,limit:1}),[r]=await this.fetchDataAndCount(e,!1);return r.length===0?null:r[0]}buildQuery(t,i){let e={...t,TableName:t.TableName||this.options.tableName},r={allowKeySplitting:!0};return this.adaptProjection(e,i.select),this.adaptFilter(e,r,i.where),this.adaptOrder(e,i.order),this.adaptLimit(e,i.limit),r.key&&this.adaptQueryKeyExpression(e,r.key),e}buildScan(t,i){let e={...t,TableName:t.TableName||this.options.tableName},r={allowKeySplitting:!1};return this.adaptProjection(e,i.select),this.adaptFilter(e,r,i.where),this.adaptLimit(e,i.limit),e}buildGetItem(t,i){let e={...t,TableName:t.TableName||this.options.tableName,Key:t.Key},r={allowKeySplitting:!0};return this.adaptProjection(e,i.select),this.adaptFilter({},r,i.where),r.key&&this.adaptGetItemKey(e,r.key),e}buildBaseGetOrQueryOrScan(t,i){let e={...t,TableName:t.TableName||this.options.tableName},r={allowKeySplitting:!0};this.adaptFilter(e,r,i.where);let n=u(a=>{let l={...e,ExpressionAttributeNames:{...e.ExpressionAttributeNames},ExpressionAttributeValues:{...e.ExpressionAttributeValues},Select:"COUNT"};return this.adaptProjection(e,i.select),this.adaptOrder(e,i.order),this.adaptLimit(e,i.limit),{count:l,full:e,type:a}},"mapResult");if(e.Key)return n("get");if(e.KeyConditionExpression)return n("query");let s=this.getAvailableCommandByKey(e,r.key);return s==="get"&&r.key?(this.adaptGetItemKey(e,r.key),n("get")):s==="query"&&r.key?(this.adaptQueryKeyExpression(e,r.key),n("query")):(r.key&&this.adaptFilterKeyExpression(e,r.key),n("scan"))}async fetchDataAndCount(t,i){if(t.type==="get"){let r=await this.options.client.send(new D(t.full));return r.Item?[[this.unmarshall(r.Item)],1]:[[],0]}let e=i&&!this.options.disableCount;if(t.type==="query"){let[r,n]=await Promise.all([this.options.client.send(new g(t.full)),e?this.options.client.send(new g(t.count)):void 0]);return[(r.Items||[]).map(a=>this.unmarshall(a)),n?.Count]}if(t.type==="scan"&&!this.options.disableScan){let[r,n]=await Promise.all([this.options.client.send(new b(t.full)),e?this.options.client.send(new b(t.count)):void 0]);return[(r.Items||[]).map(a=>this.unmarshall(a)),n?.Count]}throw new Error("The partition key is missing in the query. Scan is disabled")}getAvailableCommandByKey(t,i){if(!i)return"scan";let e=!1,r=!this.sortKey;for(let n of i){let s=n.operator==="eq";p(n.field,this.partitionKey)&&s&&(e=!0),this.sortKey&&p(n.field,this.sortKey)&&s&&(r=!0)}return e&&r&&!t.FilterExpression?"get":e?"query":"scan"}adaptQueryKeyExpression(t,i){let e=[];for(let r of i){let n=this.mapWhereOperators(t,r);t.ExpressionAttributeValues={...t.ExpressionAttributeValues||{},...this.marshall(n.params)},e.push(n.where)}t.KeyConditionExpression=e.join(" AND ")}adaptFilterKeyExpression(t,i){let e=[];for(let r of i){let n=this.mapWhereOperators(t,r);t.ExpressionAttributeValues={...t.ExpressionAttributeValues||{},...this.marshall(n.params)},e.push(n.where)}t.FilterExpression?t.FilterExpression=e.join(" AND ")+" AND "+this.wrapParenthesis(t.FilterExpression):t.FilterExpression=e.join(" AND ")}adaptGetItemKey(t,i){let e=t.Key?this.unmarshall(t.Key):{};for(let r of i)r.operator==="eq"&&(e[r.field.join(".")]=r.value);t.Key=this.marshall(e)}adaptProjection(t,i){if(i.length===0)return;let e=t.ProjectionExpression?.split(",").map(n=>n.trim()).filter(n=>!!n)||[],r=i.map(n=>this.registerAttribute(t,n.field));t.ProjectionExpression=[...new Set([...e,...r])].join(", ")}adaptOrder(t,i){let e=this.sortKey;if(!e)return;let r=i.find(n=>p(n.field,e));r&&(t.ScanIndexForward=r.order==="ASC")}adaptFilter(t,i,e){let r=this.mapWhere(t,i,e,!0);if(!r)return;let n=t.FilterExpression;t.FilterExpression=n?`${this.wrapParenthesis(n)} AND ${this.wrapParenthesis(r)}`:r}adaptLimit(t,i){i&&(t.Limit=i)}mapWhere(t,i,e,r=!1){if(e.and&&e.and.length>0)return e.and.length===1?this.mapWhere(t,i,e.and[0],r):this.wrapParenthesis(e.and.map(n=>this.mapWhere(t,i,n,r)).filter(n=>!!n).join(" AND "));if(e.or&&e.or.length>0)return e.or.length===1?this.mapWhere(t,i,e.or[0],r):this.wrapParenthesis(e.or.map(n=>this.mapWhere(t,i,n,!1)).filter(n=>!!n).join(" OR "));if(e.field){if(r&&i.allowKeySplitting&&(p(this.partitionKey,e.field)&&e.operator==="eq"||this.sortKey&&p(this.sortKey,e.field))){i.key=i.key||[],i.key.push(e);return}let n=this.mapWhereOperators(t,e);return t.ExpressionAttributeValues={...t.ExpressionAttributeValues||{},...this.marshall(n.params)},n.where}}mapWhereOperators(t,i){let e=this.registerAttribute(t,i.field),r=this.createUniqueParam(t,e.replace("#",":")),n=i.value;switch(i.operator){case"eq":return{where:`${e} = ${r}`,params:{[r]:n}};case"neq":return{where:`${e} <> ${r}`,params:{[r]:n}};case"lt":return{where:`${e} < ${r}`,params:{[r]:n}};case"lte":return{where:`${e} <= ${r}`,params:{[r]:n}};case"gt":return{where:`${e} > ${r}`,params:{[r]:n}};case"gte":return{where:`${e} >= ${r}`,params:{[r]:n}};case"starts":return{where:`begins_with(${e}, ${r})`,params:{[r]:n}};case"contains":return{where:`contains(${e}, ${r})`,params:{[r]:n}};case"not_contains":return{where:`NOT contains(${e}, ${r})`,params:{[r]:n}};case"between":let s=c("BETWEEN operator",n,2);return{where:`${e} BETWEEN ${r}_start AND ${r}_end`,params:{[`${r}_start`]:s[0],[`${r}_end`]:s[1]}};case"in":return n=c("IN operator",n,1),{where:`${e} IN (${n.map((a,l)=>r+"_"+l).join(", ")})`,params:n.reduce((a,l,m)=>({...a,[r+"_"+m]:l}),{})};case"not_in":return n=c("NOT IN operator",n,1),{where:`NOT (${e} IN (${n.map((a,l)=>r+"_"+l).join(", ")}))`,params:n.reduce((a,l,m)=>({...a,[r+"_"+m]:l}),{})};case"is_null":return y("IS NULL operator",n),{where:`(attribute_not_exists(${e}) OR ${e} = :null)`,params:{":null":null}};case"not_null":return y("NOT NULL operator",n),{where:`(attribute_exists(${e}) AND ${e} <> :null)`,params:{":null":null}}}throw new Error(`Operator not supported in DynamoDB "${i.operator}"`)}registerAttribute(t,i){let e=i.join("."),r="#"+e.replace(/[^A-Za-z0-9_]/g,"_"),n=r,s=1,a=t.ExpressionAttributeNames||{};for(;a[n]&&a[n]!==e;)n=r+s.toString(),s++;return a[n]=e,t.ExpressionAttributeNames=a,n}createUniqueParam(t,i){let e=i,r=1;for(;t.ExpressionAttributeValues?.[e];)e=i+r.toString(),r++;return e}wrapParenthesis(t){return t?t.startsWith("(")&&t.endsWith(")")?t:`(${t})`:""}marshall(t){return w(t)}unmarshall(t){return T(t)}};export{E as DynamoDBQueryAdapter};
|
2
|
+
//# sourceMappingURL=index.mjs.map
|