@openstax/ts-utils 1.1.27 → 1.1.29

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.
Files changed (145) hide show
  1. package/dist/{assertions.d.ts → cjs/assertions.d.ts} +0 -0
  2. package/dist/{assertions.js → cjs/assertions.js} +0 -0
  3. package/dist/{aws → cjs/aws}/securityTokenService.d.ts +0 -0
  4. package/dist/{aws → cjs/aws}/securityTokenService.js +0 -0
  5. package/dist/{aws → cjs/aws}/ssmService.d.ts +0 -0
  6. package/dist/{aws → cjs/aws}/ssmService.js +0 -0
  7. package/dist/cjs/config/awsAccountConfig.d.ts +5 -0
  8. package/dist/cjs/config/awsAccountConfig.js +35 -0
  9. package/dist/cjs/config/awsParameterConfig.d.ts +2 -0
  10. package/dist/cjs/config/awsParameterConfig.js +18 -0
  11. package/dist/cjs/config/envConfig.d.ts +3 -0
  12. package/dist/cjs/config/envConfig.js +35 -0
  13. package/dist/cjs/config/index.d.ts +21 -0
  14. package/dist/cjs/config/index.js +39 -0
  15. package/dist/cjs/config/lambdaParameterConfig.d.ts +2 -0
  16. package/dist/cjs/config/lambdaParameterConfig.js +36 -0
  17. package/dist/cjs/config/replaceConfig.d.ts +4 -0
  18. package/dist/cjs/config/replaceConfig.js +12 -0
  19. package/dist/cjs/config/resolveConfigValue.d.ts +2 -0
  20. package/dist/cjs/config/resolveConfigValue.js +12 -0
  21. package/dist/{config.d.ts → cjs/config.d.ts} +0 -0
  22. package/dist/{config.js → cjs/config.js} +0 -0
  23. package/dist/{errors.d.ts → cjs/errors.d.ts} +0 -0
  24. package/dist/{errors.js → cjs/errors.js} +0 -0
  25. package/dist/{fetch.d.ts → cjs/fetch.d.ts} +0 -0
  26. package/dist/{fetch.js → cjs/fetch.js} +0 -0
  27. package/dist/{guards.d.ts → cjs/guards.d.ts} +0 -0
  28. package/dist/{guards.js → cjs/guards.js} +0 -0
  29. package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  30. package/dist/{index.js → cjs/index.js} +0 -0
  31. package/dist/{middleware.d.ts → cjs/middleware.d.ts} +0 -0
  32. package/dist/{middleware.js → cjs/middleware.js} +0 -0
  33. package/dist/{pagination.d.ts → cjs/pagination.d.ts} +0 -0
  34. package/dist/{pagination.js → cjs/pagination.js} +0 -0
  35. package/dist/{profile.d.ts → cjs/profile.d.ts} +0 -0
  36. package/dist/{profile.js → cjs/profile.js} +0 -0
  37. package/dist/{routing.d.ts → cjs/routing.d.ts} +0 -0
  38. package/dist/{routing.js → cjs/routing.js} +0 -0
  39. package/dist/{services → cjs/services}/apiGateway/index.d.ts +0 -0
  40. package/dist/{services → cjs/services}/apiGateway/index.js +0 -0
  41. package/dist/{services → cjs/services}/authProvider/browser.d.ts +0 -0
  42. package/dist/{services → cjs/services}/authProvider/browser.js +0 -0
  43. package/dist/{services → cjs/services}/authProvider/decryption.d.ts +0 -0
  44. package/dist/{services → cjs/services}/authProvider/decryption.js +0 -0
  45. package/dist/{services → cjs/services}/authProvider/index.d.ts +0 -0
  46. package/dist/{services → cjs/services}/authProvider/index.js +0 -0
  47. package/dist/{services → cjs/services}/authProvider/subrequest.d.ts +0 -0
  48. package/dist/{services → cjs/services}/authProvider/subrequest.js +0 -0
  49. package/dist/{services → cjs/services}/authProvider/utils/embeddedAuthProvider.d.ts +0 -0
  50. package/dist/{services → cjs/services}/authProvider/utils/embeddedAuthProvider.js +0 -0
  51. package/dist/{services → cjs/services}/exercisesGateway/index.d.ts +0 -0
  52. package/dist/{services → cjs/services}/exercisesGateway/index.js +0 -0
  53. package/dist/{services → cjs/services}/lrsGateway/attempt-utils.d.ts +0 -0
  54. package/dist/{services → cjs/services}/lrsGateway/attempt-utils.js +0 -0
  55. package/dist/{services → cjs/services}/lrsGateway/file-system.d.ts +0 -0
  56. package/dist/{services → cjs/services}/lrsGateway/file-system.js +0 -0
  57. package/dist/{services → cjs/services}/lrsGateway/index.d.ts +0 -0
  58. package/dist/{services → cjs/services}/lrsGateway/index.js +0 -0
  59. package/dist/{services → cjs/services}/searchProvider/index.d.ts +0 -0
  60. package/dist/{services → cjs/services}/searchProvider/index.js +0 -0
  61. package/dist/{services → cjs/services}/searchProvider/memorySearchTheBadWay.d.ts +0 -0
  62. package/dist/{services → cjs/services}/searchProvider/memorySearchTheBadWay.js +0 -0
  63. package/dist/{services → cjs/services}/versionedDocumentStore/dynamodb.d.ts +0 -0
  64. package/dist/{services → cjs/services}/versionedDocumentStore/dynamodb.js +0 -0
  65. package/dist/{services → cjs/services}/versionedDocumentStore/file-system.d.ts +0 -0
  66. package/dist/{services → cjs/services}/versionedDocumentStore/file-system.js +0 -0
  67. package/dist/{services → cjs/services}/versionedDocumentStore/index.d.ts +0 -0
  68. package/dist/{services → cjs/services}/versionedDocumentStore/index.js +0 -0
  69. package/dist/cjs/tsconfig.withoutspecs.cjs.tsbuildinfo +1 -0
  70. package/dist/{types.d.ts → cjs/types.d.ts} +0 -0
  71. package/dist/{types.js → cjs/types.js} +0 -0
  72. package/dist/esm/assertions.d.ts +9 -0
  73. package/dist/esm/assertions.js +90 -0
  74. package/dist/esm/aws/securityTokenService.d.ts +2 -0
  75. package/dist/esm/aws/securityTokenService.js +3 -0
  76. package/dist/esm/aws/ssmService.d.ts +2 -0
  77. package/dist/esm/aws/ssmService.js +3 -0
  78. package/dist/esm/config/awsAccountConfig.d.ts +5 -0
  79. package/dist/esm/config/awsAccountConfig.js +31 -0
  80. package/dist/esm/config/awsParameterConfig.d.ts +2 -0
  81. package/dist/esm/config/awsParameterConfig.js +14 -0
  82. package/dist/esm/config/envConfig.d.ts +3 -0
  83. package/dist/esm/config/envConfig.js +31 -0
  84. package/dist/esm/config/index.d.ts +21 -0
  85. package/dist/esm/config/index.js +21 -0
  86. package/dist/esm/config/lambdaParameterConfig.d.ts +2 -0
  87. package/dist/esm/config/lambdaParameterConfig.js +29 -0
  88. package/dist/esm/config/replaceConfig.d.ts +4 -0
  89. package/dist/esm/config/replaceConfig.js +8 -0
  90. package/dist/esm/config/resolveConfigValue.d.ts +2 -0
  91. package/dist/esm/config/resolveConfigValue.js +8 -0
  92. package/dist/esm/config.d.ts +27 -0
  93. package/dist/esm/config.js +127 -0
  94. package/dist/esm/errors.d.ts +12 -0
  95. package/dist/esm/errors.js +26 -0
  96. package/dist/esm/fetch.d.ts +64 -0
  97. package/dist/esm/fetch.js +46 -0
  98. package/dist/esm/guards.d.ts +6 -0
  99. package/dist/esm/guards.js +29 -0
  100. package/dist/esm/index.d.ts +29 -0
  101. package/dist/esm/index.js +210 -0
  102. package/dist/esm/middleware.d.ts +9 -0
  103. package/dist/esm/middleware.js +34 -0
  104. package/dist/esm/pagination.d.ts +63 -0
  105. package/dist/esm/pagination.js +77 -0
  106. package/dist/esm/profile.d.ts +59 -0
  107. package/dist/esm/profile.js +191 -0
  108. package/dist/esm/routing.d.ts +107 -0
  109. package/dist/esm/routing.js +208 -0
  110. package/dist/esm/services/apiGateway/index.d.ts +55 -0
  111. package/dist/esm/services/apiGateway/index.js +51 -0
  112. package/dist/esm/services/authProvider/browser.d.ts +61 -0
  113. package/dist/esm/services/authProvider/browser.js +119 -0
  114. package/dist/esm/services/authProvider/decryption.d.ts +16 -0
  115. package/dist/esm/services/authProvider/decryption.js +61 -0
  116. package/dist/esm/services/authProvider/index.d.ts +42 -0
  117. package/dist/esm/services/authProvider/index.js +15 -0
  118. package/dist/esm/services/authProvider/subrequest.d.ts +16 -0
  119. package/dist/esm/services/authProvider/subrequest.js +36 -0
  120. package/dist/esm/services/authProvider/utils/embeddedAuthProvider.d.ts +20 -0
  121. package/dist/esm/services/authProvider/utils/embeddedAuthProvider.js +30 -0
  122. package/dist/esm/services/exercisesGateway/index.d.ts +74 -0
  123. package/dist/esm/services/exercisesGateway/index.js +69 -0
  124. package/dist/esm/services/lrsGateway/attempt-utils.d.ts +62 -0
  125. package/dist/esm/services/lrsGateway/attempt-utils.js +251 -0
  126. package/dist/esm/services/lrsGateway/file-system.d.ts +15 -0
  127. package/dist/esm/services/lrsGateway/file-system.js +96 -0
  128. package/dist/esm/services/lrsGateway/index.d.ts +110 -0
  129. package/dist/esm/services/lrsGateway/index.js +87 -0
  130. package/dist/esm/services/searchProvider/index.d.ts +19 -0
  131. package/dist/esm/services/searchProvider/index.js +1 -0
  132. package/dist/esm/services/searchProvider/memorySearchTheBadWay.d.ts +12 -0
  133. package/dist/esm/services/searchProvider/memorySearchTheBadWay.js +53 -0
  134. package/dist/esm/services/versionedDocumentStore/dynamodb.d.ts +23 -0
  135. package/dist/esm/services/versionedDocumentStore/dynamodb.js +147 -0
  136. package/dist/esm/services/versionedDocumentStore/file-system.d.ts +25 -0
  137. package/dist/esm/services/versionedDocumentStore/file-system.js +81 -0
  138. package/dist/esm/services/versionedDocumentStore/index.d.ts +23 -0
  139. package/dist/esm/services/versionedDocumentStore/index.js +1 -0
  140. package/dist/esm/tsconfig.withoutspecs.esm.tsbuildinfo +1 -0
  141. package/dist/esm/types.d.ts +6 -0
  142. package/dist/esm/types.js +1 -0
  143. package/package.json +24 -8
  144. package/dist/tsconfig.tsbuildinfo +0 -1
  145. package/dist/tsconfig.withoutspecs.tsbuildinfo +0 -1
