@openstax/ts-utils 1.27.1 → 1.27.3
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/cjs/middleware/lambdaCorsResponseMiddleware.js +3 -1
- package/dist/cjs/services/accountsGateway/index.js +5 -4
- package/dist/cjs/services/apiGateway/index.d.ts +9 -10
- package/dist/cjs/services/documentStore/unversioned/dynamodb.d.ts +2 -0
- package/dist/cjs/services/documentStore/unversioned/dynamodb.js +145 -143
- package/dist/cjs/services/documentStore/versioned/dynamodb.d.ts +2 -0
- package/dist/cjs/services/documentStore/versioned/dynamodb.js +125 -123
- package/dist/cjs/services/fileServer/s3FileServer.d.ts +1 -1
- package/dist/cjs/services/fileServer/s3FileServer.js +5 -2
- package/dist/cjs/services/launchParams/verifier.js +3 -1
- package/dist/cjs/services/searchProvider/index.d.ts +4 -0
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/esm/middleware/lambdaCorsResponseMiddleware.js +3 -1
- package/dist/esm/services/accountsGateway/index.js +5 -4
- package/dist/esm/services/apiGateway/index.d.ts +9 -10
- package/dist/esm/services/documentStore/unversioned/dynamodb.d.ts +2 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.js +145 -143
- package/dist/esm/services/documentStore/versioned/dynamodb.d.ts +2 -0
- package/dist/esm/services/documentStore/versioned/dynamodb.js +125 -123
- package/dist/esm/services/fileServer/s3FileServer.d.ts +1 -1
- package/dist/esm/services/fileServer/s3FileServer.js +5 -2
- package/dist/esm/services/launchParams/verifier.js +3 -1
- package/dist/esm/services/searchProvider/index.d.ts +4 -0
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createLambdaCorsResponseMiddleware = void 0;
|
|
4
4
|
const resolveConfigValue_1 = require("../config/resolveConfigValue");
|
|
5
|
+
const helpers_1 = require("../misc/helpers");
|
|
5
6
|
const routing_1 = require("../routing");
|
|
6
7
|
/**
|
|
7
8
|
* Creates response middleware that adds CORS headers to responses from approved hosts.
|
|
@@ -14,8 +15,9 @@ const routing_1 = require("../routing");
|
|
|
14
15
|
* }),
|
|
15
16
|
*/
|
|
16
17
|
const createLambdaCorsResponseMiddleware = (config) => () => (responsePromise, { request }) => {
|
|
18
|
+
const getAllowedHostRegex = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.corsAllowedHostRegex));
|
|
17
19
|
const cors = async () => {
|
|
18
|
-
const allowedHost = await (
|
|
20
|
+
const allowedHost = await getAllowedHostRegex();
|
|
19
21
|
if (request.headers.origin && request.headers.origin !== 'null' && new URL(request.headers.origin).hostname.match(new RegExp(allowedHost))) {
|
|
20
22
|
return {
|
|
21
23
|
'Access-Control-Allow-Origin': request.headers.origin,
|
|
@@ -8,6 +8,7 @@ const lodash_1 = require("lodash");
|
|
|
8
8
|
const query_string_1 = __importDefault(require("query-string"));
|
|
9
9
|
const config_1 = require("../../config");
|
|
10
10
|
const guards_1 = require("../../guards");
|
|
11
|
+
const helpers_1 = require("../../misc/helpers");
|
|
11
12
|
const routing_1 = require("../../routing");
|
|
12
13
|
const logger_1 = require("../logger");
|
|
13
14
|
class ApiError extends Error {
|
|
@@ -18,15 +19,15 @@ class ApiError extends Error {
|
|
|
18
19
|
}
|
|
19
20
|
const accountsGateway = (initializer) => (configProvider) => {
|
|
20
21
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'accounts')];
|
|
21
|
-
const accountsBase = (0, config_1.resolveConfigValue)(config.accountsBase);
|
|
22
|
-
const accountsAuthToken = (0, config_1.resolveConfigValue)(config.accountsAuthToken);
|
|
22
|
+
const accountsBase = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.accountsBase));
|
|
23
|
+
const accountsAuthToken = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.accountsAuthToken));
|
|
23
24
|
return ({ logger }) => {
|
|
24
25
|
const request = async (method, path, options, statuses = [200, 201]) => {
|
|
25
|
-
const host = (await accountsBase).replace(/\/+$/, '');
|
|
26
|
+
const host = (await accountsBase()).replace(/\/+$/, '');
|
|
26
27
|
const url = `${host}/api/${path}`;
|
|
27
28
|
const config = {
|
|
28
29
|
headers: {
|
|
29
|
-
Authorization: `Bearer ${options.token || await accountsAuthToken}`,
|
|
30
|
+
Authorization: `Bearer ${options.token || await accountsAuthToken()}`,
|
|
30
31
|
},
|
|
31
32
|
method,
|
|
32
33
|
};
|
|
@@ -4,9 +4,9 @@ import { ConfigForFetch, GenericFetch, Response } from '../../fetch';
|
|
|
4
4
|
import { AnyRoute, ApiResponse, OutputForRoute, ParamsForRoute, PayloadForRoute, QueryParams } from '../../routing';
|
|
5
5
|
import { UnwrapPromise } from '../../types';
|
|
6
6
|
import { Logger } from '../logger';
|
|
7
|
-
declare type TResponsePayload<R> = R extends ApiResponse<any, infer P> ? P : never;
|
|
8
|
-
declare type TResponseStatus<R> = R extends ApiResponse<infer S, any> ? S : never;
|
|
9
|
-
declare type RouteClient<R> = {
|
|
7
|
+
export declare type TResponsePayload<R> = R extends ApiResponse<any, infer P> ? P : never;
|
|
8
|
+
export declare type TResponseStatus<R> = R extends ApiResponse<infer S, any> ? S : never;
|
|
9
|
+
export declare type RouteClient<R> = {
|
|
10
10
|
(config: {
|
|
11
11
|
fetchConfig?: any;
|
|
12
12
|
query?: QueryParams;
|
|
@@ -21,25 +21,25 @@ declare type RouteClient<R> = {
|
|
|
21
21
|
params: ParamsForRoute<R>;
|
|
22
22
|
})) => Promise<string>;
|
|
23
23
|
};
|
|
24
|
-
interface AcceptStatus<Ro> {
|
|
24
|
+
export interface AcceptStatus<Ro> {
|
|
25
25
|
<S extends TResponseStatus<Ro>[]>(...args: S): Promise<ApiClientResponse<Extract<Ro, Record<'statusCode', S[number]>>>>;
|
|
26
26
|
<S extends number[]>(...args: S): Promise<ApiClientResponse<any>>;
|
|
27
27
|
}
|
|
28
|
-
declare type UnsafeApiClientResponse<Ro> = {
|
|
28
|
+
export declare type UnsafeApiClientResponse<Ro> = {
|
|
29
29
|
headers: Headers;
|
|
30
30
|
load: () => Promise<any>;
|
|
31
31
|
status: number;
|
|
32
32
|
acceptStatus: AcceptStatus<Ro>;
|
|
33
33
|
};
|
|
34
|
-
declare type ApiClientResponse<Ro> = Ro extends any ? {
|
|
34
|
+
export declare type ApiClientResponse<Ro> = Ro extends any ? {
|
|
35
35
|
headers: Headers;
|
|
36
36
|
status: TResponseStatus<Ro>;
|
|
37
37
|
load: () => Promise<TResponsePayload<Ro>>;
|
|
38
38
|
} : never;
|
|
39
|
-
declare type MapRoutesToClient<Ru> = [Ru] extends [AnyRoute<Ru>] ? {
|
|
39
|
+
export declare type MapRoutesToClient<Ru> = [Ru] extends [AnyRoute<Ru>] ? {
|
|
40
40
|
[N in Ru['name']]: RouteClient<Extract<Ru, Record<'name', N>>>;
|
|
41
41
|
} : never;
|
|
42
|
-
declare type MapRoutesToConfig<Ru> = [Ru] extends [AnyRoute<Ru>] ? {
|
|
42
|
+
export declare type MapRoutesToConfig<Ru> = [Ru] extends [AnyRoute<Ru>] ? {
|
|
43
43
|
[N in Ru['name']]: {
|
|
44
44
|
path: string;
|
|
45
45
|
method: string;
|
|
@@ -47,7 +47,7 @@ declare type MapRoutesToConfig<Ru> = [Ru] extends [AnyRoute<Ru>] ? {
|
|
|
47
47
|
} : never;
|
|
48
48
|
/** Pulls the content out of a response based on the content type */
|
|
49
49
|
export declare const loadResponse: (response: Response) => () => Promise<any>;
|
|
50
|
-
interface MakeApiGateway<F> {
|
|
50
|
+
export interface MakeApiGateway<F> {
|
|
51
51
|
<Ru>(config: ConfigProviderForConfig<{
|
|
52
52
|
apiBase: string;
|
|
53
53
|
}>, routes: MapRoutesToConfig<Ru>, app?: {
|
|
@@ -61,4 +61,3 @@ interface MakeApiGateway<F> {
|
|
|
61
61
|
export declare const createApiGateway: <F extends GenericFetch<import("../../fetch").FetchConfig, Response>>(initializer: {
|
|
62
62
|
fetch: F;
|
|
63
63
|
}) => MakeApiGateway<F>;
|
|
64
|
-
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { DynamoDB } from '@aws-sdk/client-dynamodb';
|
|
1
2
|
import { Config, TDocument } from '..';
|
|
2
3
|
import { ConfigProviderForConfig } from '../../../config';
|
|
3
4
|
interface Initializer<C> {
|
|
4
5
|
configSpace?: C;
|
|
6
|
+
dynamoClient?: DynamoDB;
|
|
5
7
|
}
|
|
6
8
|
export declare const dynamoUnversionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends TDocument<T>>() => (configProvider: { [key in C]: {
|
|
7
9
|
tableName: import("../../../config").ConfigValueProvider<string>;
|
|
@@ -7,158 +7,160 @@ const config_1 = require("../../../config");
|
|
|
7
7
|
const errors_1 = require("../../../errors");
|
|
8
8
|
const guards_1 = require("../../../guards");
|
|
9
9
|
const dynamoEncoding_1 = require("../dynamoEncoding");
|
|
10
|
-
const
|
|
11
|
-
const dynamoUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey, options) => {
|
|
10
|
+
const dynamoUnversionedDocumentStore = (initializer) => {
|
|
12
11
|
const init = (0, guards_1.ifDefined)(initializer, {});
|
|
13
|
-
const
|
|
14
|
-
return {
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const dynamodb = (0, __1.once)(() => { var _a; return (_a = init.dynamoClient) !== null && _a !== void 0 ? _a : new client_dynamodb_1.DynamoDB({ apiVersion: '2012-08-10' }); });
|
|
13
|
+
return () => (configProvider) => (_, hashKey, options) => {
|
|
14
|
+
const tableName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(configProvider[(0, guards_1.ifDefined)(init.configSpace, 'dynamodb')].tableName));
|
|
15
|
+
return {
|
|
16
|
+
loadAllDocumentsTheBadWay: async () => {
|
|
17
|
+
const loadAllResults = async (ExclusiveStartKey) => {
|
|
18
|
+
var _a, _b;
|
|
19
|
+
const cmd = new client_dynamodb_1.ScanCommand({ TableName: await tableName(), ExclusiveStartKey });
|
|
20
|
+
const result = await dynamodb().send(cmd);
|
|
21
|
+
const resultItems = (_b = (_a = result.Items) === null || _a === void 0 ? void 0 : _a.map((item) => (0, dynamoEncoding_1.decodeDynamoDocument)(item))) !== null && _b !== void 0 ? _b : [];
|
|
22
|
+
if (result.LastEvaluatedKey) {
|
|
23
|
+
return [...resultItems, ...await loadAllResults(result.LastEvaluatedKey)];
|
|
24
|
+
}
|
|
25
|
+
return resultItems;
|
|
26
|
+
};
|
|
27
|
+
return loadAllResults();
|
|
28
|
+
},
|
|
29
|
+
/*
|
|
30
|
+
* requires that a global secondary index exist on the table
|
|
31
|
+
*/
|
|
32
|
+
getItemsByField: async (key, value, pageKey) => {
|
|
17
33
|
var _a, _b;
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const ExclusiveStartKey = pageKey
|
|
34
|
-
? JSON.parse(Buffer.from(pageKey, 'base64').toString('utf-8'))
|
|
35
|
-
: undefined;
|
|
36
|
-
const table = await tableName();
|
|
37
|
-
const cmd = new client_dynamodb_1.QueryCommand({
|
|
38
|
-
TableName: table,
|
|
39
|
-
IndexName: key.toString(),
|
|
40
|
-
ExclusiveStartKey,
|
|
41
|
-
KeyConditionExpression: '#hk = :hkv',
|
|
42
|
-
ExpressionAttributeValues: {
|
|
43
|
-
':hkv': (0, dynamoEncoding_1.encodeDynamoAttribute)(value),
|
|
44
|
-
},
|
|
45
|
-
ExpressionAttributeNames: {
|
|
46
|
-
'#hk': key.toString(),
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
const response = await dynamodb().send(cmd);
|
|
50
|
-
const items = (_b = (_a = response.Items) === null || _a === void 0 ? void 0 : _a.map((item) => (0, dynamoEncoding_1.decodeDynamoDocument)(item))) !== null && _b !== void 0 ? _b : [];
|
|
51
|
-
const nextPageToken = response.LastEvaluatedKey;
|
|
52
|
-
return {
|
|
53
|
-
items,
|
|
54
|
-
nextPageToken: nextPageToken
|
|
55
|
-
? Buffer.from(JSON.stringify(nextPageToken)).toString('base64')
|
|
56
|
-
: undefined,
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
batchGetItem: async (ids) => {
|
|
60
|
-
const table = await tableName();
|
|
61
|
-
const key = hashKey.toString();
|
|
62
|
-
const getBatches = async (requestItems) => {
|
|
63
|
-
const cmd = new client_dynamodb_1.BatchGetItemCommand({
|
|
64
|
-
RequestItems: requestItems !== null && requestItems !== void 0 ? requestItems : { [table]: { Keys: ids.map((id) => ({ [key]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) })) } },
|
|
34
|
+
const ExclusiveStartKey = pageKey
|
|
35
|
+
? JSON.parse(Buffer.from(pageKey, 'base64').toString('utf-8'))
|
|
36
|
+
: undefined;
|
|
37
|
+
const table = await tableName();
|
|
38
|
+
const cmd = new client_dynamodb_1.QueryCommand({
|
|
39
|
+
TableName: table,
|
|
40
|
+
IndexName: key.toString(),
|
|
41
|
+
ExclusiveStartKey,
|
|
42
|
+
KeyConditionExpression: '#hk = :hkv',
|
|
43
|
+
ExpressionAttributeValues: {
|
|
44
|
+
':hkv': (0, dynamoEncoding_1.encodeDynamoAttribute)(value),
|
|
45
|
+
},
|
|
46
|
+
ExpressionAttributeNames: {
|
|
47
|
+
'#hk': key.toString(),
|
|
48
|
+
},
|
|
65
49
|
});
|
|
66
50
|
const response = await dynamodb().send(cmd);
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
51
|
+
const items = (_b = (_a = response.Items) === null || _a === void 0 ? void 0 : _a.map((item) => (0, dynamoEncoding_1.decodeDynamoDocument)(item))) !== null && _b !== void 0 ? _b : [];
|
|
52
|
+
const nextPageToken = response.LastEvaluatedKey;
|
|
53
|
+
return {
|
|
54
|
+
items,
|
|
55
|
+
nextPageToken: nextPageToken
|
|
56
|
+
? Buffer.from(JSON.stringify(nextPageToken)).toString('base64')
|
|
57
|
+
: undefined,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
batchGetItem: async (ids) => {
|
|
61
|
+
const table = await tableName();
|
|
62
|
+
const key = hashKey.toString();
|
|
63
|
+
const getBatches = async (requestItems) => {
|
|
64
|
+
const cmd = new client_dynamodb_1.BatchGetItemCommand({
|
|
65
|
+
RequestItems: requestItems !== null && requestItems !== void 0 ? requestItems : { [table]: { Keys: ids.map((id) => ({ [key]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) })) } },
|
|
66
|
+
});
|
|
67
|
+
const response = await dynamodb().send(cmd);
|
|
68
|
+
const currentResponses = response.Responses ?
|
|
69
|
+
response.Responses[table].map(response => (0, dynamoEncoding_1.decodeDynamoDocument)(response)) : [];
|
|
70
|
+
return currentResponses.concat(response.UnprocessedKeys ? await getBatches(response.UnprocessedKeys) : []);
|
|
71
|
+
};
|
|
72
|
+
return getBatches();
|
|
73
|
+
},
|
|
74
|
+
getItem: async (id) => {
|
|
75
|
+
const cmd = new client_dynamodb_1.GetItemCommand({
|
|
76
|
+
Key: { [hashKey.toString()]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) },
|
|
77
|
+
TableName: await tableName(),
|
|
78
|
+
});
|
|
79
|
+
return dynamodb().send(cmd).then(result => result.Item ? (0, dynamoEncoding_1.decodeDynamoDocument)(result.Item) : undefined);
|
|
80
|
+
},
|
|
81
|
+
/* atomically increments the given item attribute by 1 */
|
|
82
|
+
incrementItemAttribute: async (id, attribute) => {
|
|
83
|
+
const key = hashKey.toString();
|
|
84
|
+
const field = attribute.toString();
|
|
85
|
+
const cmd = new client_dynamodb_1.UpdateItemCommand({
|
|
86
|
+
Key: { [key]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) },
|
|
87
|
+
TableName: await tableName(),
|
|
88
|
+
UpdateExpression: 'ADD #f :one',
|
|
89
|
+
ConditionExpression: 'attribute_exists(#k)',
|
|
90
|
+
ExpressionAttributeNames: { '#k': hashKey.toString(), '#f': field },
|
|
91
|
+
ExpressionAttributeValues: { ':one': { N: '1' } },
|
|
92
|
+
ReturnValues: 'ALL_NEW',
|
|
93
|
+
});
|
|
94
|
+
return dynamodb().send(cmd).then(async (item) => {
|
|
95
|
+
var _a, _b, _c;
|
|
96
|
+
const result = (_b = (_a = item.Attributes) === null || _a === void 0 ? void 0 : _a[field]) === null || _b === void 0 ? void 0 : _b['N'];
|
|
97
|
+
if (!item.Attributes) {
|
|
98
|
+
throw new errors_1.NotFoundError(`Item with ${key} "${id}" does not exist`);
|
|
99
|
+
}
|
|
100
|
+
if (!result) {
|
|
101
|
+
throw new errors_1.NotFoundError(`Item with ${key} "${id}" did not produce field "${field}"`);
|
|
102
|
+
}
|
|
103
|
+
const updatedDoc = (0, dynamoEncoding_1.decodeDynamoDocument)(item.Attributes);
|
|
104
|
+
await ((_c = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _c === void 0 ? void 0 : _c.call(options, updatedDoc));
|
|
105
|
+
return parseFloat(result);
|
|
106
|
+
}).catch((error) => {
|
|
107
|
+
throw error.name === 'ConditionalCheckFailedException' ?
|
|
108
|
+
new errors_1.NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
/* replaces only specified attributes with the given data */
|
|
112
|
+
patchItem: async (item) => {
|
|
113
|
+
const id = item[hashKey];
|
|
114
|
+
const key = hashKey.toString();
|
|
115
|
+
if (!id) {
|
|
116
|
+
throw new Error(`Key attribute "${key}" is required for patchItem`);
|
|
98
117
|
}
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
const entries = Object.entries(item).filter(([field]) => field !== key);
|
|
119
|
+
if (entries.length === 0) {
|
|
120
|
+
throw new Error('No attributes to update');
|
|
101
121
|
}
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
ExpressionAttributeNames: expressionAttributeNames,
|
|
135
|
-
ExpressionAttributeValues: expressionAttributeValues,
|
|
136
|
-
ReturnValues: 'ALL_NEW',
|
|
137
|
-
});
|
|
138
|
-
return dynamodb().send(cmd).then(async (item) => {
|
|
122
|
+
const updates = [];
|
|
123
|
+
const expressionAttributeNames = { '#k': key };
|
|
124
|
+
const expressionAttributeValues = {};
|
|
125
|
+
entries.forEach(([field, value], index) => {
|
|
126
|
+
updates.push(`#f${index} = :f${index}`);
|
|
127
|
+
expressionAttributeNames[`#f${index}`] = field;
|
|
128
|
+
expressionAttributeValues[`:f${index}`] = (0, dynamoEncoding_1.encodeDynamoAttribute)(value);
|
|
129
|
+
});
|
|
130
|
+
const cmd = new client_dynamodb_1.UpdateItemCommand({
|
|
131
|
+
Key: { [key]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) },
|
|
132
|
+
TableName: await tableName(),
|
|
133
|
+
UpdateExpression: `SET ${updates.join(', ')}`,
|
|
134
|
+
ConditionExpression: 'attribute_exists(#k)',
|
|
135
|
+
ExpressionAttributeNames: expressionAttributeNames,
|
|
136
|
+
ExpressionAttributeValues: expressionAttributeValues,
|
|
137
|
+
ReturnValues: 'ALL_NEW',
|
|
138
|
+
});
|
|
139
|
+
return dynamodb().send(cmd).then(async (item) => {
|
|
140
|
+
var _a;
|
|
141
|
+
if (!item.Attributes) {
|
|
142
|
+
throw new errors_1.NotFoundError(`Item with ${key} "${id}" does not exist`);
|
|
143
|
+
}
|
|
144
|
+
const updatedDoc = (0, dynamoEncoding_1.decodeDynamoDocument)(item.Attributes);
|
|
145
|
+
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
146
|
+
return updatedDoc;
|
|
147
|
+
}).catch((error) => {
|
|
148
|
+
throw error.name === 'ConditionalCheckFailedException' ?
|
|
149
|
+
new errors_1.NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
/* replaces the entire document with the given data */
|
|
153
|
+
putItem: async (item) => {
|
|
139
154
|
var _a;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
155
|
+
const cmd = new client_dynamodb_1.PutItemCommand({
|
|
156
|
+
TableName: await tableName(),
|
|
157
|
+
Item: (0, dynamoEncoding_1.encodeDynamoDocument)(item),
|
|
158
|
+
});
|
|
159
|
+
const updatedDoc = await dynamodb().send(cmd).then(() => item);
|
|
144
160
|
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
145
161
|
return updatedDoc;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
new errors_1.NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
|
|
149
|
-
});
|
|
150
|
-
},
|
|
151
|
-
/* replaces the entire document with the given data */
|
|
152
|
-
putItem: async (item) => {
|
|
153
|
-
var _a;
|
|
154
|
-
const cmd = new client_dynamodb_1.PutItemCommand({
|
|
155
|
-
TableName: await tableName(),
|
|
156
|
-
Item: (0, dynamoEncoding_1.encodeDynamoDocument)(item),
|
|
157
|
-
});
|
|
158
|
-
const updatedDoc = await dynamodb().send(cmd).then(() => item);
|
|
159
|
-
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
160
|
-
return updatedDoc;
|
|
161
|
-
},
|
|
162
|
+
},
|
|
163
|
+
};
|
|
162
164
|
};
|
|
163
165
|
};
|
|
164
166
|
exports.dynamoUnversionedDocumentStore = dynamoUnversionedDocumentStore;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { DynamoDB } from '@aws-sdk/client-dynamodb';
|
|
1
2
|
import { Config } from '..';
|
|
2
3
|
import { ConfigProviderForConfig } from '../../../config';
|
|
3
4
|
import { VersionedDocumentAuthor, VersionedTDocument } from '.';
|
|
4
5
|
interface Initializer<C> {
|
|
5
6
|
configSpace?: C;
|
|
7
|
+
dynamoClient?: DynamoDB;
|
|
6
8
|
}
|
|
7
9
|
export declare const dynamoVersionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends VersionedTDocument<T>>() => (configProvider: { [key in C]: {
|
|
8
10
|
tableName: import("../../../config").ConfigValueProvider<string>;
|