@eresearchqut/ddb-repository 1.17.0 → 1.17.1
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/dist/index.cjs +25 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +25 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -4
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
let _aws_sdk_client_dynamodb = require("@aws-sdk/client-dynamodb");
|
|
3
3
|
let _aws_sdk_util_dynamodb = require("@aws-sdk/util-dynamodb");
|
|
4
|
-
let lodash = require("lodash");
|
|
5
4
|
|
|
6
5
|
//#region src/DynamoDbRepository.ts
|
|
7
6
|
let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
|
|
@@ -18,7 +17,7 @@ let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
|
|
|
18
17
|
return FilterOperator;
|
|
19
18
|
}({});
|
|
20
19
|
const marshallKey = (key) => (0, _aws_sdk_util_dynamodb.marshall)(key, { removeUndefinedValues: true });
|
|
21
|
-
const expressionAttributeKey = (key) =>
|
|
20
|
+
const expressionAttributeKey = (key) => key.replace(/-/g, "_");
|
|
22
21
|
const mapInKeys = (filterExpression) => Array.isArray(filterExpression.value) ? filterExpression.value.map((_, index) => `:${expressionAttributeKey(filterExpression.attribute)}${index}`) : `:${expressionAttributeKey(filterExpression.attribute)}`;
|
|
23
22
|
const mapFilterExpression = (filterExpression) => {
|
|
24
23
|
switch (filterExpression.operator) {
|
|
@@ -33,7 +32,7 @@ const mapFilterExpressions = (filterExpressions) => filterExpressions.map((filte
|
|
|
33
32
|
const mapFilterExpressionValues = (filterExpression) => Array.isArray(filterExpression.value) ? filterExpression.value.reduce((reduction, value, index) => ({
|
|
34
33
|
...reduction,
|
|
35
34
|
[`:${expressionAttributeKey(filterExpression.attribute)}${index}`]: value
|
|
36
|
-
}),
|
|
35
|
+
}), {}) : { [`:${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.value };
|
|
37
36
|
const paginate = (array, pageSize) => {
|
|
38
37
|
return array.reduce((acc, val, i) => {
|
|
39
38
|
const idx = Math.floor(i / pageSize);
|
|
@@ -86,7 +85,7 @@ var DynamoDbRepository = class {
|
|
|
86
85
|
ExpressionAttributeNames: filteredUpdateEntries.reduce((acc, [key]) => ({
|
|
87
86
|
...acc,
|
|
88
87
|
[`#${expressionAttributeKey(key)}`]: key
|
|
89
|
-
}),
|
|
88
|
+
}), { ...removeAttributeNames }),
|
|
90
89
|
ExpressionAttributeValues: hasUpdates ? (0, _aws_sdk_util_dynamodb.marshall)(filteredUpdateEntries.reduce((acc, [key, value]) => ({
|
|
91
90
|
...acc,
|
|
92
91
|
[`:${expressionAttributeKey(key)}`]: value
|
|
@@ -104,11 +103,11 @@ var DynamoDbRepository = class {
|
|
|
104
103
|
const keyExpressionAttributeNames = Object.keys(keys).reduce((acc, key) => ({
|
|
105
104
|
...acc,
|
|
106
105
|
[`#${expressionAttributeKey(key)}`]: key
|
|
107
|
-
}),
|
|
106
|
+
}), {});
|
|
108
107
|
const keyExpressionAttributeValues = Object.entries(keys).reduce((acc, [key, value]) => ({
|
|
109
108
|
...acc,
|
|
110
109
|
[`:${expressionAttributeKey(key)}`]: value
|
|
111
|
-
}),
|
|
110
|
+
}), {});
|
|
112
111
|
const gsiKeyAttributes = index ? [this.hashKey, ...this.rangKey ? [this.rangKey] : []] : [];
|
|
113
112
|
const ProjectionExpression = index ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(",") : projectedAttributes ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(",") : void 0;
|
|
114
113
|
const projectionAttributeNames = index ? gsiKeyAttributes.reduce((acc, attr) => ({
|
|
@@ -117,17 +116,17 @@ var DynamoDbRepository = class {
|
|
|
117
116
|
}), {}) : projectedAttributes ? projectedAttributes.reduce((reduction, attribute) => ({
|
|
118
117
|
...reduction,
|
|
119
118
|
[`#${expressionAttributeKey(attribute)}`]: attribute
|
|
120
|
-
}),
|
|
119
|
+
}), {}) : {};
|
|
121
120
|
const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;
|
|
122
121
|
const FilterExpression = hasFilterExpressions ? mapFilterExpressions(filterExpressions) : void 0;
|
|
123
122
|
const filterAttributeNames = hasFilterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
124
123
|
...reduction,
|
|
125
124
|
[`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute
|
|
126
|
-
}),
|
|
125
|
+
}), {}) : {};
|
|
127
126
|
const filterAttributeValues = filterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
128
127
|
...reduction,
|
|
129
128
|
...mapFilterExpressionValues(filterExpression)
|
|
130
|
-
}),
|
|
129
|
+
}), {}) : {};
|
|
131
130
|
const Limit = limit;
|
|
132
131
|
const ScanIndexForward = sortOrder === "DESC" ? false : void 0;
|
|
133
132
|
const queryCommandInput = {
|
|
@@ -156,7 +155,7 @@ var DynamoDbRepository = class {
|
|
|
156
155
|
if (index) {
|
|
157
156
|
const collectedKeys = [];
|
|
158
157
|
for await (const page of paginator) {
|
|
159
|
-
if (page.Items) collectedKeys.push(...page.Items.map((item) => (0, _aws_sdk_util_dynamodb.unmarshall)(item)).map((item) => (
|
|
158
|
+
if (page.Items) collectedKeys.push(...page.Items.map((item) => (0, _aws_sdk_util_dynamodb.unmarshall)(item)).map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => key === this.hashKey || key === this.rangKey))));
|
|
160
159
|
if (limit && collectedKeys.length >= limit) break;
|
|
161
160
|
}
|
|
162
161
|
const keysBatch = limit ? collectedKeys.slice(0, limit) : collectedKeys;
|
|
@@ -174,7 +173,7 @@ var DynamoDbRepository = class {
|
|
|
174
173
|
});
|
|
175
174
|
if (projectedAttributes) {
|
|
176
175
|
const projSet = new Set(projectedAttributes);
|
|
177
|
-
return orderedItems.map((item) => (
|
|
176
|
+
return orderedItems.map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => projSet.has(key))));
|
|
178
177
|
}
|
|
179
178
|
return orderedItems;
|
|
180
179
|
}
|
|
@@ -191,11 +190,11 @@ var DynamoDbRepository = class {
|
|
|
191
190
|
const keyExpressionAttributeNames = Object.keys(keys).reduce((acc, key) => ({
|
|
192
191
|
...acc,
|
|
193
192
|
[`#${expressionAttributeKey(key)}`]: key
|
|
194
|
-
}),
|
|
193
|
+
}), {});
|
|
195
194
|
const keyExpressionAttributeValues = Object.entries(keys).reduce((acc, [key, value]) => ({
|
|
196
195
|
...acc,
|
|
197
196
|
[`:${expressionAttributeKey(key)}`]: value
|
|
198
|
-
}),
|
|
197
|
+
}), {});
|
|
199
198
|
const gsiKeyAttributes = index ? [this.hashKey, ...this.rangKey ? [this.rangKey] : []] : [];
|
|
200
199
|
const ProjectionExpression = index ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(",") : projectedAttributes ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(",") : void 0;
|
|
201
200
|
const projectionAttributeNames = index ? gsiKeyAttributes.reduce((acc, attr) => ({
|
|
@@ -204,17 +203,17 @@ var DynamoDbRepository = class {
|
|
|
204
203
|
}), {}) : projectedAttributes ? projectedAttributes.reduce((reduction, attribute) => ({
|
|
205
204
|
...reduction,
|
|
206
205
|
[`#${expressionAttributeKey(attribute)}`]: attribute
|
|
207
|
-
}),
|
|
206
|
+
}), {}) : {};
|
|
208
207
|
const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;
|
|
209
208
|
const FilterExpression = hasFilterExpressions ? mapFilterExpressions(filterExpressions) : void 0;
|
|
210
209
|
const filterAttributeNames = hasFilterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
211
210
|
...reduction,
|
|
212
211
|
[`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute
|
|
213
|
-
}),
|
|
212
|
+
}), {}) : {};
|
|
214
213
|
const filterAttributeValues = filterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
215
214
|
...reduction,
|
|
216
215
|
...mapFilterExpressionValues(filterExpression)
|
|
217
|
-
}),
|
|
216
|
+
}), {}) : {};
|
|
218
217
|
const ExclusiveStartKey = cursor ? JSON.parse(Buffer.from(cursor, "base64").toString("utf-8")) : void 0;
|
|
219
218
|
const queryCommandInput = {
|
|
220
219
|
TableName: this.tableName,
|
|
@@ -239,7 +238,7 @@ var DynamoDbRepository = class {
|
|
|
239
238
|
const result = await this.dynamoDBClient.send(new _aws_sdk_client_dynamodb.QueryCommand(queryCommandInput));
|
|
240
239
|
const nextCursor = result.LastEvaluatedKey ? Buffer.from(JSON.stringify((0, _aws_sdk_util_dynamodb.unmarshall)(result.LastEvaluatedKey))).toString("base64") : void 0;
|
|
241
240
|
if (index) {
|
|
242
|
-
const collectedKeys = (result.Items ?? []).map((item) => (0, _aws_sdk_util_dynamodb.unmarshall)(item)).map((item) => (
|
|
241
|
+
const collectedKeys = (result.Items ?? []).map((item) => (0, _aws_sdk_util_dynamodb.unmarshall)(item)).map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => key === this.hashKey || key === this.rangKey)));
|
|
243
242
|
const keyAttrs = [this.hashKey, ...this.rangKey ? [this.rangKey] : []];
|
|
244
243
|
const batchProjectedQuery = projectedAttributes ? {
|
|
245
244
|
...query,
|
|
@@ -255,7 +254,7 @@ var DynamoDbRepository = class {
|
|
|
255
254
|
if (projectedAttributes) {
|
|
256
255
|
const projSet = new Set(projectedAttributes);
|
|
257
256
|
return {
|
|
258
|
-
items: orderedItems.map((item) => (
|
|
257
|
+
items: orderedItems.map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => projSet.has(key)))),
|
|
259
258
|
cursor: nextCursor
|
|
260
259
|
};
|
|
261
260
|
}
|
|
@@ -312,13 +311,17 @@ var DynamoDbRepository = class {
|
|
|
312
311
|
return limit ? items.slice(0, limit) : items;
|
|
313
312
|
};
|
|
314
313
|
this.batchGetItems = async (keys, projectedQuery) => {
|
|
315
|
-
const
|
|
314
|
+
const dedupeKey = (key) => {
|
|
315
|
+
const record = key;
|
|
316
|
+
return this.rangKey ? `${String(record[this.hashKey])}\0${String(record[this.rangKey])}` : String(record[this.hashKey]);
|
|
317
|
+
};
|
|
318
|
+
const keyPages = paginate(Array.from(new Map(keys.map((k) => [dedupeKey(k), k])).values()), 100);
|
|
316
319
|
const { projectedAttributes } = projectedQuery || {};
|
|
317
320
|
const ProjectionExpression = projectedAttributes ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(",") : void 0;
|
|
318
321
|
const ExpressionAttributeNames = projectedAttributes ? projectedAttributes.reduce((reduction, attribute) => ({
|
|
319
322
|
...reduction,
|
|
320
323
|
[`#${expressionAttributeKey(attribute)}`]: attribute
|
|
321
|
-
}),
|
|
324
|
+
}), {}) : void 0;
|
|
322
325
|
return Promise.all(keyPages.map(async (keyPage) => {
|
|
323
326
|
const batchRequest = {
|
|
324
327
|
RequestItems: { [this.tableName]: {
|
|
@@ -392,10 +395,10 @@ var DynamoDbRepository = class {
|
|
|
392
395
|
//#region src/consumed-capacity-middleware.ts
|
|
393
396
|
const consumedCapacityMiddleware = (consumedCapacityMiddlewareConfig) => (next) => async (args) => {
|
|
394
397
|
const { input } = args;
|
|
395
|
-
const returnConsumedCapacity =
|
|
398
|
+
const returnConsumedCapacity = input["ReturnConsumedCapacity"];
|
|
396
399
|
const response = await next(args);
|
|
397
400
|
const { output } = response;
|
|
398
|
-
const consumedCapacity =
|
|
401
|
+
const consumedCapacity = output["ConsumedCapacity"];
|
|
399
402
|
await consumedCapacityMiddlewareConfig.onConsumedCapacity({
|
|
400
403
|
ReturnConsumedCapacity: returnConsumedCapacity,
|
|
401
404
|
ConsumedCapacity: consumedCapacity
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["GetItemCommand","PutItemCommand","DeleteItemCommand","ReturnValue","UpdateItemCommand","QueryCommand","isEqual","BatchGetItemCommand","BatchWriteItemCommand","TransactGetItemsCommand","TransactWriteItemsCommand","ReturnConsumedCapacity"],"sources":["../src/DynamoDbRepository.ts","../src/consumed-capacity-middleware.ts","../src/JsonPointerRepository.ts"],"sourcesContent":["import {\n BatchGetItemCommand,\n BatchGetItemCommandInput,\n BatchWriteItemCommand,\n DeleteItemCommand,\n DynamoDBClient,\n GetItemCommand,\n paginateQuery,\n paginateScan,\n PutItemCommand,\n QueryCommand,\n QueryCommandInput,\n ReturnConsumedCapacity,\n ReturnValue,\n TransactGetItemsCommand,\n TransactWriteItemsCommand,\n UpdateItemCommand,\n WriteRequest,\n} from \"@aws-sdk/client-dynamodb\";\nimport {marshall, unmarshall, NativeAttributeValue} from \"@aws-sdk/util-dynamodb\";\nimport {replace, uniqWith, isEqual, pickBy} from \"lodash\";\n\nexport enum FilterOperator {\n EQUALS = \"=\",\n NOT_EQUALS = \"<>\",\n GREATER_THAN_OR_EQUALS = \">=\",\n GREATER_THAN = \">\",\n LESS_THAN = \"<\",\n LESS_THAN_OR_EQUALS = \"<=\",\n IN = \"IN\",\n BETWEEN = \"BETWEEN\",\n BEGINS_WITH = \"BEGINS_WITH\",\n CONTAINS = \"CONTAINS\",\n}\n\nexport interface FilterExpression {\n attribute: string;\n value:\n | string\n | number\n | boolean\n | Array<string | number>\n | [string, string]\n | [number, number];\n operator: FilterOperator;\n negate?: boolean;\n}\n\nexport interface FilterableQuery {\n filterExpressions: Array<FilterExpression>;\n}\n\nexport interface ProjectedQuery {\n projectedAttributes: string[];\n}\n\nexport interface IndexedQuery {\n index: string;\n}\n\nexport interface Query extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n [key: string]: unknown;\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n sortOrder?: \"ASC\" | \"DESC\";\n limit?: number\n}\n\nexport interface ScanQuery extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n limit?: number;\n}\n\nconst marshallKey = (key: unknown) =>\n marshall(key as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n\nconst expressionAttributeKey = (key: string) => replace(key, /-/g, \"_\");\n\nconst mapInKeys = (filterExpression: FilterExpression) =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.map(\n (_, index) => `:${expressionAttributeKey(filterExpression.attribute)}${index}`,\n )\n : `:${expressionAttributeKey(filterExpression.attribute)}`;\n\nconst mapFilterExpression = (filterExpression: FilterExpression) => {\n switch (filterExpression.operator) {\n case FilterOperator.IN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `(${mapInKeys(filterExpression)})`\n );\n case FilterOperator.BETWEEN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}0 AND :${expressionAttributeKey(filterExpression.attribute)}1`\n );\n case FilterOperator.BEGINS_WITH:\n case FilterOperator.CONTAINS:\n return (\n `${filterExpression.operator.toLowerCase()}(#${expressionAttributeKey(filterExpression.attribute)}, ` +\n `:${expressionAttributeKey(filterExpression.attribute)})`\n );\n default:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}`\n );\n }\n};\n\nconst mapFilterExpressions = (\n filterExpressions: Array<FilterExpression>,\n) =>\n filterExpressions\n .map((filterExpression) =>\n filterExpression.negate\n ? `NOT ${mapFilterExpression(filterExpression)}`\n : mapFilterExpression(filterExpression),\n )\n .join(\" AND \");\n\nconst mapFilterExpressionValues = (\n filterExpression: FilterExpression,\n): Record<string, string | number | boolean> =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.reduce(\n (reduction, value, index) => ({\n ...reduction,\n [`:${expressionAttributeKey(filterExpression.attribute)}${index}`]: value,\n }),\n Object.assign({}),\n )\n : {\n [`:${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.value,\n };\n\nconst paginate = <T>(array: Array<T>, pageSize: number) => {\n return array.reduce((acc, val, i) => {\n const idx = Math.floor(i / pageSize)\n const page = acc[idx] || (acc[idx] = [])\n page.push(val)\n return acc\n }, [] as Array<Array<T>>);\n}\n\nexport interface DynamoDbRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n hashKey: string;\n rangeKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\nexport interface PageResult<T> {\n items: Array<T>;\n cursor?: string;\n}\n\nexport class DynamoDbRepository<K, T> {\n private readonly dynamoDBClient: DynamoDBClient;\n private readonly tableName: string;\n private readonly hashKey: string;\n private readonly rangKey?: string;\n private readonly returnConsumedCapacity: ReturnConsumedCapacity | undefined;\n\n constructor(options: DynamoDbRepositoryOptions) {\n this.dynamoDBClient = options.client;\n this.tableName = options.tableName;\n this.hashKey = options.hashKey;\n this.rangKey = options.rangeKey;\n this.returnConsumedCapacity = options.returnConsumedCapacity ?? ReturnConsumedCapacity.TOTAL;\n }\n\n getItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient\n .send(\n new GetItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n )\n .then((result) =>\n result.Item ? unmarshall(result.Item) as T : undefined,\n )\n };\n\n putItem = async (key: K, record: T): Promise<T> => {\n const Item = marshall({...record, ...key} as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n return this.dynamoDBClient\n .send(\n new PutItemCommand({\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n Item,\n }),\n )\n .then(() => unmarshall(Item) as T);\n };\n\n deleteItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient.send(new DeleteItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnValues: ReturnValue.ALL_OLD,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })).then((result) => result.Attributes ?\n unmarshall(result.Attributes) as T : undefined);\n };\n\n\n updateItem = async (\n key: K,\n updates: Partial<T>,\n remove?: string[],\n ): Promise<T | undefined> => {\n const filteredUpdateEntries = Object.entries(updates).filter(([, value]) => value !== undefined);\n const hasUpdates = filteredUpdateEntries.length > 0;\n if (!hasUpdates && !remove?.length) {\n return this.getItem(key);\n }\n const setAttributesExpression = hasUpdates ? `SET ${filteredUpdateEntries\n .map(\n ([key]) =>\n `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`,\n )\n .join(\", \")}` : '';\n const removeAttributesExpression = remove?.length\n ? ` REMOVE ${remove.map((key) => `#${expressionAttributeKey(key)}`).join(\", \")}`\n : \"\";\n const removeAttributeNames = remove?.length\n ? remove.reduce(\n (acc, key) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n {} as Record<string, string>,\n )\n : {};\n const updateItemCommandInput = {\n TableName: this.tableName,\n Key: marshallKey(key),\n UpdateExpression: `${setAttributesExpression}${removeAttributesExpression}`,\n ExpressionAttributeNames: filteredUpdateEntries\n .reduce(\n (acc, [key]) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n Object.assign(\n removeAttributeNames,\n ),\n ) as Record<string, string>,\n ExpressionAttributeValues: hasUpdates ? marshall(\n filteredUpdateEntries.reduce(\n (acc, [key, value]) => ({\n ...acc,\n [`:${expressionAttributeKey(key)}`]: value,\n }),\n {} as Record<string, NativeAttributeValue>,\n ),\n {removeUndefinedValues: true},\n ) : undefined,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n };\n return this.dynamoDBClient\n .send(new UpdateItemCommand({...updateItemCommandInput, ReturnValues: 'ALL_NEW'}))\n .then((result) => result.Attributes ? unmarshall(result.Attributes) as T : undefined);\n };\n\n\n getItems = async (\n query: Query\n ): Promise<Array<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder,...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), Object.assign({}));\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), Object.assign({}));\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n Object.assign({}),\n ) : {})\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (\n reduction: Record<string, string>,\n filterExpression: FilterExpression,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.attribute,\n }),\n Object.assign({}),\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n Object.assign({}),\n )\n : {};\n\n const Limit = limit;\n const ScanIndexForward = sortOrder === \"DESC\" ? false : undefined;\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit,\n ScanIndexForward\n };\n const paginator = paginateQuery(\n {client: this.dynamoDBClient, pageSize: 100},\n queryCommandInput,\n );\n\n if (index) {\n const collectedKeys: Array<K> = [];\n for await (const page of paginator) {\n if (page.Items) {\n collectedKeys.push(\n ...(page.Items.map((item) => unmarshall(item) as T)\n .map((item: T) =>\n pickBy(item as object, (_, key) => (key === this.hashKey || key === this.rangKey)) as K)),\n )\n }\n if (limit && collectedKeys.length >= limit) break;\n }\n const keysBatch = limit ? collectedKeys.slice(0, limit) : collectedKeys;\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(keysBatch, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = keysBatch.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return orderedItems.map(item =>\n pickBy(item as object, (_, key) => projSet.has(key)) as T\n ) as Array<T>;\n }\n return orderedItems as Array<T>;\n }\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n getItemsPage = async (\n query: Query & { cursor?: string }\n ): Promise<PageResult<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder, cursor, ...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), Object.assign({}));\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), Object.assign({}));\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (reduction: Record<string, string>, attribute: string) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n Object.assign({}),\n ) : {});\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (reduction: Record<string, string>, filterExpression: FilterExpression) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute,\n }),\n Object.assign({}),\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n Object.assign({}),\n )\n : {};\n\n const ExclusiveStartKey = cursor\n ? JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8')) as Record<string, unknown>\n : undefined;\n\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit: limit,\n ScanIndexForward: sortOrder === \"DESC\" ? false : undefined,\n ExclusiveStartKey: ExclusiveStartKey\n ? marshall(ExclusiveStartKey as Record<string, NativeAttributeValue>, {removeUndefinedValues: true})\n : undefined,\n };\n\n const result = await this.dynamoDBClient.send(new QueryCommand(queryCommandInput));\n const nextCursor = result.LastEvaluatedKey\n ? Buffer.from(JSON.stringify(unmarshall(result.LastEvaluatedKey))).toString('base64')\n : undefined;\n\n if (index) {\n const collectedKeys = (result.Items ?? [])\n .map((item) => unmarshall(item) as T)\n .map((item: T) =>\n pickBy(item as object, (_, key) => (key === this.hashKey || key === this.rangKey)) as K\n );\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(collectedKeys, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = collectedKeys.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return {\n items: orderedItems.map(item => pickBy(item as object, (_, key) => projSet.has(key)) as T),\n cursor: nextCursor,\n };\n }\n return {items: orderedItems, cursor: nextCursor};\n }\n\n const items = (result.Items ?? []).map((item) => unmarshall(item) as T);\n return {items, cursor: nextCursor};\n };\n\n\n scan = async (options?: ScanQuery): Promise<Array<T>> => {\n const { filterExpressions, projectedAttributes, limit, index } = options ?? {};\n\n const ProjectionExpression = projectedAttributes?.length\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const projectionAttributeNames: Record<string, string> = projectedAttributes?.length\n ? projectedAttributes.reduce(\n (acc: Record<string, string>, attribute: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n {},\n )\n : {};\n\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc: Record<string, string>, fe: FilterExpression) => ({\n ...acc,\n [`#${expressionAttributeKey(fe.attribute)}`]: fe.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc, fe) => ({ ...acc, ...mapFilterExpressionValues(fe) }),\n {} as Record<string, unknown>,\n )\n : {};\n\n const allAttributeNames = { ...filterAttributeNames, ...projectionAttributeNames };\n const ExpressionAttributeNames = Object.keys(allAttributeNames).length > 0 ? allAttributeNames : undefined;\n const ExpressionAttributeValues = hasFilterExpressions\n ? marshall(filterAttributeValues as Record<string, NativeAttributeValue>, { removeUndefinedValues: true })\n : undefined;\n\n const paginator = paginateScan(\n { client: this.dynamoDBClient, pageSize: 100 },\n {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames,\n ExpressionAttributeValues,\n },\n );\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n batchGetItems = async (\n keys: K[], projectedQuery?: ProjectedQuery\n ): Promise<Array<T>> => {\n const uniqueKeys = uniqWith(keys, isEqual);\n const keyPages = paginate(uniqueKeys, 100);\n const {projectedAttributes} = projectedQuery || {};\n const ProjectionExpression = projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const ExpressionAttributeNames = projectedAttributes ?\n projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n Object.assign({}),\n ) : undefined;\n return Promise.all((keyPages.map(async (keyPage) => {\n const batchRequest: BatchGetItemCommandInput = {\n RequestItems: {\n [this.tableName]: {\n Keys: keyPage.map((key) => marshallKey(key)),\n ProjectionExpression,\n ExpressionAttributeNames,\n }\n },\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }\n\n const fetchPage = async (request: BatchGetItemCommandInput): Promise<T[]> => {\n const result = await this.dynamoDBClient.send(new BatchGetItemCommand(request));\n const retrieved = result.Responses?.[this.tableName]?.map((item) => unmarshall(item) as T) ?? [];\n const unprocessed = result.UnprocessedKeys;\n if (!unprocessed || Object.keys(unprocessed).length === 0) return retrieved;\n return [...retrieved, ...await fetchPage({\n RequestItems: unprocessed,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })];\n };\n\n return fetchPage(batchRequest);\n })))\n .then((itemSets) => itemSets.flat());\n };\n\n batchWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const requests: WriteRequest[] = [\n ...puts.map(({ key, item }) => ({\n PutRequest: {\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n DeleteRequest: { Key: marshallKey(key) },\n })),\n ];\n\n const sendBatch = async (requestItems: Record<string, WriteRequest[]>): Promise<void> => {\n const result = await this.dynamoDBClient.send(\n new BatchWriteItemCommand({\n RequestItems: requestItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n const unprocessed = result.UnprocessedItems;\n if (unprocessed && Object.keys(unprocessed).length > 0) {\n await sendBatch(unprocessed as Record<string, WriteRequest[]>);\n }\n };\n\n await Promise.all(\n paginate(requests, 25).map(batch => sendBatch({ [this.tableName]: batch })),\n );\n };\n\n transactGetItems = async (keys: K[]): Promise<Array<T | undefined>> => {\n const result = await this.dynamoDBClient.send(\n new TransactGetItemsCommand({\n TransactItems: keys.map((key) => ({\n Get: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n return (result.Responses ?? []).map((response) =>\n response.Item ? unmarshall(response.Item) as T : undefined,\n );\n };\n\n transactWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const transactItems = [\n ...puts.map(({ key, item }) => ({\n Put: {\n TableName: this.tableName,\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n Delete: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ];\n await this.dynamoDBClient.send(\n new TransactWriteItemsCommand({\n TransactItems: transactItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n };\n}\n\n","import {\n ConsumedCapacity,\n ReturnConsumedCapacity,\n ServiceInputTypes,\n ServiceOutputTypes,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport {\n InitializeHandler,\n InitializeHandlerArguments,\n InitializeHandlerOutput,\n} from \"@smithy/types\";\n\nimport {get} from \"lodash\";\n\nexport interface ConsumedCapacityDetail {\n ReturnConsumedCapacity: ReturnConsumedCapacity | undefined\n ConsumedCapacity: ConsumedCapacity | ConsumedCapacity[] | undefined\n}\n\nexport interface ConsumedCapacityMiddlewareConfig {\n onConsumedCapacity: (consumedCapacity: ConsumedCapacityDetail) => Promise<unknown>;\n}\n\nexport const consumedCapacityMiddleware =\n (consumedCapacityMiddlewareConfig: ConsumedCapacityMiddlewareConfig) =>\n (next: InitializeHandler<ServiceInputTypes, ServiceOutputTypes>) =>\n async (args: InitializeHandlerArguments<ServiceInputTypes>): Promise<InitializeHandlerOutput<ServiceOutputTypes>> => {\n const {input} = args;\n const returnConsumedCapacity = get(input, \"ReturnConsumedCapacity\") as ReturnConsumedCapacity | undefined;\n const response = await next(args);\n const {output} = response;\n const consumedCapacity = get(output, \"ConsumedCapacity\") as ConsumedCapacity | ConsumedCapacity[] | undefined;\n await consumedCapacityMiddlewareConfig.onConsumedCapacity({ReturnConsumedCapacity: returnConsumedCapacity, ConsumedCapacity: consumedCapacity});\n return response;\n };","import { DynamoDBClient, ReturnConsumedCapacity } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDbRepository } from \"./DynamoDbRepository\";\n\nexport type JsonPointerValue = string | number | boolean | null;\n\nexport interface JsonPointerRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n idKey?: string;\n pointerKey?: string;\n valueKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\ntype PointerKey = Record<string, string>;\ntype PointerItem = Record<string, unknown>;\n\nconst isJsonPointerValue = (value: unknown): value is JsonPointerValue =>\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\";\n\nconst escapeToken = (token: string): string =>\n token.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n\nconst unescapeToken = (token: string): string =>\n token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\nconst validatePointer = (pointer: string): void => {\n if (!pointer.startsWith(\"/\")) {\n throw new TypeError(`Invalid JSON Pointer \"${pointer}\": must start with \"/\".`);\n }\n};\n\nconst flattenDocument = (doc: unknown, prefix = \"\"): Record<string, JsonPointerValue> => {\n if (doc === null) return { [prefix]: null };\n if (typeof doc !== \"object\") {\n if (isJsonPointerValue(doc)) {\n return { [prefix]: doc };\n }\n const pointer = prefix === \"\" ? \"/\" : prefix;\n throw new TypeError(\n `Unsupported value at JSON pointer \"${pointer}\": expected string, number, boolean, or null but received ${typeof doc}.`,\n );\n }\n\n const result: Record<string, JsonPointerValue> = {};\n\n if (Array.isArray(doc)) {\n for (let i = 0; i < doc.length; i++) {\n Object.assign(result, flattenDocument(doc[i], `${prefix}/${i}`));\n }\n } else {\n for (const [key, value] of Object.entries(doc)) {\n Object.assign(result, flattenDocument(value, `${prefix}/${escapeToken(key)}`));\n }\n }\n\n return result;\n};\n\nconst setAtPointer = (\n root: Record<string, unknown>,\n pointer: string,\n value: JsonPointerValue,\n): void => {\n const tokens = pointer.split(\"/\").slice(1).map(unescapeToken);\n if (tokens.length === 0) return;\n\n let current: Record<string, unknown> = root;\n for (let i = 0; i < tokens.length - 1; i++) {\n const token = tokens[i];\n const nextToken = tokens[i + 1];\n if (current[token] == null) {\n current[token] = /^\\d+$/.test(nextToken) ? [] : {};\n } else if (typeof current[token] !== \"object\") {\n throw new TypeError(\n `Conflicting pointers: cannot traverse \"${pointer}\" because \"/${tokens.slice(0, i + 1).join(\"/\")}\" already holds a primitive value.`,\n );\n }\n current = current[token] as Record<string, unknown>;\n }\n\n const lastToken = tokens[tokens.length - 1];\n current[lastToken] = value;\n};\n\nconst reconstructDocument = <T>(\n items: Array<{ pointer: string; value: JsonPointerValue }>,\n): T => {\n const root: Record<string, unknown> = {};\n const sorted = [...items].sort((a, b) => a.pointer.localeCompare(b.pointer));\n for (const item of sorted) {\n setAtPointer(root, item.pointer, item.value);\n }\n return root as T;\n};\n\n/**\n * Stores JSON documents as individual per-pointer DynamoDB items addressed by JSON Pointer (RFC 6901).\n *\n * Only JSON objects are supported as the root document (`T extends Record<string, unknown>`).\n * Root arrays and primitives are not supported. Documents must contain at least one leaf value;\n * empty objects and empty arrays are not supported.\n */\nexport class JsonPointerRepository<T extends Record<string, unknown>> {\n private readonly repository: DynamoDbRepository<PointerKey, PointerItem>;\n private readonly idKey: string;\n private readonly pointerKey: string;\n private readonly valueKey: string;\n\n constructor(options: JsonPointerRepositoryOptions) {\n const {\n client,\n tableName,\n idKey = \"id\",\n pointerKey = \"pointer\",\n valueKey = \"value\",\n returnConsumedCapacity,\n } = options;\n\n this.idKey = idKey;\n this.pointerKey = pointerKey;\n this.valueKey = valueKey;\n\n this.repository = new DynamoDbRepository<PointerKey, PointerItem>({\n client,\n tableName,\n hashKey: idKey,\n rangeKey: pointerKey,\n returnConsumedCapacity,\n });\n }\n\n putDocument = async (id: string, document: T): Promise<void> => {\n const flat = flattenDocument(document);\n const newPointers = Object.keys(flat);\n\n if (newPointers.length === 0) {\n throw new TypeError(\n \"Cannot store a document with no leaf values. Empty objects and arrays are not supported.\",\n );\n }\n\n const newPointerSet = new Set(newPointers);\n const existing = await this.repository.getItems({ [this.idKey]: id });\n const existingPointers = existing.map(item => item[this.pointerKey] as string);\n const stalePointers = existingPointers.filter(p => !newPointerSet.has(p));\n\n const puts = Object.entries(flat).map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = stalePointers.map(\n pointer => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey),\n );\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n\n getDocument = async (id: string): Promise<T | undefined> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (!items || items.length === 0) return undefined;\n\n return reconstructDocument<T>(\n items.map(item => ({\n pointer: item[this.pointerKey] as string,\n value: item[this.valueKey] as JsonPointerValue,\n })),\n );\n };\n\n getAttribute = async <V = JsonPointerValue>(\n id: string,\n pointer: string,\n ): Promise<V | undefined> => {\n validatePointer(pointer);\n const item = await this.repository.getItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n return item ? (item[this.valueKey] as V) : undefined;\n };\n\n putAttribute = async (\n id: string,\n pointer: string,\n value: JsonPointerValue,\n ): Promise<void> => {\n validatePointer(pointer);\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n await this.repository.putItem(key, { ...key, [this.valueKey]: value } as PointerItem);\n };\n\n deleteAttribute = async (id: string, pointer: string): Promise<void> => {\n validatePointer(pointer);\n await this.repository.deleteItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n };\n\n deleteDocument = async (id: string): Promise<void> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (items.length === 0) return;\n const deleteKeys = items.map(\n item => ({ [this.idKey]: id, [this.pointerKey]: item[this.pointerKey] as string } as PointerKey),\n );\n await this.repository.batchWriteItems([], deleteKeys);\n };\n\n listDocumentIds = async (): Promise<string[]> => {\n const items = await this.repository.scan({ projectedAttributes: [this.idKey] });\n const seen = new Set<string>();\n for (const item of items) {\n seen.add(item[this.idKey] as string);\n }\n return [...seen];\n };\n\n patchDocument = async (\n id: string,\n updates: Record<string, JsonPointerValue | undefined>,\n ): Promise<void> => {\n const entries = Object.entries(updates);\n if (entries.length === 0) return;\n entries.forEach(([pointer]) => validatePointer(pointer));\n const puts = entries\n .filter((entry): entry is [string, JsonPointerValue] => entry[1] !== undefined)\n .map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = entries\n .filter(([, value]) => value === undefined)\n .map(([pointer]) => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey));\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["GetItemCommand","PutItemCommand","DeleteItemCommand","ReturnValue","UpdateItemCommand","QueryCommand","BatchGetItemCommand","BatchWriteItemCommand","TransactGetItemsCommand","TransactWriteItemsCommand","ReturnConsumedCapacity"],"sources":["../src/DynamoDbRepository.ts","../src/consumed-capacity-middleware.ts","../src/JsonPointerRepository.ts"],"sourcesContent":["import {\n BatchGetItemCommand,\n BatchGetItemCommandInput,\n BatchWriteItemCommand,\n DeleteItemCommand,\n DynamoDBClient,\n GetItemCommand,\n paginateQuery,\n paginateScan,\n PutItemCommand,\n QueryCommand,\n QueryCommandInput,\n ReturnConsumedCapacity,\n ReturnValue,\n TransactGetItemsCommand,\n TransactWriteItemsCommand,\n UpdateItemCommand,\n WriteRequest,\n} from \"@aws-sdk/client-dynamodb\";\nimport {marshall, unmarshall, NativeAttributeValue} from \"@aws-sdk/util-dynamodb\";\n\nexport enum FilterOperator {\n EQUALS = \"=\",\n NOT_EQUALS = \"<>\",\n GREATER_THAN_OR_EQUALS = \">=\",\n GREATER_THAN = \">\",\n LESS_THAN = \"<\",\n LESS_THAN_OR_EQUALS = \"<=\",\n IN = \"IN\",\n BETWEEN = \"BETWEEN\",\n BEGINS_WITH = \"BEGINS_WITH\",\n CONTAINS = \"CONTAINS\",\n}\n\nexport interface FilterExpression {\n attribute: string;\n value:\n | string\n | number\n | boolean\n | Array<string | number>\n | [string, string]\n | [number, number];\n operator: FilterOperator;\n negate?: boolean;\n}\n\nexport interface FilterableQuery {\n filterExpressions: Array<FilterExpression>;\n}\n\nexport interface ProjectedQuery {\n projectedAttributes: string[];\n}\n\nexport interface IndexedQuery {\n index: string;\n}\n\nexport interface Query extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n [key: string]: unknown;\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n sortOrder?: \"ASC\" | \"DESC\";\n limit?: number\n}\n\nexport interface ScanQuery extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n limit?: number;\n}\n\nconst marshallKey = (key: unknown) =>\n marshall(key as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n\nconst expressionAttributeKey = (key: string) => key.replace(/-/g, \"_\");\n\nconst mapInKeys = (filterExpression: FilterExpression) =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.map(\n (_, index) => `:${expressionAttributeKey(filterExpression.attribute)}${index}`,\n )\n : `:${expressionAttributeKey(filterExpression.attribute)}`;\n\nconst mapFilterExpression = (filterExpression: FilterExpression) => {\n switch (filterExpression.operator) {\n case FilterOperator.IN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `(${mapInKeys(filterExpression)})`\n );\n case FilterOperator.BETWEEN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}0 AND :${expressionAttributeKey(filterExpression.attribute)}1`\n );\n case FilterOperator.BEGINS_WITH:\n case FilterOperator.CONTAINS:\n return (\n `${filterExpression.operator.toLowerCase()}(#${expressionAttributeKey(filterExpression.attribute)}, ` +\n `:${expressionAttributeKey(filterExpression.attribute)})`\n );\n default:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}`\n );\n }\n};\n\nconst mapFilterExpressions = (\n filterExpressions: Array<FilterExpression>,\n) =>\n filterExpressions\n .map((filterExpression) =>\n filterExpression.negate\n ? `NOT ${mapFilterExpression(filterExpression)}`\n : mapFilterExpression(filterExpression),\n )\n .join(\" AND \");\n\nconst mapFilterExpressionValues = (\n filterExpression: FilterExpression,\n): Record<string, string | number | boolean> =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.reduce(\n (reduction, value, index) => ({\n ...reduction,\n [`:${expressionAttributeKey(filterExpression.attribute)}${index}`]: value,\n }),\n {},\n )\n : {\n [`:${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.value,\n };\n\nconst paginate = <T>(array: Array<T>, pageSize: number) => {\n return array.reduce((acc, val, i) => {\n const idx = Math.floor(i / pageSize)\n const page = acc[idx] || (acc[idx] = [])\n page.push(val)\n return acc\n }, [] as Array<Array<T>>);\n}\n\nexport interface DynamoDbRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n hashKey: string;\n rangeKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\nexport interface PageResult<T> {\n items: Array<T>;\n cursor?: string;\n}\n\nexport class DynamoDbRepository<K, T> {\n private readonly dynamoDBClient: DynamoDBClient;\n private readonly tableName: string;\n private readonly hashKey: string;\n private readonly rangKey?: string;\n private readonly returnConsumedCapacity: ReturnConsumedCapacity | undefined;\n\n constructor(options: DynamoDbRepositoryOptions) {\n this.dynamoDBClient = options.client;\n this.tableName = options.tableName;\n this.hashKey = options.hashKey;\n this.rangKey = options.rangeKey;\n this.returnConsumedCapacity = options.returnConsumedCapacity ?? ReturnConsumedCapacity.TOTAL;\n }\n\n getItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient\n .send(\n new GetItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n )\n .then((result) =>\n result.Item ? unmarshall(result.Item) as T : undefined,\n )\n };\n\n putItem = async (key: K, record: T): Promise<T> => {\n const Item = marshall({...record, ...key} as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n return this.dynamoDBClient\n .send(\n new PutItemCommand({\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n Item,\n }),\n )\n .then(() => unmarshall(Item) as T);\n };\n\n deleteItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient.send(new DeleteItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnValues: ReturnValue.ALL_OLD,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })).then((result) => result.Attributes ?\n unmarshall(result.Attributes) as T : undefined);\n };\n\n\n updateItem = async (\n key: K,\n updates: Partial<T>,\n remove?: string[],\n ): Promise<T | undefined> => {\n const filteredUpdateEntries = Object.entries(updates).filter(([, value]) => value !== undefined);\n const hasUpdates = filteredUpdateEntries.length > 0;\n if (!hasUpdates && !remove?.length) {\n return this.getItem(key);\n }\n const setAttributesExpression = hasUpdates ? `SET ${filteredUpdateEntries\n .map(\n ([key]) =>\n `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`,\n )\n .join(\", \")}` : '';\n const removeAttributesExpression = remove?.length\n ? ` REMOVE ${remove.map((key) => `#${expressionAttributeKey(key)}`).join(\", \")}`\n : \"\";\n const removeAttributeNames = remove?.length\n ? remove.reduce(\n (acc, key) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n {} as Record<string, string>,\n )\n : {};\n const updateItemCommandInput = {\n TableName: this.tableName,\n Key: marshallKey(key),\n UpdateExpression: `${setAttributesExpression}${removeAttributesExpression}`,\n ExpressionAttributeNames: filteredUpdateEntries\n .reduce(\n (acc, [key]) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n {...removeAttributeNames},\n ) as Record<string, string>,\n ExpressionAttributeValues: hasUpdates ? marshall(\n filteredUpdateEntries.reduce(\n (acc, [key, value]) => ({\n ...acc,\n [`:${expressionAttributeKey(key)}`]: value,\n }),\n {} as Record<string, NativeAttributeValue>,\n ),\n {removeUndefinedValues: true},\n ) : undefined,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n };\n return this.dynamoDBClient\n .send(new UpdateItemCommand({...updateItemCommandInput, ReturnValues: 'ALL_NEW'}))\n .then((result) => result.Attributes ? unmarshall(result.Attributes) as T : undefined);\n };\n\n\n getItems = async (\n query: Query\n ): Promise<Array<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder,...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), {});\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), {});\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n {},\n ) : {})\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (\n reduction: Record<string, string>,\n filterExpression: FilterExpression,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n {},\n )\n : {};\n\n const Limit = limit;\n const ScanIndexForward = sortOrder === \"DESC\" ? false : undefined;\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit,\n ScanIndexForward\n };\n const paginator = paginateQuery(\n {client: this.dynamoDBClient, pageSize: 100},\n queryCommandInput,\n );\n\n if (index) {\n const collectedKeys: Array<K> = [];\n for await (const page of paginator) {\n if (page.Items) {\n collectedKeys.push(\n ...(page.Items.map((item) => unmarshall(item) as T)\n .map((item: T) =>\n Object.fromEntries(Object.entries(item as object).filter(([key]) => key === this.hashKey || key === this.rangKey)) as K)),\n )\n }\n if (limit && collectedKeys.length >= limit) break;\n }\n const keysBatch = limit ? collectedKeys.slice(0, limit) : collectedKeys;\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(keysBatch, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = keysBatch.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return orderedItems.map(item =>\n Object.fromEntries(Object.entries(item as object).filter(([key]) => projSet.has(key))) as T\n ) as Array<T>;\n }\n return orderedItems as Array<T>;\n }\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n getItemsPage = async (\n query: Query & { cursor?: string }\n ): Promise<PageResult<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder, cursor, ...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), {});\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), {});\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (reduction: Record<string, string>, attribute: string) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n {},\n ) : {});\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (reduction: Record<string, string>, filterExpression: FilterExpression) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n {},\n )\n : {};\n\n const ExclusiveStartKey = cursor\n ? JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8')) as Record<string, unknown>\n : undefined;\n\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit: limit,\n ScanIndexForward: sortOrder === \"DESC\" ? false : undefined,\n ExclusiveStartKey: ExclusiveStartKey\n ? marshall(ExclusiveStartKey as Record<string, NativeAttributeValue>, {removeUndefinedValues: true})\n : undefined,\n };\n\n const result = await this.dynamoDBClient.send(new QueryCommand(queryCommandInput));\n const nextCursor = result.LastEvaluatedKey\n ? Buffer.from(JSON.stringify(unmarshall(result.LastEvaluatedKey))).toString('base64')\n : undefined;\n\n if (index) {\n const collectedKeys = (result.Items ?? [])\n .map((item) => unmarshall(item) as T)\n .map((item: T) =>\n Object.fromEntries(Object.entries(item as object).filter(([key]) => key === this.hashKey || key === this.rangKey)) as K\n );\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(collectedKeys, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = collectedKeys.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return {\n items: orderedItems.map(item => Object.fromEntries(Object.entries(item as object).filter(([key]) => projSet.has(key))) as T),\n cursor: nextCursor,\n };\n }\n return {items: orderedItems, cursor: nextCursor};\n }\n\n const items = (result.Items ?? []).map((item) => unmarshall(item) as T);\n return {items, cursor: nextCursor};\n };\n\n\n scan = async (options?: ScanQuery): Promise<Array<T>> => {\n const { filterExpressions, projectedAttributes, limit, index } = options ?? {};\n\n const ProjectionExpression = projectedAttributes?.length\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const projectionAttributeNames: Record<string, string> = projectedAttributes?.length\n ? projectedAttributes.reduce(\n (acc: Record<string, string>, attribute: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n {},\n )\n : {};\n\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc: Record<string, string>, fe: FilterExpression) => ({\n ...acc,\n [`#${expressionAttributeKey(fe.attribute)}`]: fe.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc, fe) => ({ ...acc, ...mapFilterExpressionValues(fe) }),\n {} as Record<string, unknown>,\n )\n : {};\n\n const allAttributeNames = { ...filterAttributeNames, ...projectionAttributeNames };\n const ExpressionAttributeNames = Object.keys(allAttributeNames).length > 0 ? allAttributeNames : undefined;\n const ExpressionAttributeValues = hasFilterExpressions\n ? marshall(filterAttributeValues as Record<string, NativeAttributeValue>, { removeUndefinedValues: true })\n : undefined;\n\n const paginator = paginateScan(\n { client: this.dynamoDBClient, pageSize: 100 },\n {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames,\n ExpressionAttributeValues,\n },\n );\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n batchGetItems = async (\n keys: K[], projectedQuery?: ProjectedQuery\n ): Promise<Array<T>> => {\n const dedupeKey = (key: K): string => {\n const record = key as Record<string, unknown>;\n return this.rangKey\n ? `${String(record[this.hashKey])}\\0${String(record[this.rangKey])}`\n : String(record[this.hashKey]);\n };\n const uniqueKeys = Array.from(new Map(keys.map(k => [dedupeKey(k), k])).values());\n const keyPages = paginate(uniqueKeys, 100);\n const {projectedAttributes} = projectedQuery || {};\n const ProjectionExpression = projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const ExpressionAttributeNames = projectedAttributes ?\n projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n {},\n ) : undefined;\n return Promise.all((keyPages.map(async (keyPage) => {\n const batchRequest: BatchGetItemCommandInput = {\n RequestItems: {\n [this.tableName]: {\n Keys: keyPage.map((key) => marshallKey(key)),\n ProjectionExpression,\n ExpressionAttributeNames,\n }\n },\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }\n\n const fetchPage = async (request: BatchGetItemCommandInput): Promise<T[]> => {\n const result = await this.dynamoDBClient.send(new BatchGetItemCommand(request));\n const retrieved = result.Responses?.[this.tableName]?.map((item) => unmarshall(item) as T) ?? [];\n const unprocessed = result.UnprocessedKeys;\n if (!unprocessed || Object.keys(unprocessed).length === 0) return retrieved;\n return [...retrieved, ...await fetchPage({\n RequestItems: unprocessed,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })];\n };\n\n return fetchPage(batchRequest);\n })))\n .then((itemSets) => itemSets.flat());\n };\n\n batchWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const requests: WriteRequest[] = [\n ...puts.map(({ key, item }) => ({\n PutRequest: {\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n DeleteRequest: { Key: marshallKey(key) },\n })),\n ];\n\n const sendBatch = async (requestItems: Record<string, WriteRequest[]>): Promise<void> => {\n const result = await this.dynamoDBClient.send(\n new BatchWriteItemCommand({\n RequestItems: requestItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n const unprocessed = result.UnprocessedItems;\n if (unprocessed && Object.keys(unprocessed).length > 0) {\n await sendBatch(unprocessed as Record<string, WriteRequest[]>);\n }\n };\n\n await Promise.all(\n paginate(requests, 25).map(batch => sendBatch({ [this.tableName]: batch })),\n );\n };\n\n transactGetItems = async (keys: K[]): Promise<Array<T | undefined>> => {\n const result = await this.dynamoDBClient.send(\n new TransactGetItemsCommand({\n TransactItems: keys.map((key) => ({\n Get: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n return (result.Responses ?? []).map((response) =>\n response.Item ? unmarshall(response.Item) as T : undefined,\n );\n };\n\n transactWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const transactItems = [\n ...puts.map(({ key, item }) => ({\n Put: {\n TableName: this.tableName,\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n Delete: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ];\n await this.dynamoDBClient.send(\n new TransactWriteItemsCommand({\n TransactItems: transactItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n };\n}\n\n","import {\n ConsumedCapacity,\n ReturnConsumedCapacity,\n ServiceInputTypes,\n ServiceOutputTypes,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport {\n InitializeHandler,\n InitializeHandlerArguments,\n InitializeHandlerOutput,\n} from \"@smithy/types\";\n\n\n\nexport interface ConsumedCapacityDetail {\n ReturnConsumedCapacity: ReturnConsumedCapacity | undefined\n ConsumedCapacity: ConsumedCapacity | ConsumedCapacity[] | undefined\n}\n\nexport interface ConsumedCapacityMiddlewareConfig {\n onConsumedCapacity: (consumedCapacity: ConsumedCapacityDetail) => Promise<unknown>;\n}\n\nexport const consumedCapacityMiddleware =\n (consumedCapacityMiddlewareConfig: ConsumedCapacityMiddlewareConfig) =>\n (next: InitializeHandler<ServiceInputTypes, ServiceOutputTypes>) =>\n async (args: InitializeHandlerArguments<ServiceInputTypes>): Promise<InitializeHandlerOutput<ServiceOutputTypes>> => {\n const {input} = args;\n const returnConsumedCapacity = (input as unknown as Record<string, unknown>)[\"ReturnConsumedCapacity\"] as ReturnConsumedCapacity | undefined;\n const response = await next(args);\n const {output} = response;\n const consumedCapacity = (output as unknown as Record<string, unknown>)[\"ConsumedCapacity\"] as ConsumedCapacity | ConsumedCapacity[] | undefined;\n await consumedCapacityMiddlewareConfig.onConsumedCapacity({ReturnConsumedCapacity: returnConsumedCapacity, ConsumedCapacity: consumedCapacity});\n return response;\n };","import { DynamoDBClient, ReturnConsumedCapacity } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDbRepository } from \"./DynamoDbRepository\";\n\nexport type JsonPointerValue = string | number | boolean | null;\n\nexport interface JsonPointerRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n idKey?: string;\n pointerKey?: string;\n valueKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\ntype PointerKey = Record<string, string>;\ntype PointerItem = Record<string, unknown>;\n\nconst isJsonPointerValue = (value: unknown): value is JsonPointerValue =>\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\";\n\nconst escapeToken = (token: string): string =>\n token.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n\nconst unescapeToken = (token: string): string =>\n token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\nconst validatePointer = (pointer: string): void => {\n if (!pointer.startsWith(\"/\")) {\n throw new TypeError(`Invalid JSON Pointer \"${pointer}\": must start with \"/\".`);\n }\n};\n\nconst flattenDocument = (doc: unknown, prefix = \"\"): Record<string, JsonPointerValue> => {\n if (doc === null) return { [prefix]: null };\n if (typeof doc !== \"object\") {\n if (isJsonPointerValue(doc)) {\n return { [prefix]: doc };\n }\n const pointer = prefix === \"\" ? \"/\" : prefix;\n throw new TypeError(\n `Unsupported value at JSON pointer \"${pointer}\": expected string, number, boolean, or null but received ${typeof doc}.`,\n );\n }\n\n const result: Record<string, JsonPointerValue> = {};\n\n if (Array.isArray(doc)) {\n for (let i = 0; i < doc.length; i++) {\n Object.assign(result, flattenDocument(doc[i], `${prefix}/${i}`));\n }\n } else {\n for (const [key, value] of Object.entries(doc)) {\n Object.assign(result, flattenDocument(value, `${prefix}/${escapeToken(key)}`));\n }\n }\n\n return result;\n};\n\nconst setAtPointer = (\n root: Record<string, unknown>,\n pointer: string,\n value: JsonPointerValue,\n): void => {\n const tokens = pointer.split(\"/\").slice(1).map(unescapeToken);\n if (tokens.length === 0) return;\n\n let current: Record<string, unknown> = root;\n for (let i = 0; i < tokens.length - 1; i++) {\n const token = tokens[i];\n const nextToken = tokens[i + 1];\n if (current[token] == null) {\n current[token] = /^\\d+$/.test(nextToken) ? [] : {};\n } else if (typeof current[token] !== \"object\") {\n throw new TypeError(\n `Conflicting pointers: cannot traverse \"${pointer}\" because \"/${tokens.slice(0, i + 1).join(\"/\")}\" already holds a primitive value.`,\n );\n }\n current = current[token] as Record<string, unknown>;\n }\n\n const lastToken = tokens[tokens.length - 1];\n current[lastToken] = value;\n};\n\nconst reconstructDocument = <T>(\n items: Array<{ pointer: string; value: JsonPointerValue }>,\n): T => {\n const root: Record<string, unknown> = {};\n const sorted = [...items].sort((a, b) => a.pointer.localeCompare(b.pointer));\n for (const item of sorted) {\n setAtPointer(root, item.pointer, item.value);\n }\n return root as T;\n};\n\n/**\n * Stores JSON documents as individual per-pointer DynamoDB items addressed by JSON Pointer (RFC 6901).\n *\n * Only JSON objects are supported as the root document (`T extends Record<string, unknown>`).\n * Root arrays and primitives are not supported. Documents must contain at least one leaf value;\n * empty objects and empty arrays are not supported.\n */\nexport class JsonPointerRepository<T extends Record<string, unknown>> {\n private readonly repository: DynamoDbRepository<PointerKey, PointerItem>;\n private readonly idKey: string;\n private readonly pointerKey: string;\n private readonly valueKey: string;\n\n constructor(options: JsonPointerRepositoryOptions) {\n const {\n client,\n tableName,\n idKey = \"id\",\n pointerKey = \"pointer\",\n valueKey = \"value\",\n returnConsumedCapacity,\n } = options;\n\n this.idKey = idKey;\n this.pointerKey = pointerKey;\n this.valueKey = valueKey;\n\n this.repository = new DynamoDbRepository<PointerKey, PointerItem>({\n client,\n tableName,\n hashKey: idKey,\n rangeKey: pointerKey,\n returnConsumedCapacity,\n });\n }\n\n putDocument = async (id: string, document: T): Promise<void> => {\n const flat = flattenDocument(document);\n const newPointers = Object.keys(flat);\n\n if (newPointers.length === 0) {\n throw new TypeError(\n \"Cannot store a document with no leaf values. Empty objects and arrays are not supported.\",\n );\n }\n\n const newPointerSet = new Set(newPointers);\n const existing = await this.repository.getItems({ [this.idKey]: id });\n const existingPointers = existing.map(item => item[this.pointerKey] as string);\n const stalePointers = existingPointers.filter(p => !newPointerSet.has(p));\n\n const puts = Object.entries(flat).map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = stalePointers.map(\n pointer => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey),\n );\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n\n getDocument = async (id: string): Promise<T | undefined> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (!items || items.length === 0) return undefined;\n\n return reconstructDocument<T>(\n items.map(item => ({\n pointer: item[this.pointerKey] as string,\n value: item[this.valueKey] as JsonPointerValue,\n })),\n );\n };\n\n getAttribute = async <V = JsonPointerValue>(\n id: string,\n pointer: string,\n ): Promise<V | undefined> => {\n validatePointer(pointer);\n const item = await this.repository.getItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n return item ? (item[this.valueKey] as V) : undefined;\n };\n\n putAttribute = async (\n id: string,\n pointer: string,\n value: JsonPointerValue,\n ): Promise<void> => {\n validatePointer(pointer);\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n await this.repository.putItem(key, { ...key, [this.valueKey]: value } as PointerItem);\n };\n\n deleteAttribute = async (id: string, pointer: string): Promise<void> => {\n validatePointer(pointer);\n await this.repository.deleteItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n };\n\n deleteDocument = async (id: string): Promise<void> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (items.length === 0) return;\n const deleteKeys = items.map(\n item => ({ [this.idKey]: id, [this.pointerKey]: item[this.pointerKey] as string } as PointerKey),\n );\n await this.repository.batchWriteItems([], deleteKeys);\n };\n\n listDocumentIds = async (): Promise<string[]> => {\n const items = await this.repository.scan({ projectedAttributes: [this.idKey] });\n const seen = new Set<string>();\n for (const item of items) {\n seen.add(item[this.idKey] as string);\n }\n return [...seen];\n };\n\n patchDocument = async (\n id: string,\n updates: Record<string, JsonPointerValue | undefined>,\n ): Promise<void> => {\n const entries = Object.entries(updates);\n if (entries.length === 0) return;\n entries.forEach(([pointer]) => validatePointer(pointer));\n const puts = entries\n .filter((entry): entry is [string, JsonPointerValue] => entry[1] !== undefined)\n .map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = entries\n .filter(([, value]) => value === undefined)\n .map(([pointer]) => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey));\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n}\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BatchGetItemCommand, BatchWriteItemCommand, DeleteItemCommand, GetItemCommand, PutItemCommand, QueryCommand, ReturnConsumedCapacity, ReturnValue, TransactGetItemsCommand, TransactWriteItemsCommand, UpdateItemCommand, paginateQuery, paginateScan } from "@aws-sdk/client-dynamodb";
|
|
2
2
|
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
|
|
3
|
-
import { get, isEqual, pickBy, replace, uniqWith } from "lodash";
|
|
4
3
|
|
|
5
4
|
//#region src/DynamoDbRepository.ts
|
|
6
5
|
let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
|
|
@@ -17,7 +16,7 @@ let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
|
|
|
17
16
|
return FilterOperator;
|
|
18
17
|
}({});
|
|
19
18
|
const marshallKey = (key) => marshall(key, { removeUndefinedValues: true });
|
|
20
|
-
const expressionAttributeKey = (key) => replace(
|
|
19
|
+
const expressionAttributeKey = (key) => key.replace(/-/g, "_");
|
|
21
20
|
const mapInKeys = (filterExpression) => Array.isArray(filterExpression.value) ? filterExpression.value.map((_, index) => `:${expressionAttributeKey(filterExpression.attribute)}${index}`) : `:${expressionAttributeKey(filterExpression.attribute)}`;
|
|
22
21
|
const mapFilterExpression = (filterExpression) => {
|
|
23
22
|
switch (filterExpression.operator) {
|
|
@@ -32,7 +31,7 @@ const mapFilterExpressions = (filterExpressions) => filterExpressions.map((filte
|
|
|
32
31
|
const mapFilterExpressionValues = (filterExpression) => Array.isArray(filterExpression.value) ? filterExpression.value.reduce((reduction, value, index) => ({
|
|
33
32
|
...reduction,
|
|
34
33
|
[`:${expressionAttributeKey(filterExpression.attribute)}${index}`]: value
|
|
35
|
-
}),
|
|
34
|
+
}), {}) : { [`:${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.value };
|
|
36
35
|
const paginate = (array, pageSize) => {
|
|
37
36
|
return array.reduce((acc, val, i) => {
|
|
38
37
|
const idx = Math.floor(i / pageSize);
|
|
@@ -85,7 +84,7 @@ var DynamoDbRepository = class {
|
|
|
85
84
|
ExpressionAttributeNames: filteredUpdateEntries.reduce((acc, [key]) => ({
|
|
86
85
|
...acc,
|
|
87
86
|
[`#${expressionAttributeKey(key)}`]: key
|
|
88
|
-
}),
|
|
87
|
+
}), { ...removeAttributeNames }),
|
|
89
88
|
ExpressionAttributeValues: hasUpdates ? marshall(filteredUpdateEntries.reduce((acc, [key, value]) => ({
|
|
90
89
|
...acc,
|
|
91
90
|
[`:${expressionAttributeKey(key)}`]: value
|
|
@@ -103,11 +102,11 @@ var DynamoDbRepository = class {
|
|
|
103
102
|
const keyExpressionAttributeNames = Object.keys(keys).reduce((acc, key) => ({
|
|
104
103
|
...acc,
|
|
105
104
|
[`#${expressionAttributeKey(key)}`]: key
|
|
106
|
-
}),
|
|
105
|
+
}), {});
|
|
107
106
|
const keyExpressionAttributeValues = Object.entries(keys).reduce((acc, [key, value]) => ({
|
|
108
107
|
...acc,
|
|
109
108
|
[`:${expressionAttributeKey(key)}`]: value
|
|
110
|
-
}),
|
|
109
|
+
}), {});
|
|
111
110
|
const gsiKeyAttributes = index ? [this.hashKey, ...this.rangKey ? [this.rangKey] : []] : [];
|
|
112
111
|
const ProjectionExpression = index ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(",") : projectedAttributes ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(",") : void 0;
|
|
113
112
|
const projectionAttributeNames = index ? gsiKeyAttributes.reduce((acc, attr) => ({
|
|
@@ -116,17 +115,17 @@ var DynamoDbRepository = class {
|
|
|
116
115
|
}), {}) : projectedAttributes ? projectedAttributes.reduce((reduction, attribute) => ({
|
|
117
116
|
...reduction,
|
|
118
117
|
[`#${expressionAttributeKey(attribute)}`]: attribute
|
|
119
|
-
}),
|
|
118
|
+
}), {}) : {};
|
|
120
119
|
const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;
|
|
121
120
|
const FilterExpression = hasFilterExpressions ? mapFilterExpressions(filterExpressions) : void 0;
|
|
122
121
|
const filterAttributeNames = hasFilterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
123
122
|
...reduction,
|
|
124
123
|
[`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute
|
|
125
|
-
}),
|
|
124
|
+
}), {}) : {};
|
|
126
125
|
const filterAttributeValues = filterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
127
126
|
...reduction,
|
|
128
127
|
...mapFilterExpressionValues(filterExpression)
|
|
129
|
-
}),
|
|
128
|
+
}), {}) : {};
|
|
130
129
|
const Limit = limit;
|
|
131
130
|
const ScanIndexForward = sortOrder === "DESC" ? false : void 0;
|
|
132
131
|
const queryCommandInput = {
|
|
@@ -155,7 +154,7 @@ var DynamoDbRepository = class {
|
|
|
155
154
|
if (index) {
|
|
156
155
|
const collectedKeys = [];
|
|
157
156
|
for await (const page of paginator) {
|
|
158
|
-
if (page.Items) collectedKeys.push(...page.Items.map((item) => unmarshall(item)).map((item) =>
|
|
157
|
+
if (page.Items) collectedKeys.push(...page.Items.map((item) => unmarshall(item)).map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => key === this.hashKey || key === this.rangKey))));
|
|
159
158
|
if (limit && collectedKeys.length >= limit) break;
|
|
160
159
|
}
|
|
161
160
|
const keysBatch = limit ? collectedKeys.slice(0, limit) : collectedKeys;
|
|
@@ -173,7 +172,7 @@ var DynamoDbRepository = class {
|
|
|
173
172
|
});
|
|
174
173
|
if (projectedAttributes) {
|
|
175
174
|
const projSet = new Set(projectedAttributes);
|
|
176
|
-
return orderedItems.map((item) =>
|
|
175
|
+
return orderedItems.map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => projSet.has(key))));
|
|
177
176
|
}
|
|
178
177
|
return orderedItems;
|
|
179
178
|
}
|
|
@@ -190,11 +189,11 @@ var DynamoDbRepository = class {
|
|
|
190
189
|
const keyExpressionAttributeNames = Object.keys(keys).reduce((acc, key) => ({
|
|
191
190
|
...acc,
|
|
192
191
|
[`#${expressionAttributeKey(key)}`]: key
|
|
193
|
-
}),
|
|
192
|
+
}), {});
|
|
194
193
|
const keyExpressionAttributeValues = Object.entries(keys).reduce((acc, [key, value]) => ({
|
|
195
194
|
...acc,
|
|
196
195
|
[`:${expressionAttributeKey(key)}`]: value
|
|
197
|
-
}),
|
|
196
|
+
}), {});
|
|
198
197
|
const gsiKeyAttributes = index ? [this.hashKey, ...this.rangKey ? [this.rangKey] : []] : [];
|
|
199
198
|
const ProjectionExpression = index ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(",") : projectedAttributes ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(",") : void 0;
|
|
200
199
|
const projectionAttributeNames = index ? gsiKeyAttributes.reduce((acc, attr) => ({
|
|
@@ -203,17 +202,17 @@ var DynamoDbRepository = class {
|
|
|
203
202
|
}), {}) : projectedAttributes ? projectedAttributes.reduce((reduction, attribute) => ({
|
|
204
203
|
...reduction,
|
|
205
204
|
[`#${expressionAttributeKey(attribute)}`]: attribute
|
|
206
|
-
}),
|
|
205
|
+
}), {}) : {};
|
|
207
206
|
const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;
|
|
208
207
|
const FilterExpression = hasFilterExpressions ? mapFilterExpressions(filterExpressions) : void 0;
|
|
209
208
|
const filterAttributeNames = hasFilterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
210
209
|
...reduction,
|
|
211
210
|
[`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute
|
|
212
|
-
}),
|
|
211
|
+
}), {}) : {};
|
|
213
212
|
const filterAttributeValues = filterExpressions ? filterExpressions.reduce((reduction, filterExpression) => ({
|
|
214
213
|
...reduction,
|
|
215
214
|
...mapFilterExpressionValues(filterExpression)
|
|
216
|
-
}),
|
|
215
|
+
}), {}) : {};
|
|
217
216
|
const ExclusiveStartKey = cursor ? JSON.parse(Buffer.from(cursor, "base64").toString("utf-8")) : void 0;
|
|
218
217
|
const queryCommandInput = {
|
|
219
218
|
TableName: this.tableName,
|
|
@@ -238,7 +237,7 @@ var DynamoDbRepository = class {
|
|
|
238
237
|
const result = await this.dynamoDBClient.send(new QueryCommand(queryCommandInput));
|
|
239
238
|
const nextCursor = result.LastEvaluatedKey ? Buffer.from(JSON.stringify(unmarshall(result.LastEvaluatedKey))).toString("base64") : void 0;
|
|
240
239
|
if (index) {
|
|
241
|
-
const collectedKeys = (result.Items ?? []).map((item) => unmarshall(item)).map((item) =>
|
|
240
|
+
const collectedKeys = (result.Items ?? []).map((item) => unmarshall(item)).map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => key === this.hashKey || key === this.rangKey)));
|
|
242
241
|
const keyAttrs = [this.hashKey, ...this.rangKey ? [this.rangKey] : []];
|
|
243
242
|
const batchProjectedQuery = projectedAttributes ? {
|
|
244
243
|
...query,
|
|
@@ -254,7 +253,7 @@ var DynamoDbRepository = class {
|
|
|
254
253
|
if (projectedAttributes) {
|
|
255
254
|
const projSet = new Set(projectedAttributes);
|
|
256
255
|
return {
|
|
257
|
-
items: orderedItems.map((item) =>
|
|
256
|
+
items: orderedItems.map((item) => Object.fromEntries(Object.entries(item).filter(([key]) => projSet.has(key)))),
|
|
258
257
|
cursor: nextCursor
|
|
259
258
|
};
|
|
260
259
|
}
|
|
@@ -311,13 +310,17 @@ var DynamoDbRepository = class {
|
|
|
311
310
|
return limit ? items.slice(0, limit) : items;
|
|
312
311
|
};
|
|
313
312
|
this.batchGetItems = async (keys, projectedQuery) => {
|
|
314
|
-
const
|
|
313
|
+
const dedupeKey = (key) => {
|
|
314
|
+
const record = key;
|
|
315
|
+
return this.rangKey ? `${String(record[this.hashKey])}\0${String(record[this.rangKey])}` : String(record[this.hashKey]);
|
|
316
|
+
};
|
|
317
|
+
const keyPages = paginate(Array.from(new Map(keys.map((k) => [dedupeKey(k), k])).values()), 100);
|
|
315
318
|
const { projectedAttributes } = projectedQuery || {};
|
|
316
319
|
const ProjectionExpression = projectedAttributes ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(",") : void 0;
|
|
317
320
|
const ExpressionAttributeNames = projectedAttributes ? projectedAttributes.reduce((reduction, attribute) => ({
|
|
318
321
|
...reduction,
|
|
319
322
|
[`#${expressionAttributeKey(attribute)}`]: attribute
|
|
320
|
-
}),
|
|
323
|
+
}), {}) : void 0;
|
|
321
324
|
return Promise.all(keyPages.map(async (keyPage) => {
|
|
322
325
|
const batchRequest = {
|
|
323
326
|
RequestItems: { [this.tableName]: {
|
|
@@ -391,10 +394,10 @@ var DynamoDbRepository = class {
|
|
|
391
394
|
//#region src/consumed-capacity-middleware.ts
|
|
392
395
|
const consumedCapacityMiddleware = (consumedCapacityMiddlewareConfig) => (next) => async (args) => {
|
|
393
396
|
const { input } = args;
|
|
394
|
-
const returnConsumedCapacity =
|
|
397
|
+
const returnConsumedCapacity = input["ReturnConsumedCapacity"];
|
|
395
398
|
const response = await next(args);
|
|
396
399
|
const { output } = response;
|
|
397
|
-
const consumedCapacity =
|
|
400
|
+
const consumedCapacity = output["ConsumedCapacity"];
|
|
398
401
|
await consumedCapacityMiddlewareConfig.onConsumedCapacity({
|
|
399
402
|
ReturnConsumedCapacity: returnConsumedCapacity,
|
|
400
403
|
ConsumedCapacity: consumedCapacity
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/DynamoDbRepository.ts","../src/consumed-capacity-middleware.ts","../src/JsonPointerRepository.ts"],"sourcesContent":["import {\n BatchGetItemCommand,\n BatchGetItemCommandInput,\n BatchWriteItemCommand,\n DeleteItemCommand,\n DynamoDBClient,\n GetItemCommand,\n paginateQuery,\n paginateScan,\n PutItemCommand,\n QueryCommand,\n QueryCommandInput,\n ReturnConsumedCapacity,\n ReturnValue,\n TransactGetItemsCommand,\n TransactWriteItemsCommand,\n UpdateItemCommand,\n WriteRequest,\n} from \"@aws-sdk/client-dynamodb\";\nimport {marshall, unmarshall, NativeAttributeValue} from \"@aws-sdk/util-dynamodb\";\nimport {replace, uniqWith, isEqual, pickBy} from \"lodash\";\n\nexport enum FilterOperator {\n EQUALS = \"=\",\n NOT_EQUALS = \"<>\",\n GREATER_THAN_OR_EQUALS = \">=\",\n GREATER_THAN = \">\",\n LESS_THAN = \"<\",\n LESS_THAN_OR_EQUALS = \"<=\",\n IN = \"IN\",\n BETWEEN = \"BETWEEN\",\n BEGINS_WITH = \"BEGINS_WITH\",\n CONTAINS = \"CONTAINS\",\n}\n\nexport interface FilterExpression {\n attribute: string;\n value:\n | string\n | number\n | boolean\n | Array<string | number>\n | [string, string]\n | [number, number];\n operator: FilterOperator;\n negate?: boolean;\n}\n\nexport interface FilterableQuery {\n filterExpressions: Array<FilterExpression>;\n}\n\nexport interface ProjectedQuery {\n projectedAttributes: string[];\n}\n\nexport interface IndexedQuery {\n index: string;\n}\n\nexport interface Query extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n [key: string]: unknown;\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n sortOrder?: \"ASC\" | \"DESC\";\n limit?: number\n}\n\nexport interface ScanQuery extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n limit?: number;\n}\n\nconst marshallKey = (key: unknown) =>\n marshall(key as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n\nconst expressionAttributeKey = (key: string) => replace(key, /-/g, \"_\");\n\nconst mapInKeys = (filterExpression: FilterExpression) =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.map(\n (_, index) => `:${expressionAttributeKey(filterExpression.attribute)}${index}`,\n )\n : `:${expressionAttributeKey(filterExpression.attribute)}`;\n\nconst mapFilterExpression = (filterExpression: FilterExpression) => {\n switch (filterExpression.operator) {\n case FilterOperator.IN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `(${mapInKeys(filterExpression)})`\n );\n case FilterOperator.BETWEEN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}0 AND :${expressionAttributeKey(filterExpression.attribute)}1`\n );\n case FilterOperator.BEGINS_WITH:\n case FilterOperator.CONTAINS:\n return (\n `${filterExpression.operator.toLowerCase()}(#${expressionAttributeKey(filterExpression.attribute)}, ` +\n `:${expressionAttributeKey(filterExpression.attribute)})`\n );\n default:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}`\n );\n }\n};\n\nconst mapFilterExpressions = (\n filterExpressions: Array<FilterExpression>,\n) =>\n filterExpressions\n .map((filterExpression) =>\n filterExpression.negate\n ? `NOT ${mapFilterExpression(filterExpression)}`\n : mapFilterExpression(filterExpression),\n )\n .join(\" AND \");\n\nconst mapFilterExpressionValues = (\n filterExpression: FilterExpression,\n): Record<string, string | number | boolean> =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.reduce(\n (reduction, value, index) => ({\n ...reduction,\n [`:${expressionAttributeKey(filterExpression.attribute)}${index}`]: value,\n }),\n Object.assign({}),\n )\n : {\n [`:${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.value,\n };\n\nconst paginate = <T>(array: Array<T>, pageSize: number) => {\n return array.reduce((acc, val, i) => {\n const idx = Math.floor(i / pageSize)\n const page = acc[idx] || (acc[idx] = [])\n page.push(val)\n return acc\n }, [] as Array<Array<T>>);\n}\n\nexport interface DynamoDbRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n hashKey: string;\n rangeKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\nexport interface PageResult<T> {\n items: Array<T>;\n cursor?: string;\n}\n\nexport class DynamoDbRepository<K, T> {\n private readonly dynamoDBClient: DynamoDBClient;\n private readonly tableName: string;\n private readonly hashKey: string;\n private readonly rangKey?: string;\n private readonly returnConsumedCapacity: ReturnConsumedCapacity | undefined;\n\n constructor(options: DynamoDbRepositoryOptions) {\n this.dynamoDBClient = options.client;\n this.tableName = options.tableName;\n this.hashKey = options.hashKey;\n this.rangKey = options.rangeKey;\n this.returnConsumedCapacity = options.returnConsumedCapacity ?? ReturnConsumedCapacity.TOTAL;\n }\n\n getItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient\n .send(\n new GetItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n )\n .then((result) =>\n result.Item ? unmarshall(result.Item) as T : undefined,\n )\n };\n\n putItem = async (key: K, record: T): Promise<T> => {\n const Item = marshall({...record, ...key} as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n return this.dynamoDBClient\n .send(\n new PutItemCommand({\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n Item,\n }),\n )\n .then(() => unmarshall(Item) as T);\n };\n\n deleteItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient.send(new DeleteItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnValues: ReturnValue.ALL_OLD,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })).then((result) => result.Attributes ?\n unmarshall(result.Attributes) as T : undefined);\n };\n\n\n updateItem = async (\n key: K,\n updates: Partial<T>,\n remove?: string[],\n ): Promise<T | undefined> => {\n const filteredUpdateEntries = Object.entries(updates).filter(([, value]) => value !== undefined);\n const hasUpdates = filteredUpdateEntries.length > 0;\n if (!hasUpdates && !remove?.length) {\n return this.getItem(key);\n }\n const setAttributesExpression = hasUpdates ? `SET ${filteredUpdateEntries\n .map(\n ([key]) =>\n `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`,\n )\n .join(\", \")}` : '';\n const removeAttributesExpression = remove?.length\n ? ` REMOVE ${remove.map((key) => `#${expressionAttributeKey(key)}`).join(\", \")}`\n : \"\";\n const removeAttributeNames = remove?.length\n ? remove.reduce(\n (acc, key) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n {} as Record<string, string>,\n )\n : {};\n const updateItemCommandInput = {\n TableName: this.tableName,\n Key: marshallKey(key),\n UpdateExpression: `${setAttributesExpression}${removeAttributesExpression}`,\n ExpressionAttributeNames: filteredUpdateEntries\n .reduce(\n (acc, [key]) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n Object.assign(\n removeAttributeNames,\n ),\n ) as Record<string, string>,\n ExpressionAttributeValues: hasUpdates ? marshall(\n filteredUpdateEntries.reduce(\n (acc, [key, value]) => ({\n ...acc,\n [`:${expressionAttributeKey(key)}`]: value,\n }),\n {} as Record<string, NativeAttributeValue>,\n ),\n {removeUndefinedValues: true},\n ) : undefined,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n };\n return this.dynamoDBClient\n .send(new UpdateItemCommand({...updateItemCommandInput, ReturnValues: 'ALL_NEW'}))\n .then((result) => result.Attributes ? unmarshall(result.Attributes) as T : undefined);\n };\n\n\n getItems = async (\n query: Query\n ): Promise<Array<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder,...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), Object.assign({}));\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), Object.assign({}));\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n Object.assign({}),\n ) : {})\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (\n reduction: Record<string, string>,\n filterExpression: FilterExpression,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.attribute,\n }),\n Object.assign({}),\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n Object.assign({}),\n )\n : {};\n\n const Limit = limit;\n const ScanIndexForward = sortOrder === \"DESC\" ? false : undefined;\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit,\n ScanIndexForward\n };\n const paginator = paginateQuery(\n {client: this.dynamoDBClient, pageSize: 100},\n queryCommandInput,\n );\n\n if (index) {\n const collectedKeys: Array<K> = [];\n for await (const page of paginator) {\n if (page.Items) {\n collectedKeys.push(\n ...(page.Items.map((item) => unmarshall(item) as T)\n .map((item: T) =>\n pickBy(item as object, (_, key) => (key === this.hashKey || key === this.rangKey)) as K)),\n )\n }\n if (limit && collectedKeys.length >= limit) break;\n }\n const keysBatch = limit ? collectedKeys.slice(0, limit) : collectedKeys;\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(keysBatch, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = keysBatch.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return orderedItems.map(item =>\n pickBy(item as object, (_, key) => projSet.has(key)) as T\n ) as Array<T>;\n }\n return orderedItems as Array<T>;\n }\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n getItemsPage = async (\n query: Query & { cursor?: string }\n ): Promise<PageResult<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder, cursor, ...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), Object.assign({}));\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), Object.assign({}));\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (reduction: Record<string, string>, attribute: string) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n Object.assign({}),\n ) : {});\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (reduction: Record<string, string>, filterExpression: FilterExpression) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute,\n }),\n Object.assign({}),\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n Object.assign({}),\n )\n : {};\n\n const ExclusiveStartKey = cursor\n ? JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8')) as Record<string, unknown>\n : undefined;\n\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit: limit,\n ScanIndexForward: sortOrder === \"DESC\" ? false : undefined,\n ExclusiveStartKey: ExclusiveStartKey\n ? marshall(ExclusiveStartKey as Record<string, NativeAttributeValue>, {removeUndefinedValues: true})\n : undefined,\n };\n\n const result = await this.dynamoDBClient.send(new QueryCommand(queryCommandInput));\n const nextCursor = result.LastEvaluatedKey\n ? Buffer.from(JSON.stringify(unmarshall(result.LastEvaluatedKey))).toString('base64')\n : undefined;\n\n if (index) {\n const collectedKeys = (result.Items ?? [])\n .map((item) => unmarshall(item) as T)\n .map((item: T) =>\n pickBy(item as object, (_, key) => (key === this.hashKey || key === this.rangKey)) as K\n );\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(collectedKeys, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = collectedKeys.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return {\n items: orderedItems.map(item => pickBy(item as object, (_, key) => projSet.has(key)) as T),\n cursor: nextCursor,\n };\n }\n return {items: orderedItems, cursor: nextCursor};\n }\n\n const items = (result.Items ?? []).map((item) => unmarshall(item) as T);\n return {items, cursor: nextCursor};\n };\n\n\n scan = async (options?: ScanQuery): Promise<Array<T>> => {\n const { filterExpressions, projectedAttributes, limit, index } = options ?? {};\n\n const ProjectionExpression = projectedAttributes?.length\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const projectionAttributeNames: Record<string, string> = projectedAttributes?.length\n ? projectedAttributes.reduce(\n (acc: Record<string, string>, attribute: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n {},\n )\n : {};\n\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc: Record<string, string>, fe: FilterExpression) => ({\n ...acc,\n [`#${expressionAttributeKey(fe.attribute)}`]: fe.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc, fe) => ({ ...acc, ...mapFilterExpressionValues(fe) }),\n {} as Record<string, unknown>,\n )\n : {};\n\n const allAttributeNames = { ...filterAttributeNames, ...projectionAttributeNames };\n const ExpressionAttributeNames = Object.keys(allAttributeNames).length > 0 ? allAttributeNames : undefined;\n const ExpressionAttributeValues = hasFilterExpressions\n ? marshall(filterAttributeValues as Record<string, NativeAttributeValue>, { removeUndefinedValues: true })\n : undefined;\n\n const paginator = paginateScan(\n { client: this.dynamoDBClient, pageSize: 100 },\n {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames,\n ExpressionAttributeValues,\n },\n );\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n batchGetItems = async (\n keys: K[], projectedQuery?: ProjectedQuery\n ): Promise<Array<T>> => {\n const uniqueKeys = uniqWith(keys, isEqual);\n const keyPages = paginate(uniqueKeys, 100);\n const {projectedAttributes} = projectedQuery || {};\n const ProjectionExpression = projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const ExpressionAttributeNames = projectedAttributes ?\n projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n Object.assign({}),\n ) : undefined;\n return Promise.all((keyPages.map(async (keyPage) => {\n const batchRequest: BatchGetItemCommandInput = {\n RequestItems: {\n [this.tableName]: {\n Keys: keyPage.map((key) => marshallKey(key)),\n ProjectionExpression,\n ExpressionAttributeNames,\n }\n },\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }\n\n const fetchPage = async (request: BatchGetItemCommandInput): Promise<T[]> => {\n const result = await this.dynamoDBClient.send(new BatchGetItemCommand(request));\n const retrieved = result.Responses?.[this.tableName]?.map((item) => unmarshall(item) as T) ?? [];\n const unprocessed = result.UnprocessedKeys;\n if (!unprocessed || Object.keys(unprocessed).length === 0) return retrieved;\n return [...retrieved, ...await fetchPage({\n RequestItems: unprocessed,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })];\n };\n\n return fetchPage(batchRequest);\n })))\n .then((itemSets) => itemSets.flat());\n };\n\n batchWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const requests: WriteRequest[] = [\n ...puts.map(({ key, item }) => ({\n PutRequest: {\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n DeleteRequest: { Key: marshallKey(key) },\n })),\n ];\n\n const sendBatch = async (requestItems: Record<string, WriteRequest[]>): Promise<void> => {\n const result = await this.dynamoDBClient.send(\n new BatchWriteItemCommand({\n RequestItems: requestItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n const unprocessed = result.UnprocessedItems;\n if (unprocessed && Object.keys(unprocessed).length > 0) {\n await sendBatch(unprocessed as Record<string, WriteRequest[]>);\n }\n };\n\n await Promise.all(\n paginate(requests, 25).map(batch => sendBatch({ [this.tableName]: batch })),\n );\n };\n\n transactGetItems = async (keys: K[]): Promise<Array<T | undefined>> => {\n const result = await this.dynamoDBClient.send(\n new TransactGetItemsCommand({\n TransactItems: keys.map((key) => ({\n Get: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n return (result.Responses ?? []).map((response) =>\n response.Item ? unmarshall(response.Item) as T : undefined,\n );\n };\n\n transactWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const transactItems = [\n ...puts.map(({ key, item }) => ({\n Put: {\n TableName: this.tableName,\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n Delete: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ];\n await this.dynamoDBClient.send(\n new TransactWriteItemsCommand({\n TransactItems: transactItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n };\n}\n\n","import {\n ConsumedCapacity,\n ReturnConsumedCapacity,\n ServiceInputTypes,\n ServiceOutputTypes,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport {\n InitializeHandler,\n InitializeHandlerArguments,\n InitializeHandlerOutput,\n} from \"@smithy/types\";\n\nimport {get} from \"lodash\";\n\nexport interface ConsumedCapacityDetail {\n ReturnConsumedCapacity: ReturnConsumedCapacity | undefined\n ConsumedCapacity: ConsumedCapacity | ConsumedCapacity[] | undefined\n}\n\nexport interface ConsumedCapacityMiddlewareConfig {\n onConsumedCapacity: (consumedCapacity: ConsumedCapacityDetail) => Promise<unknown>;\n}\n\nexport const consumedCapacityMiddleware =\n (consumedCapacityMiddlewareConfig: ConsumedCapacityMiddlewareConfig) =>\n (next: InitializeHandler<ServiceInputTypes, ServiceOutputTypes>) =>\n async (args: InitializeHandlerArguments<ServiceInputTypes>): Promise<InitializeHandlerOutput<ServiceOutputTypes>> => {\n const {input} = args;\n const returnConsumedCapacity = get(input, \"ReturnConsumedCapacity\") as ReturnConsumedCapacity | undefined;\n const response = await next(args);\n const {output} = response;\n const consumedCapacity = get(output, \"ConsumedCapacity\") as ConsumedCapacity | ConsumedCapacity[] | undefined;\n await consumedCapacityMiddlewareConfig.onConsumedCapacity({ReturnConsumedCapacity: returnConsumedCapacity, ConsumedCapacity: consumedCapacity});\n return response;\n };","import { DynamoDBClient, ReturnConsumedCapacity } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDbRepository } from \"./DynamoDbRepository\";\n\nexport type JsonPointerValue = string | number | boolean | null;\n\nexport interface JsonPointerRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n idKey?: string;\n pointerKey?: string;\n valueKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\ntype PointerKey = Record<string, string>;\ntype PointerItem = Record<string, unknown>;\n\nconst isJsonPointerValue = (value: unknown): value is JsonPointerValue =>\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\";\n\nconst escapeToken = (token: string): string =>\n token.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n\nconst unescapeToken = (token: string): string =>\n token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\nconst validatePointer = (pointer: string): void => {\n if (!pointer.startsWith(\"/\")) {\n throw new TypeError(`Invalid JSON Pointer \"${pointer}\": must start with \"/\".`);\n }\n};\n\nconst flattenDocument = (doc: unknown, prefix = \"\"): Record<string, JsonPointerValue> => {\n if (doc === null) return { [prefix]: null };\n if (typeof doc !== \"object\") {\n if (isJsonPointerValue(doc)) {\n return { [prefix]: doc };\n }\n const pointer = prefix === \"\" ? \"/\" : prefix;\n throw new TypeError(\n `Unsupported value at JSON pointer \"${pointer}\": expected string, number, boolean, or null but received ${typeof doc}.`,\n );\n }\n\n const result: Record<string, JsonPointerValue> = {};\n\n if (Array.isArray(doc)) {\n for (let i = 0; i < doc.length; i++) {\n Object.assign(result, flattenDocument(doc[i], `${prefix}/${i}`));\n }\n } else {\n for (const [key, value] of Object.entries(doc)) {\n Object.assign(result, flattenDocument(value, `${prefix}/${escapeToken(key)}`));\n }\n }\n\n return result;\n};\n\nconst setAtPointer = (\n root: Record<string, unknown>,\n pointer: string,\n value: JsonPointerValue,\n): void => {\n const tokens = pointer.split(\"/\").slice(1).map(unescapeToken);\n if (tokens.length === 0) return;\n\n let current: Record<string, unknown> = root;\n for (let i = 0; i < tokens.length - 1; i++) {\n const token = tokens[i];\n const nextToken = tokens[i + 1];\n if (current[token] == null) {\n current[token] = /^\\d+$/.test(nextToken) ? [] : {};\n } else if (typeof current[token] !== \"object\") {\n throw new TypeError(\n `Conflicting pointers: cannot traverse \"${pointer}\" because \"/${tokens.slice(0, i + 1).join(\"/\")}\" already holds a primitive value.`,\n );\n }\n current = current[token] as Record<string, unknown>;\n }\n\n const lastToken = tokens[tokens.length - 1];\n current[lastToken] = value;\n};\n\nconst reconstructDocument = <T>(\n items: Array<{ pointer: string; value: JsonPointerValue }>,\n): T => {\n const root: Record<string, unknown> = {};\n const sorted = [...items].sort((a, b) => a.pointer.localeCompare(b.pointer));\n for (const item of sorted) {\n setAtPointer(root, item.pointer, item.value);\n }\n return root as T;\n};\n\n/**\n * Stores JSON documents as individual per-pointer DynamoDB items addressed by JSON Pointer (RFC 6901).\n *\n * Only JSON objects are supported as the root document (`T extends Record<string, unknown>`).\n * Root arrays and primitives are not supported. Documents must contain at least one leaf value;\n * empty objects and empty arrays are not supported.\n */\nexport class JsonPointerRepository<T extends Record<string, unknown>> {\n private readonly repository: DynamoDbRepository<PointerKey, PointerItem>;\n private readonly idKey: string;\n private readonly pointerKey: string;\n private readonly valueKey: string;\n\n constructor(options: JsonPointerRepositoryOptions) {\n const {\n client,\n tableName,\n idKey = \"id\",\n pointerKey = \"pointer\",\n valueKey = \"value\",\n returnConsumedCapacity,\n } = options;\n\n this.idKey = idKey;\n this.pointerKey = pointerKey;\n this.valueKey = valueKey;\n\n this.repository = new DynamoDbRepository<PointerKey, PointerItem>({\n client,\n tableName,\n hashKey: idKey,\n rangeKey: pointerKey,\n returnConsumedCapacity,\n });\n }\n\n putDocument = async (id: string, document: T): Promise<void> => {\n const flat = flattenDocument(document);\n const newPointers = Object.keys(flat);\n\n if (newPointers.length === 0) {\n throw new TypeError(\n \"Cannot store a document with no leaf values. Empty objects and arrays are not supported.\",\n );\n }\n\n const newPointerSet = new Set(newPointers);\n const existing = await this.repository.getItems({ [this.idKey]: id });\n const existingPointers = existing.map(item => item[this.pointerKey] as string);\n const stalePointers = existingPointers.filter(p => !newPointerSet.has(p));\n\n const puts = Object.entries(flat).map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = stalePointers.map(\n pointer => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey),\n );\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n\n getDocument = async (id: string): Promise<T | undefined> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (!items || items.length === 0) return undefined;\n\n return reconstructDocument<T>(\n items.map(item => ({\n pointer: item[this.pointerKey] as string,\n value: item[this.valueKey] as JsonPointerValue,\n })),\n );\n };\n\n getAttribute = async <V = JsonPointerValue>(\n id: string,\n pointer: string,\n ): Promise<V | undefined> => {\n validatePointer(pointer);\n const item = await this.repository.getItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n return item ? (item[this.valueKey] as V) : undefined;\n };\n\n putAttribute = async (\n id: string,\n pointer: string,\n value: JsonPointerValue,\n ): Promise<void> => {\n validatePointer(pointer);\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n await this.repository.putItem(key, { ...key, [this.valueKey]: value } as PointerItem);\n };\n\n deleteAttribute = async (id: string, pointer: string): Promise<void> => {\n validatePointer(pointer);\n await this.repository.deleteItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n };\n\n deleteDocument = async (id: string): Promise<void> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (items.length === 0) return;\n const deleteKeys = items.map(\n item => ({ [this.idKey]: id, [this.pointerKey]: item[this.pointerKey] as string } as PointerKey),\n );\n await this.repository.batchWriteItems([], deleteKeys);\n };\n\n listDocumentIds = async (): Promise<string[]> => {\n const items = await this.repository.scan({ projectedAttributes: [this.idKey] });\n const seen = new Set<string>();\n for (const item of items) {\n seen.add(item[this.idKey] as string);\n }\n return [...seen];\n };\n\n patchDocument = async (\n id: string,\n updates: Record<string, JsonPointerValue | undefined>,\n ): Promise<void> => {\n const entries = Object.entries(updates);\n if (entries.length === 0) return;\n entries.forEach(([pointer]) => validatePointer(pointer));\n const puts = entries\n .filter((entry): entry is [string, JsonPointerValue] => entry[1] !== undefined)\n .map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = entries\n .filter(([, value]) => value === undefined)\n .map(([pointer]) => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey));\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/DynamoDbRepository.ts","../src/consumed-capacity-middleware.ts","../src/JsonPointerRepository.ts"],"sourcesContent":["import {\n BatchGetItemCommand,\n BatchGetItemCommandInput,\n BatchWriteItemCommand,\n DeleteItemCommand,\n DynamoDBClient,\n GetItemCommand,\n paginateQuery,\n paginateScan,\n PutItemCommand,\n QueryCommand,\n QueryCommandInput,\n ReturnConsumedCapacity,\n ReturnValue,\n TransactGetItemsCommand,\n TransactWriteItemsCommand,\n UpdateItemCommand,\n WriteRequest,\n} from \"@aws-sdk/client-dynamodb\";\nimport {marshall, unmarshall, NativeAttributeValue} from \"@aws-sdk/util-dynamodb\";\n\nexport enum FilterOperator {\n EQUALS = \"=\",\n NOT_EQUALS = \"<>\",\n GREATER_THAN_OR_EQUALS = \">=\",\n GREATER_THAN = \">\",\n LESS_THAN = \"<\",\n LESS_THAN_OR_EQUALS = \"<=\",\n IN = \"IN\",\n BETWEEN = \"BETWEEN\",\n BEGINS_WITH = \"BEGINS_WITH\",\n CONTAINS = \"CONTAINS\",\n}\n\nexport interface FilterExpression {\n attribute: string;\n value:\n | string\n | number\n | boolean\n | Array<string | number>\n | [string, string]\n | [number, number];\n operator: FilterOperator;\n negate?: boolean;\n}\n\nexport interface FilterableQuery {\n filterExpressions: Array<FilterExpression>;\n}\n\nexport interface ProjectedQuery {\n projectedAttributes: string[];\n}\n\nexport interface IndexedQuery {\n index: string;\n}\n\nexport interface Query extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n [key: string]: unknown;\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n sortOrder?: \"ASC\" | \"DESC\";\n limit?: number\n}\n\nexport interface ScanQuery extends Partial<FilterableQuery>, Partial<ProjectedQuery>, Partial<IndexedQuery> {\n filterExpressions?: Array<FilterExpression>;\n projectedAttributes?: string[];\n index?: string;\n limit?: number;\n}\n\nconst marshallKey = (key: unknown) =>\n marshall(key as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n\nconst expressionAttributeKey = (key: string) => key.replace(/-/g, \"_\");\n\nconst mapInKeys = (filterExpression: FilterExpression) =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.map(\n (_, index) => `:${expressionAttributeKey(filterExpression.attribute)}${index}`,\n )\n : `:${expressionAttributeKey(filterExpression.attribute)}`;\n\nconst mapFilterExpression = (filterExpression: FilterExpression) => {\n switch (filterExpression.operator) {\n case FilterOperator.IN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `(${mapInKeys(filterExpression)})`\n );\n case FilterOperator.BETWEEN:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}0 AND :${expressionAttributeKey(filterExpression.attribute)}1`\n );\n case FilterOperator.BEGINS_WITH:\n case FilterOperator.CONTAINS:\n return (\n `${filterExpression.operator.toLowerCase()}(#${expressionAttributeKey(filterExpression.attribute)}, ` +\n `:${expressionAttributeKey(filterExpression.attribute)})`\n );\n default:\n return (\n `#${expressionAttributeKey(filterExpression.attribute)} ${filterExpression.operator} ` +\n `:${expressionAttributeKey(filterExpression.attribute)}`\n );\n }\n};\n\nconst mapFilterExpressions = (\n filterExpressions: Array<FilterExpression>,\n) =>\n filterExpressions\n .map((filterExpression) =>\n filterExpression.negate\n ? `NOT ${mapFilterExpression(filterExpression)}`\n : mapFilterExpression(filterExpression),\n )\n .join(\" AND \");\n\nconst mapFilterExpressionValues = (\n filterExpression: FilterExpression,\n): Record<string, string | number | boolean> =>\n Array.isArray(filterExpression.value)\n ? filterExpression.value.reduce(\n (reduction, value, index) => ({\n ...reduction,\n [`:${expressionAttributeKey(filterExpression.attribute)}${index}`]: value,\n }),\n {},\n )\n : {\n [`:${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.value,\n };\n\nconst paginate = <T>(array: Array<T>, pageSize: number) => {\n return array.reduce((acc, val, i) => {\n const idx = Math.floor(i / pageSize)\n const page = acc[idx] || (acc[idx] = [])\n page.push(val)\n return acc\n }, [] as Array<Array<T>>);\n}\n\nexport interface DynamoDbRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n hashKey: string;\n rangeKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\nexport interface PageResult<T> {\n items: Array<T>;\n cursor?: string;\n}\n\nexport class DynamoDbRepository<K, T> {\n private readonly dynamoDBClient: DynamoDBClient;\n private readonly tableName: string;\n private readonly hashKey: string;\n private readonly rangKey?: string;\n private readonly returnConsumedCapacity: ReturnConsumedCapacity | undefined;\n\n constructor(options: DynamoDbRepositoryOptions) {\n this.dynamoDBClient = options.client;\n this.tableName = options.tableName;\n this.hashKey = options.hashKey;\n this.rangKey = options.rangeKey;\n this.returnConsumedCapacity = options.returnConsumedCapacity ?? ReturnConsumedCapacity.TOTAL;\n }\n\n getItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient\n .send(\n new GetItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n )\n .then((result) =>\n result.Item ? unmarshall(result.Item) as T : undefined,\n )\n };\n\n putItem = async (key: K, record: T): Promise<T> => {\n const Item = marshall({...record, ...key} as Record<string, NativeAttributeValue>, {removeUndefinedValues: true});\n return this.dynamoDBClient\n .send(\n new PutItemCommand({\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n Item,\n }),\n )\n .then(() => unmarshall(Item) as T);\n };\n\n deleteItem = async (key: K): Promise<T | undefined> => {\n return this.dynamoDBClient.send(new DeleteItemCommand({\n TableName: this.tableName,\n Key: marshallKey(key),\n ReturnValues: ReturnValue.ALL_OLD,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })).then((result) => result.Attributes ?\n unmarshall(result.Attributes) as T : undefined);\n };\n\n\n updateItem = async (\n key: K,\n updates: Partial<T>,\n remove?: string[],\n ): Promise<T | undefined> => {\n const filteredUpdateEntries = Object.entries(updates).filter(([, value]) => value !== undefined);\n const hasUpdates = filteredUpdateEntries.length > 0;\n if (!hasUpdates && !remove?.length) {\n return this.getItem(key);\n }\n const setAttributesExpression = hasUpdates ? `SET ${filteredUpdateEntries\n .map(\n ([key]) =>\n `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`,\n )\n .join(\", \")}` : '';\n const removeAttributesExpression = remove?.length\n ? ` REMOVE ${remove.map((key) => `#${expressionAttributeKey(key)}`).join(\", \")}`\n : \"\";\n const removeAttributeNames = remove?.length\n ? remove.reduce(\n (acc, key) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n {} as Record<string, string>,\n )\n : {};\n const updateItemCommandInput = {\n TableName: this.tableName,\n Key: marshallKey(key),\n UpdateExpression: `${setAttributesExpression}${removeAttributesExpression}`,\n ExpressionAttributeNames: filteredUpdateEntries\n .reduce(\n (acc, [key]) => ({\n ...acc,\n [`#${expressionAttributeKey(key)}`]: key,\n }),\n {...removeAttributeNames},\n ) as Record<string, string>,\n ExpressionAttributeValues: hasUpdates ? marshall(\n filteredUpdateEntries.reduce(\n (acc, [key, value]) => ({\n ...acc,\n [`:${expressionAttributeKey(key)}`]: value,\n }),\n {} as Record<string, NativeAttributeValue>,\n ),\n {removeUndefinedValues: true},\n ) : undefined,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n };\n return this.dynamoDBClient\n .send(new UpdateItemCommand({...updateItemCommandInput, ReturnValues: 'ALL_NEW'}))\n .then((result) => result.Attributes ? unmarshall(result.Attributes) as T : undefined);\n };\n\n\n getItems = async (\n query: Query\n ): Promise<Array<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder,...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), {});\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), {});\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n {},\n ) : {})\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (\n reduction: Record<string, string>,\n filterExpression: FilterExpression,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]:\n filterExpression.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n {},\n )\n : {};\n\n const Limit = limit;\n const ScanIndexForward = sortOrder === \"DESC\" ? false : undefined;\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit,\n ScanIndexForward\n };\n const paginator = paginateQuery(\n {client: this.dynamoDBClient, pageSize: 100},\n queryCommandInput,\n );\n\n if (index) {\n const collectedKeys: Array<K> = [];\n for await (const page of paginator) {\n if (page.Items) {\n collectedKeys.push(\n ...(page.Items.map((item) => unmarshall(item) as T)\n .map((item: T) =>\n Object.fromEntries(Object.entries(item as object).filter(([key]) => key === this.hashKey || key === this.rangKey)) as K)),\n )\n }\n if (limit && collectedKeys.length >= limit) break;\n }\n const keysBatch = limit ? collectedKeys.slice(0, limit) : collectedKeys;\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(keysBatch, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = keysBatch.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return orderedItems.map(item =>\n Object.fromEntries(Object.entries(item as object).filter(([key]) => projSet.has(key))) as T\n ) as Array<T>;\n }\n return orderedItems as Array<T>;\n }\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n getItemsPage = async (\n query: Query & { cursor?: string }\n ): Promise<PageResult<T>> => {\n const {index, filterExpressions, projectedAttributes, limit, sortOrder, cursor, ...keys} = query;\n const KeyConditionExpression = Object.keys(keys)\n .map((key) => `#${expressionAttributeKey(key)} = :${expressionAttributeKey(key)}`).join(' AND ');\n const keyExpressionAttributeNames = Object.keys(keys)\n .reduce((acc, key) => ({...acc, [`#${expressionAttributeKey(key)}`]: key}), {});\n const keyExpressionAttributeValues = Object.entries(keys)\n .reduce((acc, [key, value]) => ({...acc, [`:${expressionAttributeKey(key)}`]: value}), {});\n\n const gsiKeyAttributes = index\n ? [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])]\n : [];\n const ProjectionExpression = index\n ? gsiKeyAttributes.map((attr) => `#${expressionAttributeKey(attr)}`).join(',')\n : (projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined);\n const projectionAttributeNames: Record<string, string> = index\n ? gsiKeyAttributes.reduce(\n (acc: Record<string, string>, attr: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attr)}`]: attr,\n }),\n {},\n )\n : (projectedAttributes ? projectedAttributes.reduce(\n (reduction: Record<string, string>, attribute: string) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n {},\n ) : {});\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (reduction: Record<string, string>, filterExpression: FilterExpression) => ({\n ...reduction,\n [`#${expressionAttributeKey(filterExpression.attribute)}`]: filterExpression.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = filterExpressions\n ? filterExpressions.reduce(\n (reduction, filterExpression) => ({\n ...reduction,\n ...mapFilterExpressionValues(filterExpression),\n }),\n {},\n )\n : {};\n\n const ExclusiveStartKey = cursor\n ? JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8')) as Record<string, unknown>\n : undefined;\n\n const queryCommandInput: QueryCommandInput = {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n KeyConditionExpression,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames: {\n ...keyExpressionAttributeNames,\n ...filterAttributeNames,\n ...projectionAttributeNames\n },\n ExpressionAttributeValues: marshall(\n {...keyExpressionAttributeValues, ...filterAttributeValues} as Record<string, NativeAttributeValue>,\n {removeUndefinedValues: true},\n ),\n Limit: limit,\n ScanIndexForward: sortOrder === \"DESC\" ? false : undefined,\n ExclusiveStartKey: ExclusiveStartKey\n ? marshall(ExclusiveStartKey as Record<string, NativeAttributeValue>, {removeUndefinedValues: true})\n : undefined,\n };\n\n const result = await this.dynamoDBClient.send(new QueryCommand(queryCommandInput));\n const nextCursor = result.LastEvaluatedKey\n ? Buffer.from(JSON.stringify(unmarshall(result.LastEvaluatedKey))).toString('base64')\n : undefined;\n\n if (index) {\n const collectedKeys = (result.Items ?? [])\n .map((item) => unmarshall(item) as T)\n .map((item: T) =>\n Object.fromEntries(Object.entries(item as object).filter(([key]) => key === this.hashKey || key === this.rangKey)) as K\n );\n const keyAttrs = [this.hashKey, ...(this.rangKey ? [this.rangKey] : [])];\n const batchProjectedQuery = projectedAttributes\n ? { ...query, projectedAttributes: [...new Set([...projectedAttributes, ...keyAttrs])] } as ProjectedQuery\n : query as ProjectedQuery;\n const items = await this.batchGetItems(collectedKeys, batchProjectedQuery);\n const gsiItemKey = (item: Record<string, unknown>): string =>\n this.rangKey\n ? `${String(item[this.hashKey])}\\0${String(item[this.rangKey])}`\n : String(item[this.hashKey]);\n const itemMap = new Map<string, T>(\n items.map(item => [gsiItemKey(item as Record<string, unknown>), item])\n );\n const orderedItems = collectedKeys.flatMap((key) => {\n const match = itemMap.get(gsiItemKey(key as Record<string, unknown>));\n return match ? [match] : [];\n });\n if (projectedAttributes) {\n const projSet = new Set(projectedAttributes);\n return {\n items: orderedItems.map(item => Object.fromEntries(Object.entries(item as object).filter(([key]) => projSet.has(key))) as T),\n cursor: nextCursor,\n };\n }\n return {items: orderedItems, cursor: nextCursor};\n }\n\n const items = (result.Items ?? []).map((item) => unmarshall(item) as T);\n return {items, cursor: nextCursor};\n };\n\n\n scan = async (options?: ScanQuery): Promise<Array<T>> => {\n const { filterExpressions, projectedAttributes, limit, index } = options ?? {};\n\n const ProjectionExpression = projectedAttributes?.length\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const projectionAttributeNames: Record<string, string> = projectedAttributes?.length\n ? projectedAttributes.reduce(\n (acc: Record<string, string>, attribute: string) => ({\n ...acc,\n [`#${expressionAttributeKey(attribute)}`]: attribute,\n }),\n {},\n )\n : {};\n\n const hasFilterExpressions = Array.isArray(filterExpressions) && filterExpressions.length > 0;\n const FilterExpression = hasFilterExpressions\n ? mapFilterExpressions(filterExpressions!)\n : undefined;\n const filterAttributeNames: Record<string, string> = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc: Record<string, string>, fe: FilterExpression) => ({\n ...acc,\n [`#${expressionAttributeKey(fe.attribute)}`]: fe.attribute,\n }),\n {},\n )\n : {};\n const filterAttributeValues = hasFilterExpressions\n ? filterExpressions!.reduce(\n (acc, fe) => ({ ...acc, ...mapFilterExpressionValues(fe) }),\n {} as Record<string, unknown>,\n )\n : {};\n\n const allAttributeNames = { ...filterAttributeNames, ...projectionAttributeNames };\n const ExpressionAttributeNames = Object.keys(allAttributeNames).length > 0 ? allAttributeNames : undefined;\n const ExpressionAttributeValues = hasFilterExpressions\n ? marshall(filterAttributeValues as Record<string, NativeAttributeValue>, { removeUndefinedValues: true })\n : undefined;\n\n const paginator = paginateScan(\n { client: this.dynamoDBClient, pageSize: 100 },\n {\n TableName: this.tableName,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n IndexName: index,\n FilterExpression,\n ProjectionExpression,\n ExpressionAttributeNames,\n ExpressionAttributeValues,\n },\n );\n\n const items: Array<T> = [];\n for await (const page of paginator) {\n if (page.Items) {\n items.push(...page.Items.map((item) => unmarshall(item) as T));\n }\n if (limit && items.length >= limit) break;\n }\n return limit ? items.slice(0, limit) : items;\n };\n\n\n batchGetItems = async (\n keys: K[], projectedQuery?: ProjectedQuery\n ): Promise<Array<T>> => {\n const dedupeKey = (key: K): string => {\n const record = key as Record<string, unknown>;\n return this.rangKey\n ? `${String(record[this.hashKey])}\\0${String(record[this.rangKey])}`\n : String(record[this.hashKey]);\n };\n const uniqueKeys = Array.from(new Map(keys.map(k => [dedupeKey(k), k])).values());\n const keyPages = paginate(uniqueKeys, 100);\n const {projectedAttributes} = projectedQuery || {};\n const ProjectionExpression = projectedAttributes\n ? projectedAttributes.map((attribute) => `#${expressionAttributeKey(attribute)}`).join(',')\n : undefined;\n const ExpressionAttributeNames = projectedAttributes ?\n projectedAttributes.reduce(\n (\n reduction: Record<string, string>,\n attribute: string,\n ) => ({\n ...reduction,\n [`#${expressionAttributeKey(attribute)}`]:\n attribute,\n }),\n {},\n ) : undefined;\n return Promise.all((keyPages.map(async (keyPage) => {\n const batchRequest: BatchGetItemCommandInput = {\n RequestItems: {\n [this.tableName]: {\n Keys: keyPage.map((key) => marshallKey(key)),\n ProjectionExpression,\n ExpressionAttributeNames,\n }\n },\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }\n\n const fetchPage = async (request: BatchGetItemCommandInput): Promise<T[]> => {\n const result = await this.dynamoDBClient.send(new BatchGetItemCommand(request));\n const retrieved = result.Responses?.[this.tableName]?.map((item) => unmarshall(item) as T) ?? [];\n const unprocessed = result.UnprocessedKeys;\n if (!unprocessed || Object.keys(unprocessed).length === 0) return retrieved;\n return [...retrieved, ...await fetchPage({\n RequestItems: unprocessed,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n })];\n };\n\n return fetchPage(batchRequest);\n })))\n .then((itemSets) => itemSets.flat());\n };\n\n batchWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const requests: WriteRequest[] = [\n ...puts.map(({ key, item }) => ({\n PutRequest: {\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n DeleteRequest: { Key: marshallKey(key) },\n })),\n ];\n\n const sendBatch = async (requestItems: Record<string, WriteRequest[]>): Promise<void> => {\n const result = await this.dynamoDBClient.send(\n new BatchWriteItemCommand({\n RequestItems: requestItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n const unprocessed = result.UnprocessedItems;\n if (unprocessed && Object.keys(unprocessed).length > 0) {\n await sendBatch(unprocessed as Record<string, WriteRequest[]>);\n }\n };\n\n await Promise.all(\n paginate(requests, 25).map(batch => sendBatch({ [this.tableName]: batch })),\n );\n };\n\n transactGetItems = async (keys: K[]): Promise<Array<T | undefined>> => {\n const result = await this.dynamoDBClient.send(\n new TransactGetItemsCommand({\n TransactItems: keys.map((key) => ({\n Get: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n return (result.Responses ?? []).map((response) =>\n response.Item ? unmarshall(response.Item) as T : undefined,\n );\n };\n\n transactWriteItems = async (\n puts: { key: K; item: T }[],\n deletes: K[],\n ): Promise<void> => {\n const transactItems = [\n ...puts.map(({ key, item }) => ({\n Put: {\n TableName: this.tableName,\n Item: marshall(\n { ...item, ...key } as Record<string, NativeAttributeValue>,\n { removeUndefinedValues: true },\n ),\n },\n })),\n ...deletes.map((key) => ({\n Delete: {\n TableName: this.tableName,\n Key: marshallKey(key),\n },\n })),\n ];\n await this.dynamoDBClient.send(\n new TransactWriteItemsCommand({\n TransactItems: transactItems,\n ReturnConsumedCapacity: this.returnConsumedCapacity,\n }),\n );\n };\n}\n\n","import {\n ConsumedCapacity,\n ReturnConsumedCapacity,\n ServiceInputTypes,\n ServiceOutputTypes,\n} from \"@aws-sdk/client-dynamodb\";\n\nimport {\n InitializeHandler,\n InitializeHandlerArguments,\n InitializeHandlerOutput,\n} from \"@smithy/types\";\n\n\n\nexport interface ConsumedCapacityDetail {\n ReturnConsumedCapacity: ReturnConsumedCapacity | undefined\n ConsumedCapacity: ConsumedCapacity | ConsumedCapacity[] | undefined\n}\n\nexport interface ConsumedCapacityMiddlewareConfig {\n onConsumedCapacity: (consumedCapacity: ConsumedCapacityDetail) => Promise<unknown>;\n}\n\nexport const consumedCapacityMiddleware =\n (consumedCapacityMiddlewareConfig: ConsumedCapacityMiddlewareConfig) =>\n (next: InitializeHandler<ServiceInputTypes, ServiceOutputTypes>) =>\n async (args: InitializeHandlerArguments<ServiceInputTypes>): Promise<InitializeHandlerOutput<ServiceOutputTypes>> => {\n const {input} = args;\n const returnConsumedCapacity = (input as unknown as Record<string, unknown>)[\"ReturnConsumedCapacity\"] as ReturnConsumedCapacity | undefined;\n const response = await next(args);\n const {output} = response;\n const consumedCapacity = (output as unknown as Record<string, unknown>)[\"ConsumedCapacity\"] as ConsumedCapacity | ConsumedCapacity[] | undefined;\n await consumedCapacityMiddlewareConfig.onConsumedCapacity({ReturnConsumedCapacity: returnConsumedCapacity, ConsumedCapacity: consumedCapacity});\n return response;\n };","import { DynamoDBClient, ReturnConsumedCapacity } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDbRepository } from \"./DynamoDbRepository\";\n\nexport type JsonPointerValue = string | number | boolean | null;\n\nexport interface JsonPointerRepositoryOptions {\n client: DynamoDBClient;\n tableName: string;\n idKey?: string;\n pointerKey?: string;\n valueKey?: string;\n returnConsumedCapacity?: ReturnConsumedCapacity;\n}\n\ntype PointerKey = Record<string, string>;\ntype PointerItem = Record<string, unknown>;\n\nconst isJsonPointerValue = (value: unknown): value is JsonPointerValue =>\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\";\n\nconst escapeToken = (token: string): string =>\n token.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n\nconst unescapeToken = (token: string): string =>\n token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\nconst validatePointer = (pointer: string): void => {\n if (!pointer.startsWith(\"/\")) {\n throw new TypeError(`Invalid JSON Pointer \"${pointer}\": must start with \"/\".`);\n }\n};\n\nconst flattenDocument = (doc: unknown, prefix = \"\"): Record<string, JsonPointerValue> => {\n if (doc === null) return { [prefix]: null };\n if (typeof doc !== \"object\") {\n if (isJsonPointerValue(doc)) {\n return { [prefix]: doc };\n }\n const pointer = prefix === \"\" ? \"/\" : prefix;\n throw new TypeError(\n `Unsupported value at JSON pointer \"${pointer}\": expected string, number, boolean, or null but received ${typeof doc}.`,\n );\n }\n\n const result: Record<string, JsonPointerValue> = {};\n\n if (Array.isArray(doc)) {\n for (let i = 0; i < doc.length; i++) {\n Object.assign(result, flattenDocument(doc[i], `${prefix}/${i}`));\n }\n } else {\n for (const [key, value] of Object.entries(doc)) {\n Object.assign(result, flattenDocument(value, `${prefix}/${escapeToken(key)}`));\n }\n }\n\n return result;\n};\n\nconst setAtPointer = (\n root: Record<string, unknown>,\n pointer: string,\n value: JsonPointerValue,\n): void => {\n const tokens = pointer.split(\"/\").slice(1).map(unescapeToken);\n if (tokens.length === 0) return;\n\n let current: Record<string, unknown> = root;\n for (let i = 0; i < tokens.length - 1; i++) {\n const token = tokens[i];\n const nextToken = tokens[i + 1];\n if (current[token] == null) {\n current[token] = /^\\d+$/.test(nextToken) ? [] : {};\n } else if (typeof current[token] !== \"object\") {\n throw new TypeError(\n `Conflicting pointers: cannot traverse \"${pointer}\" because \"/${tokens.slice(0, i + 1).join(\"/\")}\" already holds a primitive value.`,\n );\n }\n current = current[token] as Record<string, unknown>;\n }\n\n const lastToken = tokens[tokens.length - 1];\n current[lastToken] = value;\n};\n\nconst reconstructDocument = <T>(\n items: Array<{ pointer: string; value: JsonPointerValue }>,\n): T => {\n const root: Record<string, unknown> = {};\n const sorted = [...items].sort((a, b) => a.pointer.localeCompare(b.pointer));\n for (const item of sorted) {\n setAtPointer(root, item.pointer, item.value);\n }\n return root as T;\n};\n\n/**\n * Stores JSON documents as individual per-pointer DynamoDB items addressed by JSON Pointer (RFC 6901).\n *\n * Only JSON objects are supported as the root document (`T extends Record<string, unknown>`).\n * Root arrays and primitives are not supported. Documents must contain at least one leaf value;\n * empty objects and empty arrays are not supported.\n */\nexport class JsonPointerRepository<T extends Record<string, unknown>> {\n private readonly repository: DynamoDbRepository<PointerKey, PointerItem>;\n private readonly idKey: string;\n private readonly pointerKey: string;\n private readonly valueKey: string;\n\n constructor(options: JsonPointerRepositoryOptions) {\n const {\n client,\n tableName,\n idKey = \"id\",\n pointerKey = \"pointer\",\n valueKey = \"value\",\n returnConsumedCapacity,\n } = options;\n\n this.idKey = idKey;\n this.pointerKey = pointerKey;\n this.valueKey = valueKey;\n\n this.repository = new DynamoDbRepository<PointerKey, PointerItem>({\n client,\n tableName,\n hashKey: idKey,\n rangeKey: pointerKey,\n returnConsumedCapacity,\n });\n }\n\n putDocument = async (id: string, document: T): Promise<void> => {\n const flat = flattenDocument(document);\n const newPointers = Object.keys(flat);\n\n if (newPointers.length === 0) {\n throw new TypeError(\n \"Cannot store a document with no leaf values. Empty objects and arrays are not supported.\",\n );\n }\n\n const newPointerSet = new Set(newPointers);\n const existing = await this.repository.getItems({ [this.idKey]: id });\n const existingPointers = existing.map(item => item[this.pointerKey] as string);\n const stalePointers = existingPointers.filter(p => !newPointerSet.has(p));\n\n const puts = Object.entries(flat).map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = stalePointers.map(\n pointer => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey),\n );\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n\n getDocument = async (id: string): Promise<T | undefined> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (!items || items.length === 0) return undefined;\n\n return reconstructDocument<T>(\n items.map(item => ({\n pointer: item[this.pointerKey] as string,\n value: item[this.valueKey] as JsonPointerValue,\n })),\n );\n };\n\n getAttribute = async <V = JsonPointerValue>(\n id: string,\n pointer: string,\n ): Promise<V | undefined> => {\n validatePointer(pointer);\n const item = await this.repository.getItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n return item ? (item[this.valueKey] as V) : undefined;\n };\n\n putAttribute = async (\n id: string,\n pointer: string,\n value: JsonPointerValue,\n ): Promise<void> => {\n validatePointer(pointer);\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n await this.repository.putItem(key, { ...key, [this.valueKey]: value } as PointerItem);\n };\n\n deleteAttribute = async (id: string, pointer: string): Promise<void> => {\n validatePointer(pointer);\n await this.repository.deleteItem({\n [this.idKey]: id,\n [this.pointerKey]: pointer,\n } as PointerKey);\n };\n\n deleteDocument = async (id: string): Promise<void> => {\n const items = await this.repository.getItems({ [this.idKey]: id });\n if (items.length === 0) return;\n const deleteKeys = items.map(\n item => ({ [this.idKey]: id, [this.pointerKey]: item[this.pointerKey] as string } as PointerKey),\n );\n await this.repository.batchWriteItems([], deleteKeys);\n };\n\n listDocumentIds = async (): Promise<string[]> => {\n const items = await this.repository.scan({ projectedAttributes: [this.idKey] });\n const seen = new Set<string>();\n for (const item of items) {\n seen.add(item[this.idKey] as string);\n }\n return [...seen];\n };\n\n patchDocument = async (\n id: string,\n updates: Record<string, JsonPointerValue | undefined>,\n ): Promise<void> => {\n const entries = Object.entries(updates);\n if (entries.length === 0) return;\n entries.forEach(([pointer]) => validatePointer(pointer));\n const puts = entries\n .filter((entry): entry is [string, JsonPointerValue] => entry[1] !== undefined)\n .map(([pointer, value]) => {\n const key = { [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey;\n return { key, item: { ...key, [this.valueKey]: value } as PointerItem };\n });\n const deleteKeys = entries\n .filter(([, value]) => value === undefined)\n .map(([pointer]) => ({ [this.idKey]: id, [this.pointerKey]: pointer } as PointerKey));\n await this.repository.batchWriteItems(puts, deleteKeys);\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eresearchqut/ddb-repository",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A TypeScript library providing a generic repository pattern implementation for AWS DynamoDB, simplifying CRUD operations and common database interactions.",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
"@semantic-release/github": "^12.0.8",
|
|
39
39
|
"@semantic-release/npm": "^13.1.5",
|
|
40
40
|
"@smithy/types": "^4.14.2",
|
|
41
|
-
"@types/lodash": "^4.17.24",
|
|
42
41
|
"@types/node": "^25.9.1",
|
|
43
42
|
"@vitest/coverage-v8": "^4.1.7",
|
|
44
43
|
"eslint": "^10.4.0",
|
|
@@ -51,8 +50,7 @@
|
|
|
51
50
|
},
|
|
52
51
|
"peerDependencies": {
|
|
53
52
|
"@aws-sdk/client-dynamodb": ">= 3.1050.0",
|
|
54
|
-
"@aws-sdk/util-dynamodb": ">= 3.996.2"
|
|
55
|
-
"lodash": ">= 4.18.1"
|
|
53
|
+
"@aws-sdk/util-dynamodb": ">= 3.996.2"
|
|
56
54
|
},
|
|
57
55
|
"repository": {
|
|
58
56
|
"type": "git",
|