@openstax/ts-utils 1.14.0 → 1.15.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.
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.subrequestAuthProvider = void 0;
7
+ const cookie_1 = __importDefault(require("cookie"));
4
8
  const __1 = require("../..");
5
9
  const config_1 = require("../../config");
6
10
  const guards_1 = require("../../guards");
@@ -19,10 +23,12 @@ const subrequestAuthProvider = (initializer) => (configProvider) => {
19
23
  return { headers };
20
24
  };
21
25
  const loadUser = async () => {
22
- const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
26
+ const resolvedCookeiName = await cookieName();
27
+ const [token] = (0, _1.getAuthTokenOrCookie)(request, resolvedCookeiName);
23
28
  if (!token) {
24
29
  return undefined;
25
30
  }
31
+ const headers = { cookie: cookie_1.default.serialize(resolvedCookeiName, token) };
26
32
  return initializer.fetch((await accountsBase()).replace(/\/+$/, '') + '/api/user', { headers })
27
33
  .then(response => response.json());
28
34
  };
@@ -9,6 +9,8 @@ export declare const dynamoUnversionedDocumentStore: <C extends string = "dynamo
9
9
  loadAllDocumentsTheBadWay: () => Promise<T[]>;
10
10
  batchGetItem: (ids: T[K][]) => Promise<T[]>;
11
11
  getItem: (id: T[K]) => Promise<T | undefined>;
12
+ incrementItemAttribute: (id: T[K], attribute: keyof T) => Promise<number>;
13
+ patchItem: (item: Partial<T>) => Promise<T>;
12
14
  putItem: (item: T) => Promise<T>;
13
15
  };
14
16
  export {};
@@ -45,7 +45,64 @@ const dynamoUnversionedDocumentStore = (initializer) => () => (configProvider) =
45
45
  });
46
46
  return dynamodb().send(cmd).then(result => result.Item ? (0, dynamoEncoding_1.decodeDynamoDocument)(result.Item) : undefined);
47
47
  },
