@moicky/dynamodb 2.4.6 → 2.5.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.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/lib/fixes.d.ts +4 -4
- package/dist/lib/fixes.js +4 -4
- package/dist/lib/helpers.d.ts +30 -3
- package/dist/lib/helpers.js +67 -5
- package/dist/operations/query.js +13 -9
- package/dist/operations/transactWriteItems.js +9 -3
- package/dist/operations/update.js +7 -8
- package/dist/transactions/index.d.ts +20 -0
- package/dist/transactions/index.js +139 -0
- package/dist/transactions/operations.d.ts +41 -0
- package/dist/transactions/operations.js +148 -0
- package/dist/transactions/references/index.d.ts +21 -0
- package/dist/transactions/references/index.js +111 -0
- package/dist/transactions/references/types.d.ts +21 -0
- package/dist/transactions/references/types.js +2 -0
- package/dist/transactions/types.d.ts +54 -0
- package/dist/transactions/types.js +2 -0
- package/package.json +1 -1
- package/readme.md +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export * from "./lib";
|
|
2
2
|
export * from "./operations";
|
|
3
|
+
export * from "./transactions";
|
|
4
|
+
export { createCustomReference, getDependencies, resolveReferences, } from "./transactions/references";
|
|
5
|
+
export type { ReferenceMetadata, ReferenceTo, ResolvedItem, WithoutReferences, } from "./transactions/references/types";
|
|
3
6
|
export type * from "./types";
|
package/dist/index.js
CHANGED
|
@@ -14,5 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.resolveReferences = exports.getDependencies = exports.createCustomReference = void 0;
|
|
17
18
|
__exportStar(require("./lib"), exports);
|
|
18
19
|
__exportStar(require("./operations"), exports);
|
|
20
|
+
__exportStar(require("./transactions"), exports);
|
|
21
|
+
var references_1 = require("./transactions/references");
|
|
22
|
+
Object.defineProperty(exports, "createCustomReference", { enumerable: true, get: function () { return references_1.createCustomReference; } });
|
|
23
|
+
Object.defineProperty(exports, "getDependencies", { enumerable: true, get: function () { return references_1.getDependencies; } });
|
|
24
|
+
Object.defineProperty(exports, "resolveReferences", { enumerable: true, get: function () { return references_1.resolveReferences; } });
|
package/dist/lib/fixes.d.ts
CHANGED
|
@@ -39,27 +39,27 @@ export declare const initFixes: (fixesConfig: DynamoDBFixes) => void;
|
|
|
39
39
|
*/
|
|
40
40
|
export declare const getFixes: () => DynamoDBFixes;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* Applies fixes in arguments for Query/Scan operations.
|
|
43
43
|
* @param args - The arguments to override the default arguments with
|
|
44
44
|
* @returns The merged arguments
|
|
45
45
|
* @private
|
|
46
46
|
*/
|
|
47
47
|
export declare const withFixes: (args: Partial<QueryCommandInput> | Partial<ScanCommandInput>) => Partial<QueryCommandInput> | Partial<ScanCommandInput>;
|
|
48
48
|
/**
|
|
49
|
-
* Returns the
|
|
49
|
+
* Returns the default {@link DynamoDBFixes} used for all operations.
|
|
50
50
|
* @returns The current {@link DynamoDBFixes}
|
|
51
51
|
* @private
|
|
52
52
|
*/
|
|
53
53
|
export declare const getDefaultFixes: () => DynamoDBFixes;
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
* Marshalls the input using {@link marshall} with the global options.
|
|
56
56
|
* @param input - The input to marshall
|
|
57
57
|
* @returns The marshalled input
|
|
58
58
|
* @private
|
|
59
59
|
*/
|
|
60
60
|
export declare const marshallWithOptions: (input: Parameters<typeof marshall>[0]) => Record<string, import("@aws-sdk/client-dynamodb").AttributeValue>;
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* Unmarshalls the input using {@link unmarshall} with the global options.
|
|
63
63
|
* @param input - The input to unmarshall
|
|
64
64
|
* @returns The unmarshalled input
|
|
65
65
|
* @private
|
package/dist/lib/fixes.js
CHANGED
|
@@ -33,7 +33,7 @@ const handleIndex = (args) => {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Applies fixes in arguments for Query/Scan operations.
|
|
37
37
|
* @param args - The arguments to override the default arguments with
|
|
38
38
|
* @returns The merged arguments
|
|
39
39
|
* @private
|
|
@@ -44,14 +44,14 @@ const withFixes = (args) => {
|
|
|
44
44
|
};
|
|
45
45
|
exports.withFixes = withFixes;
|
|
46
46
|
/**
|
|
47
|
-
* Returns the
|
|
47
|
+
* Returns the default {@link DynamoDBFixes} used for all operations.
|
|
48
48
|
* @returns The current {@link DynamoDBFixes}
|
|
49
49
|
* @private
|
|
50
50
|
*/
|
|
51
51
|
const getDefaultFixes = () => defaults;
|
|
52
52
|
exports.getDefaultFixes = getDefaultFixes;
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* Marshalls the input using {@link marshall} with the global options.
|
|
55
55
|
* @param input - The input to marshall
|
|
56
56
|
* @returns The marshalled input
|
|
57
57
|
* @private
|
|
@@ -59,7 +59,7 @@ exports.getDefaultFixes = getDefaultFixes;
|
|
|
59
59
|
const marshallWithOptions = (input) => (0, util_dynamodb_1.marshall)(input, fixes.marshallOptions);
|
|
60
60
|
exports.marshallWithOptions = marshallWithOptions;
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* Unmarshalls the input using {@link unmarshall} with the global options.
|
|
63
63
|
* @param input - The input to unmarshall
|
|
64
64
|
* @returns The unmarshalled input
|
|
65
65
|
* @private
|
package/dist/lib/helpers.d.ts
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
export declare function stripKey(key:
|
|
1
|
+
export declare function stripKey(key: Record<string, any>, args?: {
|
|
2
2
|
TableName?: string;
|
|
3
3
|
}): Record<string, import("@aws-sdk/client-dynamodb").AttributeValue>;
|
|
4
4
|
export declare function splitEvery<T>(items: T[], limit?: number): T[][];
|
|
5
|
-
export declare function getAttributeValues(key:
|
|
6
|
-
|
|
5
|
+
export declare function getAttributeValues(key: Record<string, any>, { attributesToGet, prefix, }?: {
|
|
6
|
+
attributesToGet?: string[];
|
|
7
|
+
prefix?: string;
|
|
8
|
+
}): Record<string, import("@aws-sdk/client-dynamodb").AttributeValue>;
|
|
9
|
+
export declare function getAttributeNames(key: Record<string, any>, { attributesToGet, prefix, }?: {
|
|
10
|
+
attributesToGet?: string[];
|
|
11
|
+
prefix?: string;
|
|
12
|
+
}): Record<string, string>;
|
|
7
13
|
export declare function getAttributesFromExpression(expression: string, prefix?: string): string[];
|
|
14
|
+
export declare class ExpressionAttributes {
|
|
15
|
+
ExpressionAttributeValues: Record<string, any>;
|
|
16
|
+
ExpressionAttributeNames: Record<string, string>;
|
|
17
|
+
nameMapping: Record<string, string>;
|
|
18
|
+
valueMapping: Record<string, any>;
|
|
19
|
+
nameCounter: number;
|
|
20
|
+
valueCounter: number;
|
|
21
|
+
constructor(ExpressionAttributeValues?: Record<string, any>, ExpressionAttributeNames?: Record<string, string>);
|
|
22
|
+
appendNames(names: string[]): void;
|
|
23
|
+
appendValues(values: Record<string, any>): void;
|
|
24
|
+
appendBoth(values: Record<string, any>): void;
|
|
25
|
+
getAttributes(): {
|
|
26
|
+
ExpressionAttributeValues: Record<string, import("@aws-sdk/client-dynamodb").AttributeValue>;
|
|
27
|
+
ExpressionAttributeNames: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
getName(attributeName: string): string;
|
|
30
|
+
getValue(attributeName: string): any;
|
|
31
|
+
}
|
|
32
|
+
export declare const getItemKey: (item: Record<string, any>, args?: {
|
|
33
|
+
TableName?: string;
|
|
34
|
+
}) => string;
|
package/dist/lib/helpers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAttributesFromExpression = exports.getAttributeNames = exports.getAttributeValues = exports.splitEvery = exports.stripKey = void 0;
|
|
3
|
+
exports.getItemKey = exports.ExpressionAttributes = exports.getAttributesFromExpression = exports.getAttributeNames = exports.getAttributeValues = exports.splitEvery = exports.stripKey = void 0;
|
|
4
4
|
const fixes_1 = require("./fixes");
|
|
5
5
|
const schemas_1 = require("./schemas");
|
|
6
6
|
// Since dynamo only accepts key atrtributes which are described in table schema
|
|
@@ -22,16 +22,16 @@ function splitEvery(items, limit = 25) {
|
|
|
22
22
|
return batches;
|
|
23
23
|
}
|
|
24
24
|
exports.splitEvery = splitEvery;
|
|
25
|
-
function getAttributeValues(key, attributesToGet) {
|
|
25
|
+
function getAttributeValues(key, { attributesToGet, prefix = ":", } = {}) {
|
|
26
26
|
return (0, fixes_1.marshallWithOptions)((attributesToGet || Object.keys(key)).reduce((acc, keyName) => {
|
|
27
|
-
acc[
|
|
27
|
+
acc[`${prefix}${keyName}`] = key[keyName];
|
|
28
28
|
return acc;
|
|
29
29
|
}, {}));
|
|
30
30
|
}
|
|
31
31
|
exports.getAttributeValues = getAttributeValues;
|
|
32
|
-
function getAttributeNames(key, attributesToGet) {
|
|
32
|
+
function getAttributeNames(key, { attributesToGet, prefix = "#", } = {}) {
|
|
33
33
|
return (attributesToGet || Object.keys(key)).reduce((acc, keyName) => {
|
|
34
|
-
acc[
|
|
34
|
+
acc[`${prefix}${keyName}`] = keyName;
|
|
35
35
|
return acc;
|
|
36
36
|
}, {});
|
|
37
37
|
}
|
|
@@ -42,3 +42,65 @@ function getAttributesFromExpression(expression, prefix = "#") {
|
|
|
42
42
|
?.map((attr) => attr.slice(1)) || []);
|
|
43
43
|
}
|
|
44
44
|
exports.getAttributesFromExpression = getAttributesFromExpression;
|
|
45
|
+
class ExpressionAttributes {
|
|
46
|
+
ExpressionAttributeValues;
|
|
47
|
+
ExpressionAttributeNames;
|
|
48
|
+
nameMapping = {};
|
|
49
|
+
valueMapping = {};
|
|
50
|
+
nameCounter = 0;
|
|
51
|
+
valueCounter = 0;
|
|
52
|
+
constructor(ExpressionAttributeValues = {}, ExpressionAttributeNames = {}) {
|
|
53
|
+
this.ExpressionAttributeValues = ExpressionAttributeValues;
|
|
54
|
+
this.ExpressionAttributeNames = ExpressionAttributeNames;
|
|
55
|
+
}
|
|
56
|
+
appendNames(names) {
|
|
57
|
+
names.forEach((name) => {
|
|
58
|
+
const parts = name.split(".");
|
|
59
|
+
parts.forEach((part) => {
|
|
60
|
+
if (!this.nameMapping[part]) {
|
|
61
|
+
const newName = `#${this.nameCounter++}`;
|
|
62
|
+
this.nameMapping[part] = newName;
|
|
63
|
+
this.ExpressionAttributeNames[newName] = part;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
appendValues(values) {
|
|
69
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
70
|
+
const newValueName = `:${this.valueCounter++}`;
|
|
71
|
+
this.valueMapping[key] = newValueName;
|
|
72
|
+
this.ExpressionAttributeValues[newValueName] = value;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
appendBoth(values) {
|
|
76
|
+
this.appendNames(Object.keys(values));
|
|
77
|
+
this.appendValues(values);
|
|
78
|
+
}
|
|
79
|
+
getAttributes() {
|
|
80
|
+
const marshalled = (0, fixes_1.marshallWithOptions)(this.ExpressionAttributeValues);
|
|
81
|
+
return {
|
|
82
|
+
ExpressionAttributeNames: this.ExpressionAttributeNames,
|
|
83
|
+
...(Object.keys(marshalled).length > 0 && {
|
|
84
|
+
ExpressionAttributeValues: marshalled,
|
|
85
|
+
}),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
getName(attributeName) {
|
|
89
|
+
return attributeName
|
|
90
|
+
.split(".")
|
|
91
|
+
.map((part) => this.nameMapping[part])
|
|
92
|
+
.join(".");
|
|
93
|
+
}
|
|
94
|
+
getValue(attributeName) {
|
|
95
|
+
return this.valueMapping[attributeName];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.ExpressionAttributes = ExpressionAttributes;
|
|
99
|
+
const getItemKey = (item, args) => {
|
|
100
|
+
const { hash, range } = (0, schemas_1.getTableSchema)(args?.TableName);
|
|
101
|
+
return JSON.stringify({
|
|
102
|
+
[hash]: item[hash],
|
|
103
|
+
...(range && { [range]: item[range] }),
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
exports.getItemKey = getItemKey;
|
package/dist/operations/query.js
CHANGED
|
@@ -15,14 +15,18 @@ async function _query(keyCondition, key, args = {}) {
|
|
|
15
15
|
args = (0, lib_1.withFixes)(args);
|
|
16
16
|
return (0, lib_1.getClient)().send(new client_dynamodb_1.QueryCommand({
|
|
17
17
|
KeyConditionExpression: keyCondition,
|
|
18
|
-
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(key,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(key, {
|
|
19
|
+
attributesToGet: [
|
|
20
|
+
...(0, lib_1.getAttributesFromExpression)(keyCondition, ":"),
|
|
21
|
+
...(0, lib_1.getAttributesFromExpression)(args?.FilterExpression || "", ":"),
|
|
22
|
+
],
|
|
23
|
+
}),
|
|
24
|
+
ExpressionAttributeNames: (0, lib_1.getAttributeNames)(key, {
|
|
25
|
+
attributesToGet: [
|
|
26
|
+
...(0, lib_1.getAttributesFromExpression)(keyCondition),
|
|
27
|
+
...(0, lib_1.getAttributesFromExpression)(args?.FilterExpression || ""),
|
|
28
|
+
],
|
|
29
|
+
}),
|
|
26
30
|
...args,
|
|
27
31
|
TableName: args?.TableName || (0, lib_1.getDefaultTable)(),
|
|
28
32
|
}));
|
|
@@ -103,7 +107,7 @@ async function queryAllItems(keyCondition, key, args = {}) {
|
|
|
103
107
|
args = (0, lib_1.withDefaults)(args, "queryAllItems");
|
|
104
108
|
let data = await _query(keyCondition, key, args);
|
|
105
109
|
while (data.LastEvaluatedKey) {
|
|
106
|
-
if (!
|
|
110
|
+
if (!("Limit" in args) || data.Items.length < args?.Limit) {
|
|
107
111
|
let helper = await _query(keyCondition, key, {
|
|
108
112
|
...args,
|
|
109
113
|
ExclusiveStartKey: data.LastEvaluatedKey,
|
|
@@ -53,8 +53,12 @@ async function transactWriteItems(transactItems, args = {}) {
|
|
|
53
53
|
exports.transactWriteItems = transactWriteItems;
|
|
54
54
|
function handleExpressionAttributes(rest, data) {
|
|
55
55
|
return {
|
|
56
|
-
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(data || {},
|
|
57
|
-
|
|
56
|
+
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(data || {}, {
|
|
57
|
+
attributesToGet: (0, lib_1.getAttributesFromExpression)(rest.ConditionExpression || "", ":"),
|
|
58
|
+
}),
|
|
59
|
+
ExpressionAttributeNames: (0, lib_1.getAttributeNames)(data || {}, {
|
|
60
|
+
attributesToGet: (0, lib_1.getAttributesFromExpression)(rest.ConditionExpression || ""),
|
|
61
|
+
}),
|
|
58
62
|
};
|
|
59
63
|
}
|
|
60
64
|
function handleConditionCheck(params, args) {
|
|
@@ -106,7 +110,9 @@ function handleUpdateItem(params, args) {
|
|
|
106
110
|
Key: (0, lib_1.stripKey)(key, { TableName: rest.TableName || args.table }),
|
|
107
111
|
UpdateExpression,
|
|
108
112
|
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(mergedData),
|
|
109
|
-
ExpressionAttributeNames: (0, lib_1.getAttributeNames)({},
|
|
113
|
+
ExpressionAttributeNames: (0, lib_1.getAttributeNames)({}, {
|
|
114
|
+
attributesToGet: (0, lib_1.getAttributesFromExpression)(rest.ConditionExpression || "").concat(Object.keys(populatedData)),
|
|
115
|
+
}),
|
|
110
116
|
...rest,
|
|
111
117
|
TableName: rest.TableName || args.table,
|
|
112
118
|
},
|
|
@@ -12,18 +12,17 @@ async function updateItem(key, data, args) {
|
|
|
12
12
|
const namesInCondition = (0, lib_1.getAttributesFromExpression)(argsWithDefaults?.ConditionExpression || "");
|
|
13
13
|
const attributesToUpdate = Object.keys(data).filter((key) => !valuesInCondition.includes(key));
|
|
14
14
|
const UpdateExpression = "SET " + attributesToUpdate.map((key) => `#${key} = :${key}`).join(", ");
|
|
15
|
+
// @ts-ignore
|
|
15
16
|
return (0, lib_1.getClient)()
|
|
16
17
|
.send(new client_dynamodb_1.UpdateItemCommand({
|
|
17
18
|
Key: (0, lib_1.stripKey)(key, argsWithDefaults),
|
|
18
19
|
UpdateExpression,
|
|
19
|
-
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(data,
|
|
20
|
-
...attributesToUpdate,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
...namesInCondition,
|
|
26
|
-
]),
|
|
20
|
+
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(data, {
|
|
21
|
+
attributesToGet: [...attributesToUpdate, ...valuesInCondition],
|
|
22
|
+
}),
|
|
23
|
+
ExpressionAttributeNames: (0, lib_1.getAttributeNames)(data, {
|
|
24
|
+
attributesToGet: [...attributesToUpdate, ...namesInCondition],
|
|
25
|
+
}),
|
|
27
26
|
...argsWithDefaults,
|
|
28
27
|
TableName: argsWithDefaults?.TableName || (0, lib_1.getDefaultTable)(),
|
|
29
28
|
}))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TransactWriteItemsCommandInput } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { ConditionOperations, CreateOperations, UpdateOperations } from "./operations";
|
|
3
|
+
import { WithoutReferences } from "./references/types";
|
|
4
|
+
import { ConditionOperation, CreateOperation, DeleteOperation, DynamoDBItemKey, ItemWithKey, OnlyKey, UpdateOperation } from "./types";
|
|
5
|
+
export declare class Transaction {
|
|
6
|
+
private tableName;
|
|
7
|
+
private timestamp;
|
|
8
|
+
private operations;
|
|
9
|
+
constructor({ tableName, timestamp, }?: {
|
|
10
|
+
tableName?: string;
|
|
11
|
+
timestamp?: number;
|
|
12
|
+
});
|
|
13
|
+
private getItemKey;
|
|
14
|
+
create<T extends ItemWithKey>(item: WithoutReferences<T>, args?: CreateOperation["args"]): CreateOperations<T>;
|
|
15
|
+
update<T extends DynamoDBItemKey>(item: OnlyKey<T>, args?: UpdateOperation["args"]): UpdateOperations<T>;
|
|
16
|
+
delete(item: DynamoDBItemKey, args?: DeleteOperation["args"]): void;
|
|
17
|
+
addConditionFor<T extends DynamoDBItemKey>(item: T, args?: Partial<ConditionOperation["args"]>): ConditionOperations<T>;
|
|
18
|
+
private handleOperation;
|
|
19
|
+
execute(args?: Partial<Omit<TransactWriteItemsCommandInput, "TransactItems">>): Promise<any>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Transaction = void 0;
|
|
4
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
5
|
+
const __1 = require("..");
|
|
6
|
+
const operations_1 = require("./operations");
|
|
7
|
+
// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html
|
|
8
|
+
const OPERATIONS_LIMIT = 100;
|
|
9
|
+
class Transaction {
|
|
10
|
+
tableName;
|
|
11
|
+
timestamp = Date.now();
|
|
12
|
+
operations = {};
|
|
13
|
+
constructor({ tableName = (0, __1.getDefaultTable)(), timestamp = Date.now(), } = {}) {
|
|
14
|
+
this.tableName = tableName;
|
|
15
|
+
this.timestamp = timestamp;
|
|
16
|
+
}
|
|
17
|
+
getItemKey(item, tableName) {
|
|
18
|
+
return (0, __1.getItemKey)(item, { TableName: tableName || this.tableName });
|
|
19
|
+
}
|
|
20
|
+
create(item, args) {
|
|
21
|
+
const itemKey = this.getItemKey(item, args?.TableName);
|
|
22
|
+
const createOperation = {
|
|
23
|
+
_type: "create",
|
|
24
|
+
item: item,
|
|
25
|
+
args: { TableName: this.tableName, ...args },
|
|
26
|
+
};
|
|
27
|
+
this.operations[itemKey] = createOperation;
|
|
28
|
+
return new operations_1.CreateOperations(createOperation, this);
|
|
29
|
+
}
|
|
30
|
+
update(item, args) {
|
|
31
|
+
const itemKey = this.getItemKey(item, args?.TableName);
|
|
32
|
+
const updateOperation = {
|
|
33
|
+
_type: "update",
|
|
34
|
+
item,
|
|
35
|
+
actions: [{ _type: "set", values: { updatedAt: this.timestamp } }],
|
|
36
|
+
args: { TableName: this.tableName, ...args },
|
|
37
|
+
};
|
|
38
|
+
this.operations[itemKey] = updateOperation;
|
|
39
|
+
return new operations_1.UpdateOperations(updateOperation, this);
|
|
40
|
+
}
|
|
41
|
+
delete(item, args) {
|
|
42
|
+
const itemKey = this.getItemKey(item, args?.TableName);
|
|
43
|
+
this.operations[itemKey] = {
|
|
44
|
+
_type: "delete",
|
|
45
|
+
item,
|
|
46
|
+
args: { TableName: this.tableName, ...args },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
addConditionFor(item, args) {
|
|
50
|
+
return new operations_1.ConditionOperations(this.operations, item, {
|
|
51
|
+
TableName: this.tableName,
|
|
52
|
+
...args,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
handleOperation(operation) {
|
|
56
|
+
switch (operation._type) {
|
|
57
|
+
case "create": {
|
|
58
|
+
const { item, args } = operation;
|
|
59
|
+
return {
|
|
60
|
+
Put: {
|
|
61
|
+
Item: (0, __1.marshallWithOptions)({ createdAt: this.timestamp, ...item }),
|
|
62
|
+
...args,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
case "update": {
|
|
67
|
+
const { item, actions, args } = operation;
|
|
68
|
+
const expressions = {
|
|
69
|
+
add: [],
|
|
70
|
+
delete: [],
|
|
71
|
+
remove: [],
|
|
72
|
+
set: [],
|
|
73
|
+
};
|
|
74
|
+
const { ExpressionAttributeValues, ExpressionAttributeNames, ...otherArgs } = args;
|
|
75
|
+
const attr = new __1.ExpressionAttributes(ExpressionAttributeValues, ExpressionAttributeNames);
|
|
76
|
+
actions.forEach((action) => {
|
|
77
|
+
switch (action._type) {
|
|
78
|
+
case "set":
|
|
79
|
+
attr.appendBoth(action.values);
|
|
80
|
+
expressions.set.push(Object.keys(action.values)
|
|
81
|
+
.map((key) => `${attr.getName(key)} = ${attr.getValue(key)}`)
|
|
82
|
+
.join(", "));
|
|
83
|
+
break;
|
|
84
|
+
case "remove":
|
|
85
|
+
attr.appendNames(action.attributes);
|
|
86
|
+
expressions.remove.push(action.attributes.map((key) => attr.getName(key)).join(", "));
|
|
87
|
+
break;
|
|
88
|
+
case "add":
|
|
89
|
+
attr.appendBoth(action.values);
|
|
90
|
+
expressions.add.push(Object.keys(action.values)
|
|
91
|
+
.map((key) => `${attr.getName(key)} ${attr.getValue(key)}`)
|
|
92
|
+
.join(", "));
|
|
93
|
+
break;
|
|
94
|
+
case "delete":
|
|
95
|
+
attr.appendBoth(action.values);
|
|
96
|
+
expressions.delete.push(Object.keys(action.values)
|
|
97
|
+
.map((key) => `${attr.getName(key)} ${attr.getValue(key)}`)
|
|
98
|
+
.join(", "));
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const joinedExpressions = Object.entries(expressions)
|
|
103
|
+
.filter(([, value]) => value?.length)
|
|
104
|
+
.reduce((acc, [t, v]) => [...acc, `${t.toUpperCase()} ${v.join(", ")}`], [])
|
|
105
|
+
.join(" ");
|
|
106
|
+
return {
|
|
107
|
+
Update: {
|
|
108
|
+
Key: (0, __1.stripKey)(item),
|
|
109
|
+
UpdateExpression: joinedExpressions,
|
|
110
|
+
...attr.getAttributes(),
|
|
111
|
+
...otherArgs,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
case "delete": {
|
|
116
|
+
const { item, args } = operation;
|
|
117
|
+
return { Delete: { Key: (0, __1.stripKey)(item), ...args } };
|
|
118
|
+
}
|
|
119
|
+
case "condition": {
|
|
120
|
+
const { item, args } = operation;
|
|
121
|
+
return { ConditionCheck: { Key: (0, __1.stripKey)(item), ...args } };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async execute(args) {
|
|
126
|
+
const operations = Object.values(this.operations).map((op) => this.handleOperation(op));
|
|
127
|
+
if (operations.length === 0 || operations.length > OPERATIONS_LIMIT) {
|
|
128
|
+
throw new Error("Invalid number of operations");
|
|
129
|
+
}
|
|
130
|
+
const input = {
|
|
131
|
+
TransactItems: operations,
|
|
132
|
+
...args,
|
|
133
|
+
};
|
|
134
|
+
return (0, __1.getClient)()
|
|
135
|
+
.send(new client_dynamodb_1.TransactWriteItemsCommand(input))
|
|
136
|
+
.catch((err) => ({ ...err, args: input }));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.Transaction = Transaction;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Transaction } from ".";
|
|
2
|
+
import { DynamoDBItem } from "../types";
|
|
3
|
+
import { DynamoDBReference } from "./references/types";
|
|
4
|
+
import { ConditionOperation, CreateOperation, DynamoDBItemKey, DynamoDBSet, ItemWithKey, NestedParams, NestedTypedParams, TypedParams, UpdateOperation, WithoutKey } from "./types";
|
|
5
|
+
export declare class CreateOperations<U extends ItemWithKey> {
|
|
6
|
+
private operation;
|
|
7
|
+
private transaction;
|
|
8
|
+
constructor(operation: CreateOperation, transaction: Transaction);
|
|
9
|
+
setReferences(refs: SetReferencesParams<U>): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class UpdateOperations<U extends DynamoDBItem> {
|
|
12
|
+
private operation;
|
|
13
|
+
private transaction;
|
|
14
|
+
constructor(operation: UpdateOperation, transaction: Transaction);
|
|
15
|
+
setReferences(refs: SetReferencesParams<U>): void;
|
|
16
|
+
set(values: WithoutKey<Partial<U>> & NestedParams): this;
|
|
17
|
+
adjustNumber(values: NestedTypedParams<U, number>): this;
|
|
18
|
+
removeAttributes(...attributes: string[]): this;
|
|
19
|
+
addItemsToSet(values: {
|
|
20
|
+
[Key in keyof U as NonNullable<U[Key]> extends DynamoDBSet ? Key : never]?: U[Key] extends Set<infer type> ? Set<type> | type[] : never;
|
|
21
|
+
} & NestedParams<Set<any> | any[]>): this;
|
|
22
|
+
deleteItemsFromSet(values: NestedTypedParams<U, Set<any>>): this;
|
|
23
|
+
onCondition({ expression, values, }: {
|
|
24
|
+
expression: string;
|
|
25
|
+
values: Partial<U> & Record<string, any>;
|
|
26
|
+
}): void;
|
|
27
|
+
}
|
|
28
|
+
export declare class ConditionOperations<U extends DynamoDBItem> {
|
|
29
|
+
private operations;
|
|
30
|
+
private item;
|
|
31
|
+
private args;
|
|
32
|
+
constructor(operations: Transaction["operations"], item: DynamoDBItemKey, args: Partial<ConditionOperation["args"]> & {
|
|
33
|
+
TableName: string;
|
|
34
|
+
});
|
|
35
|
+
matches({ expression, values, }: {
|
|
36
|
+
expression: string;
|
|
37
|
+
values: Partial<U> & Record<string, any>;
|
|
38
|
+
}): void;
|
|
39
|
+
}
|
|
40
|
+
type SetReferencesParams<U extends DynamoDBItem> = TypedParams<U, DynamoDBReference, DynamoDBItemKey> & TypedParams<U, Set<DynamoDBReference>, DynamoDBItemKey[] | Set<DynamoDBItemKey>> & NestedParams<DynamoDBItemKey | DynamoDBItemKey[] | Set<DynamoDBItemKey>>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConditionOperations = exports.UpdateOperations = exports.CreateOperations = void 0;
|
|
4
|
+
const lib_1 = require("../lib");
|
|
5
|
+
const references_1 = require("./references");
|
|
6
|
+
class CreateOperations {
|
|
7
|
+
operation;
|
|
8
|
+
transaction;
|
|
9
|
+
constructor(operation, transaction) {
|
|
10
|
+
this.operation = operation;
|
|
11
|
+
this.transaction = transaction;
|
|
12
|
+
}
|
|
13
|
+
setReferences(refs) {
|
|
14
|
+
Object.entries(arraysToSets(refs)).forEach(([attributeName, ref]) => {
|
|
15
|
+
if (!ref)
|
|
16
|
+
return;
|
|
17
|
+
const refArgs = {
|
|
18
|
+
item: this.operation.item,
|
|
19
|
+
onAttribute: attributeName,
|
|
20
|
+
};
|
|
21
|
+
const refData = ref instanceof Set
|
|
22
|
+
? [...ref].map((references) => (0, references_1.createReference)({ references, ...refArgs }, this.transaction))
|
|
23
|
+
: (0, references_1.createReference)({ references: ref, ...refArgs }, this.transaction);
|
|
24
|
+
const parts = attributeName.split(".");
|
|
25
|
+
parts.reduce((acc, part, index) => {
|
|
26
|
+
if (index === parts.length - 1) {
|
|
27
|
+
acc[part] = refData;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
acc[part] = acc[part] || {};
|
|
31
|
+
return acc[part];
|
|
32
|
+
}
|
|
33
|
+
}, this.operation.item);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.CreateOperations = CreateOperations;
|
|
38
|
+
class UpdateOperations {
|
|
39
|
+
operation;
|
|
40
|
+
transaction;
|
|
41
|
+
constructor(operation, transaction) {
|
|
42
|
+
this.operation = operation;
|
|
43
|
+
this.transaction = transaction;
|
|
44
|
+
}
|
|
45
|
+
setReferences(refs) {
|
|
46
|
+
Object.entries(arraysToSets(refs)).forEach(([attributeName, ref]) => {
|
|
47
|
+
if (!ref)
|
|
48
|
+
return;
|
|
49
|
+
const refArgs = {
|
|
50
|
+
item: this.operation.item,
|
|
51
|
+
onAttribute: attributeName,
|
|
52
|
+
};
|
|
53
|
+
this.operation.actions.push({
|
|
54
|
+
_type: "set",
|
|
55
|
+
values: {
|
|
56
|
+
[attributeName]: ref instanceof Set
|
|
57
|
+
? [...ref].map((references) => (0, references_1.createReference)({ references, ...refArgs }, this.transaction))
|
|
58
|
+
: (0, references_1.createReference)({ references: ref, ...refArgs }, this.transaction),
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
set(values) {
|
|
64
|
+
if (Object.keys(values).length === 0)
|
|
65
|
+
return this;
|
|
66
|
+
this.operation.actions.push({ _type: "set", values });
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
adjustNumber(values) {
|
|
70
|
+
if (Object.keys(values).length === 0)
|
|
71
|
+
return this;
|
|
72
|
+
this.operation.actions.push({ _type: "add", values });
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
removeAttributes(...attributes) {
|
|
76
|
+
if (attributes.length === 0)
|
|
77
|
+
return this;
|
|
78
|
+
this.operation.actions.push({ _type: "remove", attributes });
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
addItemsToSet(values) {
|
|
82
|
+
if (Object.keys(values).length === 0)
|
|
83
|
+
return this;
|
|
84
|
+
this.operation.actions.push({
|
|
85
|
+
_type: "add",
|
|
86
|
+
values: arraysToSets(values),
|
|
87
|
+
});
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
deleteItemsFromSet(values) {
|
|
91
|
+
if (Object.keys(values).length === 0)
|
|
92
|
+
return this;
|
|
93
|
+
this.operation.actions.push({
|
|
94
|
+
_type: "delete",
|
|
95
|
+
values: arraysToSets(values),
|
|
96
|
+
});
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
onCondition({ expression, values, }) {
|
|
100
|
+
this.operation.args = {
|
|
101
|
+
...this.operation.args,
|
|
102
|
+
ConditionExpression: expression,
|
|
103
|
+
ExpressionAttributeNames: (0, lib_1.getAttributeNames)(values),
|
|
104
|
+
ExpressionAttributeValues: Object.keys(values).reduce((acc, keyName) => {
|
|
105
|
+
acc[`:${keyName}`] = values[keyName];
|
|
106
|
+
return acc;
|
|
107
|
+
}, {}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.UpdateOperations = UpdateOperations;
|
|
112
|
+
class ConditionOperations {
|
|
113
|
+
operations;
|
|
114
|
+
item;
|
|
115
|
+
args;
|
|
116
|
+
constructor(operations, item, args) {
|
|
117
|
+
this.operations = operations;
|
|
118
|
+
this.item = item;
|
|
119
|
+
this.args = args;
|
|
120
|
+
}
|
|
121
|
+
matches({ expression, values, }) {
|
|
122
|
+
if (Object.keys(values).length === 0) {
|
|
123
|
+
throw new Error("[@moicky/dynamodb]: No values in ConditionCheck provided");
|
|
124
|
+
}
|
|
125
|
+
const itemKey = (0, lib_1.getItemKey)(this.item, this.args);
|
|
126
|
+
this.operations[itemKey] = {
|
|
127
|
+
_type: "condition",
|
|
128
|
+
item: this.item,
|
|
129
|
+
args: {
|
|
130
|
+
ConditionExpression: expression,
|
|
131
|
+
ExpressionAttributeNames: (0, lib_1.getAttributeNames)(values),
|
|
132
|
+
ExpressionAttributeValues: (0, lib_1.getAttributeValues)(values),
|
|
133
|
+
...this.args,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.ConditionOperations = ConditionOperations;
|
|
139
|
+
const arraysToSets = (values) => {
|
|
140
|
+
return Object.entries(values).reduce((acc, [key, value]) => ({
|
|
141
|
+
...acc,
|
|
142
|
+
[key]: value instanceof Set
|
|
143
|
+
? value
|
|
144
|
+
: Array.isArray(value)
|
|
145
|
+
? new Set(value)
|
|
146
|
+
: value,
|
|
147
|
+
}), {});
|
|
148
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Transaction } from "..";
|
|
2
|
+
import { DynamoDBItem } from "../../types";
|
|
3
|
+
import { DynamoDBItemKey, ItemWithKey } from "../types";
|
|
4
|
+
import { DynamoDBReference, ReferenceMetadata, ResolvedItem } from "./types";
|
|
5
|
+
export declare const createReference: (ref: Pick<ReferenceMetadata, "item" | "references" | "onAttribute">, transaction: Transaction) => DynamoDBReference;
|
|
6
|
+
export declare const createCustomReference: (baseItem: DynamoDBItemKey, references: DynamoDBItemKey, onAttribute?: string) => Promise<{
|
|
7
|
+
PK: "dynamodb:reference";
|
|
8
|
+
SK: `${string}-${string}-${string}-${string}-${string}`;
|
|
9
|
+
item: {
|
|
10
|
+
SK: string | number;
|
|
11
|
+
PK: string;
|
|
12
|
+
};
|
|
13
|
+
references: {
|
|
14
|
+
SK: string | number;
|
|
15
|
+
PK: string;
|
|
16
|
+
};
|
|
17
|
+
onAttribute: string;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const resolveReferences: <T extends DynamoDBItem>(item: T) => Promise<ResolvedItem<T>>;
|
|
20
|
+
export declare const getDependencies: (item: ItemWithKey) => Promise<ReferenceMetadata[]>;
|
|
21
|
+
export declare const getResolvedDependencies: <T extends ItemWithKey = ItemWithKey>(item: ItemWithKey) => Promise<T[]>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getResolvedDependencies = exports.getDependencies = exports.resolveReferences = exports.createCustomReference = exports.createReference = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const operations_1 = require("../../operations");
|
|
6
|
+
const createReference = (ref, transaction) => {
|
|
7
|
+
const { item, references, onAttribute } = ref;
|
|
8
|
+
const referenceKey = {
|
|
9
|
+
PK: references.PK,
|
|
10
|
+
...(references.SK && { SK: references.SK }),
|
|
11
|
+
};
|
|
12
|
+
const referenceItem = {
|
|
13
|
+
PK: "dynamodb:reference",
|
|
14
|
+
SK: (0, crypto_1.randomUUID)(),
|
|
15
|
+
item: {
|
|
16
|
+
PK: item.PK,
|
|
17
|
+
...(item.SK && { SK: item.SK }),
|
|
18
|
+
},
|
|
19
|
+
references: referenceKey,
|
|
20
|
+
onAttribute,
|
|
21
|
+
};
|
|
22
|
+
transaction.create(referenceItem);
|
|
23
|
+
return {
|
|
24
|
+
_type: "dynamodb:reference",
|
|
25
|
+
_target: referenceKey,
|
|
26
|
+
_refId: referenceItem.SK,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
exports.createReference = createReference;
|
|
30
|
+
const itemToStringKey = (item) => `${item.PK}#|#${item.SK}`;
|
|
31
|
+
const getRefsToResolve = (item) => {
|
|
32
|
+
const refs = [];
|
|
33
|
+
if (!item)
|
|
34
|
+
return refs;
|
|
35
|
+
if (typeof item !== "object")
|
|
36
|
+
return refs;
|
|
37
|
+
if (item?._type === "dynamodb:reference")
|
|
38
|
+
return [item?._target];
|
|
39
|
+
for (const value of Object.values(item)) {
|
|
40
|
+
if (typeof value === "object") {
|
|
41
|
+
if (value instanceof Set || Array.isArray(value)) {
|
|
42
|
+
refs.push(...[...value].map((v) => getRefsToResolve(v)).flat());
|
|
43
|
+
}
|
|
44
|
+
else if (value?._type === "dynamodb:reference") {
|
|
45
|
+
refs.push(value?._target);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
refs.push(...getRefsToResolve(value));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return refs;
|
|
53
|
+
};
|
|
54
|
+
const injectRefs = (item, refs) => {
|
|
55
|
+
if (!item)
|
|
56
|
+
return item;
|
|
57
|
+
if (typeof item !== "object")
|
|
58
|
+
return item;
|
|
59
|
+
if (item?._type === "dynamodb:reference") {
|
|
60
|
+
return refs[itemToStringKey(item._target)];
|
|
61
|
+
}
|
|
62
|
+
for (const [key, value] of Object.entries(item)) {
|
|
63
|
+
if (typeof value === "object") {
|
|
64
|
+
if (value instanceof Set || Array.isArray(value)) {
|
|
65
|
+
item[key] = new Set([...value].map((v) => injectRefs(v, refs)));
|
|
66
|
+
}
|
|
67
|
+
else if (value?._type === "dynamodb:reference") {
|
|
68
|
+
item[key] = refs[itemToStringKey(value._target)];
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
item[key] = injectRefs(value, refs);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return item;
|
|
76
|
+
};
|
|
77
|
+
const createCustomReference = async (baseItem, references, onAttribute) => (0, operations_1.putItem)({
|
|
78
|
+
PK: "dynamodb:reference",
|
|
79
|
+
SK: (0, crypto_1.randomUUID)(),
|
|
80
|
+
item: {
|
|
81
|
+
PK: baseItem.PK,
|
|
82
|
+
...(baseItem.SK && { SK: baseItem.SK }),
|
|
83
|
+
},
|
|
84
|
+
references: {
|
|
85
|
+
PK: references.PK,
|
|
86
|
+
...(references.SK && { SK: references.SK }),
|
|
87
|
+
},
|
|
88
|
+
onAttribute: onAttribute || "",
|
|
89
|
+
}, { ReturnValues: "ALL_NEW" });
|
|
90
|
+
exports.createCustomReference = createCustomReference;
|
|
91
|
+
const resolveReferences = async (item) => {
|
|
92
|
+
const resolvedItem = structuredClone(item);
|
|
93
|
+
let refs = getRefsToResolve(item);
|
|
94
|
+
if (!refs.length)
|
|
95
|
+
return item;
|
|
96
|
+
const fetchedRefs = await (0, operations_1.getItems)(refs).then((items) => items.reduce((acc, item) => ({ ...acc, [itemToStringKey(item)]: item }), {}));
|
|
97
|
+
return injectRefs(resolvedItem, fetchedRefs);
|
|
98
|
+
};
|
|
99
|
+
exports.resolveReferences = resolveReferences;
|
|
100
|
+
const getDependencies = async (item) => (0, operations_1.queryAllItems)("#PK = :PK", {
|
|
101
|
+
PK: "dynamodb:reference",
|
|
102
|
+
references: {
|
|
103
|
+
PK: item.PK,
|
|
104
|
+
...(item.SK && { SK: item.SK }),
|
|
105
|
+
},
|
|
106
|
+
}, { FilterExpression: "#references = :references" });
|
|
107
|
+
exports.getDependencies = getDependencies;
|
|
108
|
+
const getResolvedDependencies = async (item) => (0, exports.getDependencies)(item).then((refs) => (0, operations_1.getItems)(refs
|
|
109
|
+
.map(({ item }) => item)
|
|
110
|
+
.filter((item, index, array) => array.findIndex((i) => i.SK === item.SK) === index)).then((items) => items.filter(Boolean)));
|
|
111
|
+
exports.getResolvedDependencies = getResolvedDependencies;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DynamoDBItem } from "../../types";
|
|
2
|
+
import { DynamoDBItemKey, ItemWithKey } from "../types";
|
|
3
|
+
export type DynamoDBReference<T extends ItemWithKey = ItemWithKey> = T extends any[] ? never : {
|
|
4
|
+
_type: "dynamodb:reference";
|
|
5
|
+
_target: T;
|
|
6
|
+
_refId: ReferenceMetadata["SK"];
|
|
7
|
+
};
|
|
8
|
+
export type ResolvedItem<T extends DynamoDBItem> = {
|
|
9
|
+
[Key in keyof T]: NonNullable<T[Key]> extends DynamoDBReference ? T[Key]["_target"] | undefined : NonNullable<T[Key]> extends Set<DynamoDBReference<infer T>> ? Set<T | undefined> : T[Key] extends object ? ResolvedItem<T[Key]> : T[Key];
|
|
10
|
+
};
|
|
11
|
+
export type WithoutReferences<T extends DynamoDBItem> = {
|
|
12
|
+
[Key in keyof T as NonNullable<T[Key]> extends DynamoDBReference | Set<DynamoDBReference> ? never : Key]: T[Key] extends object ? WithoutReferences<T[Key]> : T[Key];
|
|
13
|
+
};
|
|
14
|
+
export type ReferenceTo<T extends ItemWithKey> = T extends any[] ? void : DynamoDBReference<T>;
|
|
15
|
+
export type ReferenceMetadata = {
|
|
16
|
+
PK: "dynamodb:reference";
|
|
17
|
+
SK: string;
|
|
18
|
+
item: DynamoDBItemKey;
|
|
19
|
+
references: DynamoDBItemKey;
|
|
20
|
+
onAttribute: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ConditionCheck, Delete, Put, Update } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBItem } from "../types";
|
|
3
|
+
export type DynamoDBItemKey = {
|
|
4
|
+
PK: string;
|
|
5
|
+
SK?: string | number | undefined;
|
|
6
|
+
};
|
|
7
|
+
export type ItemWithKey = DynamoDBItem & DynamoDBItemKey;
|
|
8
|
+
export type WithoutKey<T> = Omit<T, keyof DynamoDBItemKey>;
|
|
9
|
+
export type OnlyKey<T extends DynamoDBItemKey> = Pick<T, keyof DynamoDBItemKey>;
|
|
10
|
+
export type Prettify<T> = {
|
|
11
|
+
[key in keyof T]: T[key];
|
|
12
|
+
} & {};
|
|
13
|
+
export type CreateOperation = {
|
|
14
|
+
_type: "create";
|
|
15
|
+
item: ItemWithKey;
|
|
16
|
+
args?: Omit<Put, "Item">;
|
|
17
|
+
};
|
|
18
|
+
export type UpdateOperation = {
|
|
19
|
+
_type: "update";
|
|
20
|
+
item: DynamoDBItemKey;
|
|
21
|
+
actions: Array<UpdateAction>;
|
|
22
|
+
args?: Omit<Update, "Key" | "UpdateExpression">;
|
|
23
|
+
};
|
|
24
|
+
export type DeleteOperation = {
|
|
25
|
+
_type: "delete";
|
|
26
|
+
item: DynamoDBItemKey;
|
|
27
|
+
args?: Omit<Delete, "Key">;
|
|
28
|
+
};
|
|
29
|
+
export type ConditionOperation = {
|
|
30
|
+
_type: "condition";
|
|
31
|
+
item: DynamoDBItemKey;
|
|
32
|
+
args?: Omit<ConditionCheck, "Key">;
|
|
33
|
+
};
|
|
34
|
+
export type UpdateAction = {
|
|
35
|
+
_type: "set";
|
|
36
|
+
values: Record<string, any>;
|
|
37
|
+
} | {
|
|
38
|
+
_type: "remove";
|
|
39
|
+
attributes: string[];
|
|
40
|
+
} | {
|
|
41
|
+
_type: "add";
|
|
42
|
+
values: Record<string, number | any[]>;
|
|
43
|
+
} | {
|
|
44
|
+
_type: "delete";
|
|
45
|
+
values: Record<string, any[]>;
|
|
46
|
+
};
|
|
47
|
+
export type ItemOperation = CreateOperation | UpdateOperation | DeleteOperation | ConditionOperation;
|
|
48
|
+
export type TypedParams<T extends DynamoDBItem, ValueType, ParamType = ValueType> = {
|
|
49
|
+
[Key in keyof T as NonNullable<T[Key]> extends ValueType ? Key : never]?: ParamType;
|
|
50
|
+
};
|
|
51
|
+
export type NestedParams<T = any> = Record<`${string}.${string}`, T>;
|
|
52
|
+
export type NestedTypedParams<T extends DynamoDBItem, ValueType, ParamType = ValueType> = TypedParams<T, ValueType, ParamType> & NestedParams<ParamType>;
|
|
53
|
+
export type DynamoDBSetMember = number | string | undefined;
|
|
54
|
+
export type DynamoDBSet = Set<DynamoDBSetMember>;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -452,7 +452,7 @@ const result = await client
|
|
|
452
452
|
.then((result) => unmarshall(result.Attributes));
|
|
453
453
|
|
|
454
454
|
// With helpers
|
|
455
|
-
import { updateItem } from "@
|
|
455
|
+
import { updateItem } from "@moicky/dynamodb";
|
|
456
456
|
|
|
457
457
|
const result = await updateItem(
|
|
458
458
|
{ PK: "User/1", SK: "Book/1" },
|