@openstax/ts-utils 1.6.1 → 1.7.0

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.
@@ -106,7 +106,18 @@ export const mapFind = (array, mapper, predicate = (r) => !!r) => {
106
106
  export const once = (fn) => {
107
107
  const initialValue = {};
108
108
  let result = initialValue;
109
- return ((...args) => result === initialValue ? (result = fn(...args)) : result);
109
+ return ((...args) => {
110
+ if (result !== initialValue) {
111
+ return result;
112
+ }
113
+ result = fn(...args);
114
+ if (typeof result === 'object' && result instanceof Promise) {
115
+ // Clear the result when possible but do not return a Promise that resolves to the initialValue
116
+ result.catch(() => result = initialValue);
117
+ }
118
+ // If this is a rejected Promise, it should be returned before catch() actually overwrites it
119
+ return result;
120
+ });
110
121
  };
111
122
  /**
112
123
  * memoizes a function with any number of arguments
@@ -29,6 +29,10 @@ export interface Window {
29
29
  export declare const browserAuthProvider: <C extends string = "auth">({ window, configSpace }: Initializer<C>) => (configProvider: { [key in C]: {
30
30
  accountsBase: import("../../config").ConfigValueProvider<string>;
31
31
  }; }) => {
32
+ /**
33
+ * gets the authentication token
34
+ */
35
+ getAuthToken: () => Promise<string | null>;
32
36
  /**
33
37
  * adds auth parameters to the url. this is only safe to use when using javascript to navigate
34
38
  * within the current window, eg `window.location = 'https://my.otherservice.com';` anchors
@@ -17,6 +17,9 @@ export const browserAuthProvider = ({ window, configSpace }) => (configProvider)
17
17
  let userData = {
18
18
  token: [null, embeddedQueryValue].includes(authQuery) ? null : authQuery
19
19
  };
20
+ const getAuthToken = async () => {
21
+ return (await getUserData()).token;
22
+ };
20
23
  const getAuthorizedLinkUrl = (urlString) => {
21
24
  const url = new URL(urlString);
22
25
  if (userData.token) {
@@ -89,6 +92,10 @@ export const browserAuthProvider = ({ window, configSpace }) => (configProvider)
89
92
  return (await getUserData()).user;
90
93
  };
91
94
  return {
95
+ /**
96
+ * gets the authentication token
97
+ */
98
+ getAuthToken,
92
99
  /**
93
100
  * adds auth parameters to the url. this is only safe to use when using javascript to navigate
94
101
  * within the current window, eg `window.location = 'https://my.otherservice.com';` anchors
@@ -9,7 +9,7 @@ export interface Grade {
9
9
  comment?: string;
10
10
  activityProgress: 'Initialized' | 'Started' | 'inProgress' | 'Submitted' | 'Completed';
11
11
  gradingProgress: 'FullyGraded' | 'Pending' | 'PendingManual' | 'Failed' | 'NotReady';
12
- userId: string;
12
+ userId?: string;
13
13
  }
14
14
  export declare const getRegistrationAttemptInfo: (lrs: LrsGateway, registration: string, options?: {
15
15
  activity?: string | undefined;
@@ -25,7 +25,7 @@ export declare const getScoreGrade: (score: {
25
25
  raw?: number;
26
26
  min?: number;
27
27
  max?: number;
28
- }, completed: boolean, userId: string, maxScore?: number | undefined) => Grade;
28
+ }, completed: boolean, userId?: string | undefined, maxScore?: number | undefined) => Grade;
29
29
  export declare type Progress = {
30
30
  scaled: number;
31
31
  max?: number;
@@ -34,6 +34,7 @@ export declare type Progress = {
34
34
  export declare type GradeAndProgress = {
35
35
  grade: Grade;
36
36
  progress: Progress;
37
+ name?: string;
37
38
  };
38
39
  export declare const getCurrentGrade: (services: {
39
40
  lrs: LrsGateway;
@@ -41,6 +42,7 @@ export declare const getCurrentGrade: (services: {
41
42
  }, registration: string, options?: {
42
43
  currentPreference?: "latest" | "oldest" | undefined;
43
44
  incompleteAttemptCallback?: ((info: ActivityState) => Promise<GradeAndProgress>) | undefined;
45
+ name?: string | undefined;
44
46
  scoreMaximum?: number | undefined;
45
47
  userId?: string | undefined;
46
48
  } | undefined) => Promise<GradeAndProgress | null>;
@@ -40,17 +40,20 @@ export const getScoreGrade = (score, completed, userId, maxScore) => {
40
40
  scoreGiven: roundToPrecision(scoreGiven, -2),
41
41
  };
42
42
  };
43
- // These methods assigns 0's to incomplete activities
44
- const getCompletedActivityStateGradeAndProgress = (state, userId, maxScore) => {
43
+ // These methods assign 0's to incomplete activities
44
+ const getCompletedActivityStateGradeAndProgress = ({ name, scoreMaximum, state, userId }) => {
45
45
  var _a, _b;
46
46
  return ({
47
- grade: getScoreGrade(((_b = (_a = state.currentAttemptCompleted) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.score) || {}, !!state.currentAttemptCompleted, userId, maxScore),
47
+ grade: getScoreGrade(((_b = (_a = state.currentAttemptCompleted) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.score) || {}, !!state.currentAttemptCompleted, userId, scoreMaximum),
48
48
  progress: {
49
49
  scaled: state.currentAttemptCompleted ? 1 : 0,
50
50
  },
51
+ name,
51
52
  });
52
53
  };
53
- const getCompletedUserInfosGradeAndProgress = (infos, scoreMaximum) => infos.map(({ data, fullName, platformUserId }) => getCompletedActivityStateGradeAndProgress(data, platformUserId !== null && platformUserId !== void 0 ? platformUserId : fullName, scoreMaximum));
54
+ const getCompletedUserInfosGradeAndProgress = (infos, scoreMaximum) => infos.map(({ data, fullName, platformUserId }) => getCompletedActivityStateGradeAndProgress({
55
+ name: fullName, scoreMaximum, userId: platformUserId, state: data
56
+ }));
54
57
  export const getCurrentGrade = async (services, registration, options) => {
55
58
  var _a;
56
59
  const user = await services.ltiAuthProvider.getUser();
@@ -58,14 +61,14 @@ export const getCurrentGrade = async (services, registration, options) => {
58
61
  return null;
59
62
  }
60
63
  const userId = (_a = options === null || options === void 0 ? void 0 : options.userId) !== null && _a !== void 0 ? _a : user.uuid;
61
- const { currentPreference, incompleteAttemptCallback, scoreMaximum } = options !== null && options !== void 0 ? options : {};
64
+ const { currentPreference, incompleteAttemptCallback, name, scoreMaximum } = options !== null && options !== void 0 ? options : {};
62
65
  const infoPerUser = await getRegistrationAttemptInfo(services.lrs, registration, { currentPreference });
63
66
  const userInfo = infoPerUser[user.uuid];
64
67
  if (!userInfo) {
65
- return getCompletedActivityStateGradeAndProgress(resolveAttemptInfo([]), userId, scoreMaximum);
68
+ return getCompletedActivityStateGradeAndProgress({ name, scoreMaximum, state: resolveAttemptInfo([]), userId });
66
69
  }
67
70
  if (userInfo.currentAttemptCompleted || !incompleteAttemptCallback) {
68
- return getCompletedActivityStateGradeAndProgress(userInfo, userId, scoreMaximum);
71
+ return getCompletedActivityStateGradeAndProgress({ name, scoreMaximum, state: userInfo, userId });
69
72
  }
70
73
  return incompleteAttemptCallback(userInfo);
71
74
  };