48
- /* saves a new version of a document with the given data */
48
+ /* atomically increments the given item attribute by 1 */
49
+ incrementItemAttribute: async (id, attribute) => {
50
+ const key = hashKey.toString();
51
+ const field = attribute.toString();
52
+ const cmd = new client_dynamodb_1.UpdateItemCommand({
53
+ Key: { [key]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) },
54
+ TableName: await tableName(),
55
+ UpdateExpression: 'ADD #f :one',
56
+ ConditionExpression: 'attribute_exists(#k)',
57
+ ExpressionAttributeNames: { '#k': hashKey.toString(), '#f': field },
58
+ ExpressionAttributeValues: { ':one': { N: '1' } },
59
+ ReturnValues: 'UPDATED_NEW',
60
+ });
61
+ return dynamodb().send(cmd).then((item) => {
62
+ var _a;
63
+ const result = (_a = item.Attributes) === null || _a === void 0 ? void 0 : _a[field]['N'];
64
+ if (!result) {
65
+ throw new Error(`Item with ${key} "${id}" does not exist`);
66
+ }
67
+ return parseFloat(result);
68
+ });
69
+ },
70
+ /* replaces only specified attributes with the given data */
71
+ patchItem: async (item) => {
72
+ const id = item[hashKey];
73
+ const key = hashKey.toString();
74
+ if (!id) {
75
+ throw new Error(`Key attribute "${key}" is required for patchItem`);
76
+ }
77
+ const entries = Object.entries(item).filter(([field]) => field !== key);
78
+ if (entries.length === 0) {
79
+ throw new Error('No attributes to update');
80
+ }
81
+ const updates = [];
82
+ const expressionAttributeNames = { '#k': key };
83
+ const expressionAttributeValues = {};
84
+ entries.forEach(([field, value], index) => {
85
+ updates.push(`#f${index} = :f${index}`);
86
+ expressionAttributeNames[`#f${index}`] = field;
87
+ expressionAttributeValues[`:f${index}`] = (0, dynamoEncoding_1.encodeDynamoAttribute)(value);
88
+ });
89
+ const cmd = new client_dynamodb_1.UpdateItemCommand({
90
+ Key: { [key]: (0, dynamoEncoding_1.encodeDynamoAttribute)(id) },
91
+ TableName: await tableName(),
92
+ UpdateExpression: `SET ${updates.join(', ')}`,
93
+ ConditionExpression: 'attribute_exists(#k)',
94
+ ExpressionAttributeNames: expressionAttributeNames,
95
+ ExpressionAttributeValues: expressionAttributeValues,
96
+ ReturnValues: 'ALL_NEW',
97
+ });
98
+ return dynamodb().send(cmd).then((item) => {
99
+ if (!item.Attributes) {
100
+ throw new Error(`Item with ${key} "${id}" does not exist`);
101
+ }
102
+ return (0, dynamoEncoding_1.decodeDynamoDocument)(item.Attributes);
103
+ });
104
+ },
105
+ /* replaces the entire document with the given data */
49
106
  putItem: async (item) => {
50
107
  const cmd = new client_dynamodb_1.PutItemCommand({
51
108
  TableName: await tableName(),
@@ -11,6 +11,8 @@ export declare const fileSystemUnversionedDocumentStore: <C extends string = "fi
11
11
  loadAllDocumentsTheBadWay: () => Promise<T[]>;
12
12
  batchGetItem: (ids: T[K][]) => Promise<Exclude<Awaited<T>, undefined>[]>;
13
13
  getItem: (id: T[K]) => Promise<T | undefined>;
14
+ incrementItemAttribute: (id: T[K], attribute: keyof T) => Promise<number>;
15
+ patchItem: (item: Partial<T>) => Promise<T>;
14
16
  putItem: (item: T) => Promise<T>;
15
17
  };
16
18
  export {};
@@ -73,6 +73,41 @@ const fileSystemUnversionedDocumentStore = (initializer) => () => (configProvide
73
73
  return items.filter(guards_1.isDefined);
74
74
  },
75
75
  getItem: (id) => load(hashFilename(id)),
76
+ incrementItemAttribute: async (id, attribute) => {
77
+ const filename = hashFilename(id);
78
+ const path = await filePath(filename);
79
+ await mkTableDir;
80
+ const data = await load(filename);
81
+ if (!data) {
82
+ throw new Error(`Item with ${hashKey.toString()} "${id}" does not exist`);
83
+ }
84
+ const newValue = typeof data[attribute] === 'number' ? data[attribute] + 1 : 1;
85
+ const newItem = { ...data, [hashKey]: id, [attribute]: newValue };
86
+ return new Promise((resolve, reject) => {
87
+ writeFile(path, JSON.stringify(newItem, null, 2), (err) => err ? reject(err) : resolve(newValue));
88
+ });
89
+ },
90
+ patchItem: async (item) => {
91
+ const id = item[hashKey];
92
+ if (!id) {
93
+ throw new Error(`Key attribute "${hashKey.toString()}" is required for patchItem`);
94
+ }
95
+ // This check is just to make this adapter consistent with the dynamo adapter
96
+ if (Object.keys(item).filter((key) => key !== hashKey.toString()).length === 0) {
97
+ throw new Error('No attributes to update');
98
+ }
99
+ const filename = hashFilename(id);
100
+ const path = await filePath(filename);
101
+ await mkTableDir;
102
+ const data = await load(filename);
103
+ if (!data) {
104
+ throw new Error(`Item with ${hashKey.toString()} "${id}" does not exist`);
105
+ }
106
+ const newItem = { ...data, ...item };
107
+ return new Promise((resolve, reject) => {
108
+ writeFile(path, JSON.stringify(newItem, null, 2), (err) => err ? reject(err) : resolve(newItem));
109
+ });
110
+ },
76
111
  putItem: async (item) => {
77
112
  const path = await filePath(hashFilename(item[hashKey]));
78
113
  await mkTableDir;
@@ -1,13 +1,34 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
4
24
  };
5
25
  Object.defineProperty(exports, "__esModule", { value: true });
6
26
  exports.createLaunchVerifier = void 0;
7
- const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
27
+ const jsonwebtoken_1 = __importStar(require("jsonwebtoken"));
8
28
  const jwks_rsa_1 = require("jwks-rsa");
9
29
  const __1 = require("../..");
10
30
  const config_1 = require("../../config");
31
+ const errors_1 = require("../../errors");
11
32
  const guards_1 = require("../../guards");
12
33
  /**
13
34
  * Creates a class that can verify launch params
@@ -40,7 +61,10 @@ const createLaunchVerifier = ({ configSpace, fetcher }) => (configProvider) => {
40
61
  }
41
62
  };
42
63
  const verify = (token) => new Promise((resolve, reject) => jsonwebtoken_1.default.verify(token, getKey, {}, (err, payload) => {
43
- if (err) {
64
+ if (err && err instanceof jsonwebtoken_1.TokenExpiredError) {
65
+ reject(new errors_1.SessionExpiredError());
66
+ }
67
+ else if (err) {
44
68
  reject(err);
45
69
  }
46
70
  else if (typeof payload !== 'object') {