@openstax/ts-utils 1.24.5 → 1.25.1-pre1

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.
@@ -3,7 +3,7 @@ import queryString from 'query-string';
3
3
  import { v4 as uuid } from 'uuid';
4
4
  import { merge } from '../..';
5
5
  import { resolveConfigValue } from '../../config';
6
- import { ForbiddenError, SessionExpiredError, UnauthorizedError } from '../../errors';
6
+ import { SessionExpiredError, UnauthorizedError } from '../../errors';
7
7
  import { fetchStatusRetry } from '../../fetch/fetchStatusRetry';
8
8
  import { Level } from '../logger';
9
9
  /** Pulls the content out of a response based on the content type */
@@ -49,9 +49,6 @@ const makeRouteClient = (initializer, config, route, appProvider) => {
49
49
  if (response.status === 401) {
50
50
  throw new UnauthorizedError();
51
51
  }
52
- if (response.status === 403) {
53
- throw new ForbiddenError();
54
- }
55
52
  if (response.status === 440) {
56
53
  throw new SessionExpiredError();
57
54
  }
@@ -5,7 +5,9 @@ interface Initializer<C> {
5
5
  }
6
6
  export declare const dynamoUnversionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends TDocument<T>>() => (configProvider: { [key in C]: {
7
7
  tableName: import("../../../config").ConfigValueProvider<string>;
8
- }; }) => <K extends keyof T>(_: {}, hashKey: K) => {
8
+ }; }) => <K extends keyof T>(_: {}, hashKey: K, options?: {
9
+ afterWrite?: ((item: T) => void | Promise<void>) | undefined;
10
+ } | undefined) => {
9
11
  loadAllDocumentsTheBadWay: () => Promise<T[]>;
10
12
  batchGetItem: (ids: T[K][]) => Promise<T[]>;
11
13
  getItem: (id: T[K]) => Promise<T | undefined>;
@@ -5,9 +5,9 @@ import { NotFoundError } from '../../../errors';
5
5
  import { ifDefined } from '../../../guards';
6
6
  import { decodeDynamoDocument, encodeDynamoAttribute, encodeDynamoDocument } from '../dynamoEncoding';
7
7
  const dynamodb = once(() => new DynamoDB({ apiVersion: '2012-08-10' }));
8
- export const dynamoUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey) => {
9
- const options = ifDefined(initializer, {});
10
- const tableName = once(() => resolveConfigValue(configProvider[ifDefined(options.configSpace, 'dynamodb')].tableName));
8
+ export const dynamoUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey, options) => {
9
+ const init = ifDefined(initializer, {});
10
+ const tableName = once(() => resolveConfigValue(configProvider[ifDefined(init.configSpace, 'dynamodb')].tableName));
11
11
  return {
12
12
  loadAllDocumentsTheBadWay: async () => {
13
13
  const loadAllResults = async (ExclusiveStartKey) => {
@@ -54,14 +54,19 @@ export const dynamoUnversionedDocumentStore = (initializer) => () => (configProv
54
54
  ConditionExpression: 'attribute_exists(#k)',
55
55
  ExpressionAttributeNames: { '#k': hashKey.toString(), '#f': field },
56
56
  ExpressionAttributeValues: { ':one': { N: '1' } },
57
- ReturnValues: 'UPDATED_NEW',
57
+ ReturnValues: 'ALL_NEW',
58
58
  });
59
- return dynamodb().send(cmd).then((item) => {
60
- var _a;
61
- const result = (_a = item.Attributes) === null || _a === void 0 ? void 0 : _a[field]['N'];
62
- if (!result) {
59
+ return dynamodb().send(cmd).then(async (item) => {
60
+ var _a, _b, _c;
61
+ const result = (_b = (_a = item.Attributes) === null || _a === void 0 ? void 0 : _a[field]) === null || _b === void 0 ? void 0 : _b['N'];
62
+ if (!item.Attributes) {
63
63
  throw new NotFoundError(`Item with ${key} "${id}" does not exist`);
64
64
  }
65
+ if (!result) {
66
+ throw new NotFoundError(`Item with ${key} "${id}" did not produce field "${field}"`);
67
+ }
68
+ const updatedDoc = decodeDynamoDocument(item.Attributes);
69
+ await ((_c = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _c === void 0 ? void 0 : _c.call(options, updatedDoc));
65
70
  return parseFloat(result);
66
71
  }).catch((error) => {
67
72
  throw error.name === 'ConditionalCheckFailedException' ?
@@ -96,11 +101,14 @@ export const dynamoUnversionedDocumentStore = (initializer) => () => (configProv
96
101
  ExpressionAttributeValues: expressionAttributeValues,
97
102
  ReturnValues: 'ALL_NEW',
98
103
  });
99
- return dynamodb().send(cmd).then((item) => {
104
+ return dynamodb().send(cmd).then(async (item) => {
105
+ var _a;
100
106
  if (!item.Attributes) {
101
107
  throw new NotFoundError(`Item with ${key} "${id}" does not exist`);
102
108
  }
103
- return decodeDynamoDocument(item.Attributes);
109
+ const updatedDoc = decodeDynamoDocument(item.Attributes);
110
+ await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
111
+ return updatedDoc;
104
112
  }).catch((error) => {
105
113
  throw error.name === 'ConditionalCheckFailedException' ?
106
114
  new NotFoundError(`Item with ${key} "${id}" does not exist`) : error;
@@ -108,11 +116,14 @@ export const dynamoUnversionedDocumentStore = (initializer) => () => (configProv
108
116
  },
109
117
  /* replaces the entire document with the given data */
110
118
  putItem: async (item) => {
119
+ var _a;
111
120
  const cmd = new PutItemCommand({
112
121
  TableName: await tableName(),
113
122
  Item: encodeDynamoDocument(item),
114
123
  });
115
- return dynamodb().send(cmd).then(() => item);
124
+ const updatedDoc = await dynamodb().send(cmd).then(() => item);
125
+ await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
126
+ return updatedDoc;
116
127
  },
117
128
  };
118
129
  };
@@ -6,7 +6,10 @@ interface Initializer<C> {
6
6
  }
7
7
  export declare const dynamoVersionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends VersionedTDocument<T>>() => (configProvider: { [key in C]: {
8
8
  tableName: import("../../../config").ConfigValueProvider<string>;
9
- }; }) => <K extends keyof T, A extends ((...a: any[]) => Promise<VersionedDocumentAuthor>) | undefined>(_: {}, hashKey: K, getAuthor: A) => {
9
+ }; }) => <K extends keyof T, A extends ((...a: any[]) => Promise<VersionedDocumentAuthor>) | undefined>(_: {}, hashKey: K, options?: {
10
+ afterWrite?: ((item: T) => void | Promise<void>) | undefined;
11
+ getAuthor?: A | undefined;
12
+ } | undefined) => {
10
13
  loadAllDocumentsTheBadWay: () => Promise<T[]>;
11
14
  getVersions: (id: T[K], startVersion?: number | undefined) => Promise<{
12
15
  items: T[];
@@ -5,9 +5,9 @@ import { ifDefined } from '../../../guards';
5
5
  import { decodeDynamoDocument, encodeDynamoAttribute, encodeDynamoDocument } from '../dynamoEncoding';
6
6
  const dynamodb = once(() => new DynamoDB({ apiVersion: '2012-08-10' }));
7
7
  // i'm not really excited about getAuthor being required, but ts is getting confused about the type when unspecified
8
- export const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey, getAuthor) => {
9
- const options = ifDefined(initializer, {});
10
- const tableName = once(() => resolveConfigValue(configProvider[ifDefined(options.configSpace, 'dynamodb')].tableName));
8
+ export const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey, options) => {
9
+ const init = ifDefined(initializer, {});
10
+ const tableName = once(() => resolveConfigValue(configProvider[ifDefined(init.configSpace, 'dynamodb')].tableName));
11
11
  return {
12
12
  loadAllDocumentsTheBadWay: async () => {
13
13
  const loadAllResults = async (ExclusiveStartKey) => {
@@ -91,11 +91,12 @@ export const dynamoVersionedDocumentStore = (initializer) => () => (configProvid
91
91
  * cannot be modified */
92
92
  prepareItem: async (item, ...authorArgs) => {
93
93
  // this getAuthor type is terrible
94
- const author = getAuthor ? await getAuthor(...authorArgs) : authorArgs[0];
94
+ const author = (options === null || options === void 0 ? void 0 : options.getAuthor) ? await options.getAuthor(...authorArgs) : authorArgs[0];
95
95
  const timestamp = new Date().getTime();
96
96
  return {
97
97
  document: { ...item, timestamp, author },
98
98
  save: async (changes) => {
99
+ var _a;
99
100
  const document = {
100
101
  ...item,
101
102
  ...changes,
@@ -106,15 +107,18 @@ export const dynamoVersionedDocumentStore = (initializer) => () => (configProvid
106
107
  TableName: await tableName(),
107
108
  Item: encodeDynamoDocument(document),
108
109
  });
109
- return dynamodb().send(cmd)
110
+ const updatedDoc = await dynamodb().send(cmd)
110
111
  .then(() => document);
112
+ await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
113
+ return updatedDoc;
111
114
  }
112
115
  };
113
116
  },
114
117
  /* saves a new version of a document with the given data */
115
118
  putItem: async (item, ...authorArgs) => {
119
+ var _a;
116
120
  // this getAuthor type is terrible
117
- const author = getAuthor ? await getAuthor(...authorArgs) : authorArgs[0];
121
+ const author = (options === null || options === void 0 ? void 0 : options.getAuthor) ? await options.getAuthor(...authorArgs) : authorArgs[0];
118
122
  const document = {
119
123
  ...item,
120
124
  timestamp: new Date().getTime(),
@@ -124,8 +128,10 @@ export const dynamoVersionedDocumentStore = (initializer) => () => (configProvid
124
128
  TableName: await tableName(),
125
129
  Item: encodeDynamoDocument(document),
126
130
  });
127
- return dynamodb().send(cmd)
131
+ const updatedDoc = await dynamodb().send(cmd)
128
132
  .then(() => document);
133
+ await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
134
+ return updatedDoc;
129
135
  },
130
136
  };
131
137
  };