@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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveConfigValue } from '../config/resolveConfigValue';
|
|
2
|
+
import { once } from '../misc/helpers';
|
|
2
3
|
import { apiTextResponse } from '../routing';
|
|
3
4
|
/**
|
|
4
5
|
* Creates response middleware that adds CORS headers to responses from approved hosts.
|
|
@@ -11,8 +12,9 @@ import { apiTextResponse } from '../routing';
|
|
|
11
12
|
* }),
|
|
12
13
|
*/
|
|
13
14
|
export const createLambdaCorsResponseMiddleware = (config) => () => (responsePromise, { request }) => {
|
|
15
|
+
const getAllowedHostRegex = once(() => resolveConfigValue(config.corsAllowedHostRegex));
|
|
14
16
|
const cors = async () => {
|
|
15
|
-
const allowedHost = await
|
|
17
|
+
const allowedHost = await getAllowedHostRegex();
|
|
16
18
|
if (request.headers.origin && request.headers.origin !== 'null' && new URL(request.headers.origin).hostname.match(new RegExp(allowedHost))) {
|
|
17
19
|
return {
|
|
18
20
|
'Access-Control-Allow-Origin': request.headers.origin,
|
|
@@ -2,6 +2,7 @@ import { chunk, isEqual } from 'lodash';
|
|
|
2
2
|
import queryString from 'query-string';
|
|
3
3
|
import { resolveConfigValue } from '../../config';
|
|
4
4
|
import { ifDefined, isDefined } from '../../guards';
|
|
5
|
+
import { once } from '../../misc/helpers';
|
|
5
6
|
import { METHOD } from '../../routing';
|
|
6
7
|
import { Level } from '../logger';
|
|
7
8
|
class ApiError extends Error {
|
|
@@ -12,15 +13,15 @@ class ApiError extends Error {
|
|
|
12
13
|
}
|
|
13
14
|
export const accountsGateway = (initializer) => (configProvider) => {
|
|
14
15
|
const config = configProvider[ifDefined(initializer.configSpace, 'accounts')];
|
|
15
|
-
const accountsBase = resolveConfigValue(config.accountsBase);
|
|
16
|
-
const accountsAuthToken = resolveConfigValue(config.accountsAuthToken);
|
|
16
|
+
const accountsBase = once(() => resolveConfigValue(config.accountsBase));
|
|
17
|
+
const accountsAuthToken = once(() => resolveConfigValue(config.accountsAuthToken));
|
|
17
18
|
return ({ logger }) => {
|
|
18
19
|
const request = async (method, path, options, statuses = [200, 201]) => {
|
|
19
|
-
const host = (await accountsBase).replace(/\/+$/, '');
|
|
20
|
+
const host = (await accountsBase()).replace(/\/+$/, '');
|
|
20
21
|
const url = `${host}/api/${path}`;
|
|
21
22
|
const config = {
|
|
22
23
|
headers: {
|
|
23
|
-
Authorization: `Bearer ${options.token || await accountsAuthToken}`,
|
|
24
|
+
Authorization: `Bearer ${options.token || await accountsAuthToken()}`,
|
|
24
25
|
},
|
|
25
26
|
method,
|
|
26
27
|
};
|
|
@@ -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>;
|
|
@@ -4,157 +4,159 @@ import { resolveConfigValue } from '../../../config';
|
|
|
4
4
|
import { NotFoundError } from '../../../errors';
|
|
5
5
|
import { ifDefined } from '../../../guards';
|
|
6
6
|
import { decodeDynamoDocument, encodeDynamoAttribute, encodeDynamoDocument } from '../dynamoEncoding';
|
|
7
|
-
const
|
|
8
|
-
export const dynamoUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey, options) => {
|
|
7
|
+
export const dynamoUnversionedDocumentStore = (initializer) => {
|
|
9
8
|
const init = ifDefined(initializer, {});
|
|
10
|
-
const
|
|
11
|
-
return {
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const dynamodb = once(() => { var _a; return (_a = init.dynamoClient) !== null && _a !== void 0 ? _a : new DynamoDB({ apiVersion: '2012-08-10' }); });
|
|
10
|
+
return () => (configProvider) => (_, hashKey, options) => {
|
|
11
|
+
const tableName = once(() => resolveConfigValue(configProvider[ifDefined(init.configSpace, 'dynamodb')].tableName));
|
|
12
|
+
return {
|
|
13
|
+
loadAllDocumentsTheBadWay: async () => {
|
|
14
|
+
const loadAllResults = async (ExclusiveStartKey) => {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const cmd = new ScanCommand({ TableName: await tableName(), ExclusiveStartKey });
|
|
17
|
+
const result = await dynamodb().send(cmd);
|
|
18
|
+
const resultItems = (_b = (_a = result.Items) === null || _a === void 0 ? void 0 : _a.map((item) => decodeDynamoDocument(item))) !== null && _b !== void 0 ? _b : [];
|
|
19
|
+
if (result.LastEvaluatedKey) {
|
|
20
|
+
return [...resultItems, ...await loadAllResults(result.LastEvaluatedKey)];
|
|
21
|
+
}
|
|
22
|
+
return resultItems;
|
|
23
|
+
};
|
|
24
|
+
return loadAllResults();
|
|
25
|
+
},
|
|
26
|
+
/*
|
|
27
|
+
* requires that a global secondary index exist on the table
|
|
28
|
+
*/
|
|
29
|
+
getItemsByField: async (key, value, pageKey) => {
|
|
14
30
|
var _a, _b;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const ExclusiveStartKey = pageKey
|
|
31
|
-
? JSON.parse(Buffer.from(pageKey, 'base64').toString('utf-8'))
|
|
32
|
-
: undefined;
|
|
33
|
-
const table = await tableName();
|
|
34
|
-
const cmd = new QueryCommand({
|
|
35
|
-
TableName: table,
|
|
36
|
-
IndexName: key.toString(),
|
|
37
|
-
ExclusiveStartKey,
|
|
38
|
-
KeyConditionExpression: '#hk = :hkv',
|
|
39
|
-
ExpressionAttributeValues: {
|
|
40
|
-
':hkv': encodeDynamoAttribute(value),
|
|
41
|
-
},
|
|
42
|
-
ExpressionAttributeNames: {
|
|
43
|
-
'#hk': key.toString(),
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
const response = await dynamodb().send(cmd);
|
|
47
|
-
const items = (_b = (_a = response.Items) === null || _a === void 0 ? void 0 : _a.map((item) => decodeDynamoDocument(item))) !== null && _b !== void 0 ? _b : [];
|
|
48
|
-
const nextPageToken = response.LastEvaluatedKey;
|
|
49
|
-
return {
|
|
50
|
-
items,
|
|
51
|
-
nextPageToken: nextPageToken
|
|
52
|
-
? Buffer.from(JSON.stringify(nextPageToken)).toString('base64')
|
|
53
|
-
: undefined,
|
|
54
|
-
};
|
|
55
|
-
},
|
|
56
|
-
batchGetItem: async (ids) => {
|
|
57
|
-
const table = await tableName();
|
|
58
|
-
const key = hashKey.toString();
|
|
59
|
-
const getBatches = async (requestItems) => {
|
|
60
|
-
const cmd = new BatchGetItemCommand({
|
|
61
|
-
RequestItems: requestItems !== null && requestItems !== void 0 ? requestItems : { [table]: { Keys: ids.map((id) => ({ [key]: encodeDynamoAttribute(id) })) } },
|
|
31
|
+
const ExclusiveStartKey = pageKey
|
|
32
|
+
? JSON.parse(Buffer.from(pageKey, 'base64').toString('utf-8'))
|
|
33
|
+
: undefined;
|
|
34
|
+
const table = await tableName();
|
|
35
|
+
const cmd = new QueryCommand({
|
|
36
|
+
TableName: table,
|
|
37
|
+
IndexName: key.toString(),
|
|
38
|
+
ExclusiveStartKey,
|
|
39
|
+
KeyConditionExpression: '#hk = :hkv',
|
|
40
|
+
ExpressionAttributeValues: {
|
|
41
|
+
':hkv': encodeDynamoAttribute(value),
|
|
42
|
+
},
|
|
43
|
+
ExpressionAttributeNames: {
|
|
44
|
+
'#hk': key.toString(),
|
|
45
|
+
},
|
|
62
46
|
});
|
|
63
47
|
const response = await dynamodb().send(cmd);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
48
|
+
const items = (_b = (_a = response.Items) === null || _a === void 0 ? void 0 : _a.map((item) => decodeDynamoDocument(item))) !== null && _b !== void 0 ? _b : [];
|
|
49
|
+
const nextPageToken = response.LastEvaluatedKey;
|
|
50
|
+
return {
|
|
51
|
+
items,
|
|
52
|
+
nextPageToken: nextPageToken
|
|
53
|
+
? Buffer.from(JSON.stringify(nextPageToken)).toString('base64')
|
|
54
|
+
: undefined,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
batchGetItem: async (ids) => {
|
|
58
|
+
const table = await tableName();
|
|
59
|
+
const key = hashKey.toString();
|
|
60
|
+
const getBatches = async (requestItems) => {
|
|
61
|
+
const cmd = new BatchGetItemCommand({
|
|
62
|
+
RequestItems: requestItems !== null && requestItems !== void 0 ? requestItems : { [table]: { Keys: ids.map((id) => ({ [key]: encodeDynamoAttribute(id) })) } },
|
|
63
|
+
});
|
|
64
|
+
const response = await dynamodb().send(cmd);
|
|
65
|
+
const currentResponses = response.Responses ?
|
|
66
|
+
response.Responses[table].map(response => decodeDynamoDocument(response)) : [];
|
|
67
|
+
return currentResponses.concat(response.UnprocessedKeys ? await getBatches(response.UnprocessedKeys) : []);
|
|
68
|
+
};
|
|
69
|
+
return getBatches();
|
|
70
|
+
},
|
|
71
|
+
getItem: async (id) => {
|
|
72
|
+
const cmd = new GetItemCommand({
|
|
73
|
+
Key: { [hashKey.toString()]: encodeDynamoAttribute(id) },
|
|
74
|
+
TableName: await tableName(),
|
|
75
|
+
});
|
|
76
|
+
return dynamodb().send(cmd).then(result => result.Item ? decodeDynamoDocument(result.Item) : undefined);
|
|
77
|
+
},
|
|
78
|
+
/* atomically increments the given item attribute by 1 */
|
|
79
|
+
incrementItemAttribute: async (id, attribute) => {
|
|
80
|
+
const key = hashKey.toString();
|
|
81
|
+
const field = attribute.toString();
|
|
82
|
+
const cmd = new UpdateItemCommand({
|
|
83
|
+
Key: { [key]: encodeDynamoAttribute(id) },
|
|
84
|
+
TableName: await tableName(),
|
|
85
|
+
UpdateExpression: 'ADD #f :one',
|
|
86
|
+
ConditionExpression: 'attribute_exists(#k)',
|
|
87
|
+
ExpressionAttributeNames: { '#k': hashKey.toString(), '#f': field },
|
|
88
|
+
ExpressionAttributeValues: { ':one': { N: '1' } },
|
|
89
|
+
ReturnValues: 'ALL_NEW',
|
|
90
|
+
});
|
|
91
|
+
return dynamodb().send(cmd).then(async (item) => {
|
|
92
|
+
var _a, _b, _c;
|
|
93
|
+
const result = (_b = (_a = item.Attributes) === null || _a === void 0 ? void 0 : _a[field]) === null || _b === void 0 ? void 0 : _b['N'];
|
|
94
|
+
if (!item.Attributes) {
|
|
95
|
+
throw new NotFoundError(`Item with ${key} "${id}" does not exist`);
|
|
96
|
+
}
|
|
97
|
+
if (!result) {
|
|
98
|
+
throw new NotFoundError(`Item with ${key} "${id}" did not produce field "${field}"`);
|
|
99
|
+
}
|
|
100
|
+
const updatedDoc = decodeDynamoDocument(item.Attributes);
|
|
101
|
+
await ((_c = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _c === void 0 ? void 0 : _c.call(options, updatedDoc));
|
|
102
|
+
return parseFloat(result);
|
|
103
|
+
}).catch((error) => {
|
|
104
|
+
throw error.name === 'ConditionalCheckFailedException' ?
|
|
105
|
+
new NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
/* replaces only specified attributes with the given data */
|
|
109
|
+
patchItem: async (item) => {
|
|
110
|
+
const id = item[hashKey];
|
|
111
|
+
const key = hashKey.toString();
|
|
112
|
+
if (!id) {
|
|
113
|
+
throw new Error(`Key attribute "${key}" is required for patchItem`);
|
|
95
114
|
}
|
|
96
|
-
|
|
97
|
-
|
|
115
|
+
const entries = Object.entries(item).filter(([field]) => field !== key);
|
|
116
|
+
if (entries.length === 0) {
|
|
117
|
+
throw new Error('No attributes to update');
|
|
98
118
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
ExpressionAttributeNames: expressionAttributeNames,
|
|
132
|
-
ExpressionAttributeValues: expressionAttributeValues,
|
|
133
|
-
ReturnValues: 'ALL_NEW',
|
|
134
|
-
});
|
|
135
|
-
return dynamodb().send(cmd).then(async (item) => {
|
|
119
|
+
const updates = [];
|
|
120
|
+
const expressionAttributeNames = { '#k': key };
|
|
121
|
+
const expressionAttributeValues = {};
|
|
122
|
+
entries.forEach(([field, value], index) => {
|
|
123
|
+
updates.push(`#f${index} = :f${index}`);
|
|
124
|
+
expressionAttributeNames[`#f${index}`] = field;
|
|
125
|
+
expressionAttributeValues[`:f${index}`] = encodeDynamoAttribute(value);
|
|
126
|
+
});
|
|
127
|
+
const cmd = new UpdateItemCommand({
|
|
128
|
+
Key: { [key]: encodeDynamoAttribute(id) },
|
|
129
|
+
TableName: await tableName(),
|
|
130
|
+
UpdateExpression: `SET ${updates.join(', ')}`,
|
|
131
|
+
ConditionExpression: 'attribute_exists(#k)',
|
|
132
|
+
ExpressionAttributeNames: expressionAttributeNames,
|
|
133
|
+
ExpressionAttributeValues: expressionAttributeValues,
|
|
134
|
+
ReturnValues: 'ALL_NEW',
|
|
135
|
+
});
|
|
136
|
+
return dynamodb().send(cmd).then(async (item) => {
|
|
137
|
+
var _a;
|
|
138
|
+
if (!item.Attributes) {
|
|
139
|
+
throw new NotFoundError(`Item with ${key} "${id}" does not exist`);
|
|
140
|
+
}
|
|
141
|
+
const updatedDoc = decodeDynamoDocument(item.Attributes);
|
|
142
|
+
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
143
|
+
return updatedDoc;
|
|
144
|
+
}).catch((error) => {
|
|
145
|
+
throw error.name === 'ConditionalCheckFailedException' ?
|
|
146
|
+
new NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
/* replaces the entire document with the given data */
|
|
150
|
+
putItem: async (item) => {
|
|
136
151
|
var _a;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
152
|
+
const cmd = new PutItemCommand({
|
|
153
|
+
TableName: await tableName(),
|
|
154
|
+
Item: encodeDynamoDocument(item),
|
|
155
|
+
});
|
|
156
|
+
const updatedDoc = await dynamodb().send(cmd).then(() => item);
|
|
141
157
|
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
142
158
|
return updatedDoc;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
new NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
|
|
146
|
-
});
|
|
147
|
-
},
|
|
148
|
-
/* replaces the entire document with the given data */
|
|
149
|
-
putItem: async (item) => {
|
|
150
|
-
var _a;
|
|
151
|
-
const cmd = new PutItemCommand({
|
|
152
|
-
TableName: await tableName(),
|
|
153
|
-
Item: encodeDynamoDocument(item),
|
|
154
|
-
});
|
|
155
|
-
const updatedDoc = await dynamodb().send(cmd).then(() => item);
|
|
156
|
-
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
157
|
-
return updatedDoc;
|
|
158
|
-
},
|
|
159
|
+
},
|
|
160
|
+
};
|
|
159
161
|
};
|
|
160
162
|
};
|
|
@@ -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>;
|