@@ -0,0 +1,147 @@
1
+ import { DynamoDB, PutItemCommand, QueryCommand, ScanCommand } from '@aws-sdk/client-dynamodb';
2
+ import { once } from '../..';
3
+ import { resolveConfigValue } from '../../config';
4
+ import { ifDefined, isPlainObject } from '../../guards';
5
+ const dynamodb = once(() => new DynamoDB({ apiVersion: '2012-08-10' }));
6
+ const encodeDynamoAttribute = (value) => {
7
+ if (typeof value === 'string') {
8
+ return { S: value };
9
+ }
10
+ if (typeof value === 'number') {
11
+ return { N: value.toString() };
12
+ }
13
+ if (typeof value === 'boolean') {
14
+ return { BOOL: value };
15
+ }
16
+ if (value === null) {
17
+ return { NULL: true };
18
+ }
19
+ if (value instanceof Array) {
20
+ return { L: value.map(encodeDynamoAttribute) };
21
+ }
22
+ if (isPlainObject(value)) {
23
+ return { M: encodeDynamoDocument(value) };
24
+ }
25
+ throw new Error(`unknown attribute type ${typeof value} with value ${value}.`);
26
+ };
27
+ const encodeDynamoDocument = (base) => Object.fromEntries(Object.entries(base).map(([key, value]) => ([key, encodeDynamoAttribute(value)])));
28
+ const decodeDynamoAttribute = (value) => {
29
+ if (value.S !== undefined) {
30
+ return value.S;
31
+ }
32
+ if (value.N !== undefined) {
33
+ return parseFloat(value.N);
34
+ }
35
+ if (value.BOOL !== undefined) {
36
+ return value.BOOL;
37
+ }
38
+ if (value.NULL !== undefined) {
39
+ return null;
40
+ }
41
+ if (value.L !== undefined) {
42
+ return value.L.map(decodeDynamoAttribute);
43
+ }
44
+ if (value.M !== undefined) {
45
+ return decodeDynamoDocument(value.M);
46
+ }
47
+ throw new Error(`unknown attribute type: ${JSON.stringify(value)}.`);
48
+ };
49
+ const decodeDynamoDocument = (document) => Object.fromEntries(Object.entries(document).map(([key, value]) => ([key, decodeDynamoAttribute(value)])));
50
+ // i'm not really excited about getAuthor being required, but ts is getting confused about the type when unspecified
51
+ export const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) => ({ profile }, hashKey, getAuthor) => {
52
+ const options = ifDefined(initializer, {});
53
+ const tableName = once(() => resolveConfigValue(configProvider[ifDefined(options.configSpace, 'dynamodb')].tableName));
54
+ return {
55
+ loadAllDocumentsTheBadWay: profile.track('versionedDocumentStore.loadAllDocumentsTheBadWay', () => async () => {
56
+ const loadAllResults = async (ExclusiveStartKey) => {
57
+ var _a;
58
+ const cmd = new ScanCommand({ TableName: await tableName(), ExclusiveStartKey });
59
+ const result = await dynamodb().send(cmd);
60
+ const resultItems = ((_a = result.Items) === null || _a === void 0 ? void 0 : _a.map(decodeDynamoDocument)) || [];
61
+ if (result.LastEvaluatedKey) {
62
+ return [...resultItems, ...await loadAllResults(result.LastEvaluatedKey)];
63
+ }
64
+ return resultItems;
65
+ };
66
+ const allResults = await loadAllResults().then(results => results.reduce((result, document) => {
67
+ const current = result.get(document[hashKey]);
68
+ if (!current || current.timestamp < document.timestamp) {
69
+ return result.set(document[hashKey], document);
70
+ }
71
+ return result;
72
+ }, new Map()));
73
+ return Array.from(allResults.values());
74
+ }),
75
+ getVersions: profile.track('versionedDocumentStore.getVersions', () => async (id, startVersion) => {
76
+ const cmd = new QueryCommand({
77
+ TableName: await tableName(),
78
+ KeyConditionExpression: '#hk = :hkv',
79
+ ExpressionAttributeValues: {
80
+ ':hkv': encodeDynamoAttribute(id)
81
+ },
82
+ ExpressionAttributeNames: {
83
+ '#hk': hashKey.toString()
84
+ },
85
+ ...(startVersion
86
+ ? { ExclusiveStartKey: {
87
+ [hashKey]: encodeDynamoAttribute(id),
88
+ timestamp: { N: startVersion.toString() }
89
+ } }
90
+ : {}),
91
+ ScanIndexForward: false,
92
+ });
93
+ return dynamodb().send(cmd).then(result => {
94
+ var _a;
95
+ const items = (_a = result.Items) === null || _a === void 0 ? void 0 : _a.map(decodeDynamoDocument);
96
+ if (!items || items.length === 0) {
97
+ return undefined;
98
+ }
99
+ return {
100
+ items,
101
+ nextPageToken: result.LastEvaluatedKey ? decodeDynamoDocument(result.LastEvaluatedKey).timestamp : undefined
102
+ };
103
+ });
104
+ }),
105
+ getItem: profile.track('versionedDocumentStore.getItem', () => async (id, timestamp) => {
106
+ let keyConditionExpression = '#hk = :hkv';
107
+ const expressionAttributeNames = {
108
+ '#hk': hashKey.toString()
109
+ };
110
+ const expressionAttributeValues = {
111
+ ':hkv': encodeDynamoAttribute(id)
112
+ };
113
+ if (timestamp) {
114
+ keyConditionExpression += ' and #ts = :tsv';
115
+ expressionAttributeNames['#ts'] = 'timestamp';
116
+ expressionAttributeValues[':tsv'] = encodeDynamoAttribute(timestamp);
117
+ }
118
+ const cmd = new QueryCommand({
119
+ TableName: await tableName(),
120
+ KeyConditionExpression: keyConditionExpression,
121
+ ExpressionAttributeNames: expressionAttributeNames,
122
+ ExpressionAttributeValues: expressionAttributeValues,
123
+ ScanIndexForward: false,
124
+ Limit: 1
125
+ });
126
+ return dynamodb().send(cmd).then(result => {
127
+ var _a;
128
+ return (_a = result.Items) === null || _a === void 0 ? void 0 : _a.map(decodeDynamoDocument)[0];
129
+ });
130
+ }),
131
+ putItem: profile.track('versionedDocumentStore.putItem', () => async (item, ...authorArgs) => {
132
+ // this getAuthor type is terrible
133
+ const author = getAuthor ? await getAuthor(...authorArgs) : authorArgs[0];
134
+ const document = {
135
+ ...item,
136
+ timestamp: new Date().getTime(),
137
+ author
138
+ };
139
+ const cmd = new PutItemCommand({
140
+ TableName: await tableName(),
141
+ Item: encodeDynamoDocument(document),
142
+ });
143
+ return dynamodb().send(cmd)
144
+ .then(() => document);
145
+ }),
146
+ };
147
+ };
@@ -0,0 +1,25 @@
1
+ import { ConfigProviderForConfig } from '../../config';
2
+ import { Track } from '../../profile';
3
+ import { TDocument, VersionedDocumentAuthor } from '.';
4
+ declare type Config = {
5
+ tableName: string;
6
+ };
7
+ interface Initializer<C> {
8
+ dataDir: string;
9
+ fs?: Pick<typeof import('fs'), 'readFile' | 'writeFile'>;
10
+ configSpace?: C;
11
+ }
12
+ export declare const fileSystemVersionedDocumentStore: <C extends string = "fileSystem">(initializer: Initializer<C>) => <T extends TDocument<T>>() => (configProvider: { [key in C]: {
13
+ tableName: import("../../config").ConfigValueProvider<string>;
14
+ }; }) => <K extends keyof T, A extends ((...a: any[]) => Promise<VersionedDocumentAuthor>) | undefined>({ profile }: {
15
+ profile: Track;
16
+ }, hashKey: K, getAuthor: A) => {
17
+ loadAllDocumentsTheBadWay: () => Promise<T[]>;
18
+ getVersions: (id: T[K], startVersion?: number | undefined) => Promise<{
19
+ items: T[];
20
+ nextPageToken: number | undefined;
21
+ } | undefined>;
22
+ getItem: (id: T[K], timestamp?: number | undefined) => Promise<T | undefined>;
23
+ putItem: (item: Omit<T, "timestamp" | "author">, ...authorArgs: A extends Function ? Parameters<A> : [VersionedDocumentAuthor]) => Promise<T>;
24
+ };
25
+ export {};
@@ -0,0 +1,81 @@
1
+ import * as fsModule from 'fs';
2
+ import path from 'path';
3
+ import { hashValue } from '../..';
4
+ import { resolveConfigValue } from '../../config';
5
+ import { ifDefined } from '../../guards';
6
+ const PAGE_LIMIT = 5;
7
+ export const fileSystemVersionedDocumentStore = (initializer) => () => (configProvider) => ({ profile }, hashKey, getAuthor) => {
8
+ const tableName = resolveConfigValue(configProvider[initializer.configSpace || 'fileSystem'].tableName);
9
+ const filePath = tableName.then((table) => path.join(initializer.dataDir, table));
10
+ const { readFile, writeFile } = ifDefined(initializer.fs, fsModule);
11
+ let data;
12
+ const load = filePath.then(path => new Promise(resolve => {
13
+ readFile(path, (err, readData) => {
14
+ if (err) {
15
+ console.error(err);
16
+ }
17
+ else {
18
+ try {
19
+ data = JSON.parse(readData.toString());
20
+ if (typeof data !== 'object') {
21
+ data = undefined;
22
+ }
23
+ }
24
+ catch (e) {
25
+ console.error(e);
26
+ }
27
+ }
28
+ resolve();
29
+ });
30
+ }));
31
+ let previousSave;
32
+ return {
33
+ loadAllDocumentsTheBadWay: profile.track('versionedDocumentStore.loadAllDocumentsTheBadWay', () => async () => {
34
+ await load;
35
+ return Object.entries(data || []).map(([, versions]) => {
36
+ const versionsList = Object.values(versions);
37
+ return versionsList[versionsList.length - 1];
38
+ });
39
+ }),
40
+ getVersions: profile.track('versionedDocumentStore.getVersions', () => async (id, startVersion) => {
41
+ await load;
42
+ const versions = data === null || data === void 0 ? void 0 : data[hashValue(id)];
43
+ const versionsList = versions ? Object.values(versions).reverse() : undefined;
44
+ if (!versions || !versionsList) {
45
+ return undefined;
46
+ }
47
+ const startIndex = startVersion ? versionsList.indexOf(versions[startVersion.toString()]) + 1 : 0;
48
+ const items = versionsList.slice(startIndex, startIndex + PAGE_LIMIT);
49
+ const hasMore = (startIndex + 5) < versionsList.length;
50
+ return {
51
+ items,
52
+ nextPageToken: hasMore ? items[items.length - 1].timestamp : undefined
53
+ };
54
+ }),
55
+ getItem: profile.track('versionedDocumentStore.getItem', () => async (id, timestamp) => {
56
+ await load;
57
+ const versions = data === null || data === void 0 ? void 0 : data[hashValue(id)];
58
+ if (timestamp) {
59
+ return versions === null || versions === void 0 ? void 0 : versions[timestamp];
60
+ }
61
+ const versionsList = versions ? Object.values(versions) : [];
62
+ return versionsList[versionsList.length - 1];
63
+ }),
64
+ putItem: profile.track('versionedDocumentStore.putItem', () => async (item, ...authorArgs) => {
65
+ await load;
66
+ await previousSave;
67
+ const save = previousSave = new Promise(resolve => (async () => {
68
+ // this getAuthor type is terrible
69
+ const author = getAuthor ? await getAuthor(...authorArgs) : authorArgs[0];
70
+ const document = { ...item, timestamp: new Date().getTime(), author };
71
+ const hash = hashValue(document[hashKey]);
72
+ const path = await filePath;
73
+ data = data || {};
74
+ const versions = data[hash] = data[hash] || {};
75
+ versions[document.timestamp] = document;
76
+ writeFile(path, JSON.stringify(data, null, 2), () => resolve(document));
77
+ })());
78
+ return await save;
79
+ }),
80
+ };
81
+ };
@@ -0,0 +1,23 @@
1
+ import { dynamoVersionedDocumentStore } from './dynamodb';
2
+ export declare type DocumentBaseValueTypes = number | boolean | string | null | DocumentBaseMapType | DocumentBaseListType;
3
+ export declare type DocumentBaseMapType = {
4
+ [key: string]: DocumentBaseValueTypes;
5
+ };
6
+ export declare type DocumentBaseListType = DocumentBaseValueTypes[];
7
+ export declare type VersionedDocumentAuthor = {
8
+ type: 'user';
9
+ uuid: string;
10
+ name: string;
11
+ reason?: string;
12
+ } | {
13
+ type: 'system';
14
+ reason: string;
15
+ };
16
+ export declare type VersionedDocumentRequiredFields = {
17
+ timestamp: number;
18
+ author: VersionedDocumentAuthor;
19
+ };
20
+ export declare type TDocument<T> = {
21
+ [k in keyof T]: DocumentBaseValueTypes;
22
+ } & VersionedDocumentRequiredFields;
23
+ export declare type VersionedDocumentStoreCreator = typeof dynamoVersionedDocumentStore;
@@ -0,0 +1 @@
1
+ export {};