@openstax/ts-utils 1.19.0 → 1.20.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.
@@ -0,0 +1,8 @@
1
+ import { GenericFetch } from '.';
2
+ interface Options {
3
+ status?: number[];
4
+ onFail?: boolean;
5
+ retries: number;
6
+ }
7
+ export declare const fetchStatusRetry: (base: GenericFetch, options: Options) => GenericFetch;
8
+ export {};
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchStatusRetry = void 0;
4
+ const fetchStatusRetry = (base, options) => {
5
+ const fetchTry = (retries, ...params) => {
6
+ return base(...params)
7
+ .catch(e => options.onFail && retries > 0
8
+ ? fetchTry(retries - 1, ...params)
9
+ : Promise.reject(e))
10
+ .then(async (r) => {
11
+ var _a;
12
+ const shouldHandleStatus = (_a = options.status) === null || _a === void 0 ? void 0 : _a.includes(r.status);
13
+ if (shouldHandleStatus && retries > 0) {
14
+ return fetchTry(retries - 1, ...params);
15
+ }
16
+ else if (shouldHandleStatus) {
17
+ throw new Error(`fetch failed after ${options.retries} retries. ${params[0]} -- ${r.status}: ${await r.text()}`);
18
+ }
19
+ return r;
20
+ });
21
+ };
22
+ return (...params) => fetchTry(options.retries, ...params);
23
+ };
24
+ exports.fetchStatusRetry = fetchStatusRetry;
@@ -32,6 +32,7 @@ const query_string_1 = __importDefault(require("query-string"));
32
32
  const __1 = require("../..");
33
33
  const config_1 = require("../../config");
34
34
  const errors_1 = require("../../errors");
35
+ const fetchStatusRetry_1 = require("../../fetch/fetchStatusRetry");
35
36
  /** Pulls the content out of a response based on the content type */
36
37
  const loadResponse = (response) => () => {
37
38
  const [contentType] = (response.headers.get('content-type') || '').split(';');
@@ -57,7 +58,8 @@ const makeRouteClient = (initializer, config, route, authProvider) => {
57
58
  const url = await renderUrl({ params, query });
58
59
  const body = payload ? JSON.stringify(payload) : undefined;
59
60
  const baseOptions = (0, __1.merge)((await (authProvider === null || authProvider === void 0 ? void 0 : authProvider.getAuthorizedFetchConfig())) || {}, fetchConfig || {});
60
- return initializer.fetch(url, (0, __1.merge)(baseOptions, {
61
+ const fetcher = (0, fetchStatusRetry_1.fetchStatusRetry)(initializer.fetch, { retries: 1, status: [502], onFail: true });
62
+ return fetcher(url, (0, __1.merge)(baseOptions, {
61
63
  method: route.method,
62
64
  body,
63
65
  headers: {
@@ -0,0 +1,5 @@
1
+ import { XapiStatement, EagerXapiStatement } from ".";
2
+ import { User } from "../authProvider";
3
+ export declare const addStatementDefaultFields: (statement: Pick<XapiStatement, 'object' | 'verb' | 'context' | 'result'> & {
4
+ id?: string;
5
+ }, user: User) => EagerXapiStatement;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.addStatementDefaultFields = void 0;
7
+ const formatISO_1 = __importDefault(require("date-fns/formatISO"));
8
+ const uuid_1 = require("uuid");
9
+ const addStatementDefaultFields = (statement, user) => ({
10
+ id: (0, uuid_1.v4)(),
11
+ ...statement,
12
+ actor: {
13
+ account: {
14
+ homePage: 'https://openstax.org',
15
+ name: user.uuid,
16
+ },
17
+ objectType: 'Agent',
18
+ },
19
+ timestamp: (0, formatISO_1.default)(new Date())
20
+ });
21
+ exports.addStatementDefaultFields = addStatementDefaultFields;
@@ -80,9 +80,9 @@ export declare const lrsGateway: <C extends string = "lrs">(initializer: Initial
80
80
  lrsHost: import("../../config").ConfigValueProvider<string>;
81
81
  lrsAuthorization: import("../../config").ConfigValueProvider<string>;
82
82
  }; }) => (authProvider: AuthProvider) => {
83
- putXapiStatements: (statements: Array<Pick<XapiStatement, 'object' | 'verb' | 'context' | 'result'> & {
83
+ putXapiStatements: (statements: Array<(Pick<XapiStatement, 'object' | 'verb' | 'context' | 'result'> & {
84
84
  id?: string;
85
- }>) => Promise<EagerXapiStatement[]>;
85
+ }) | EagerXapiStatement>) => Promise<EagerXapiStatement[]>;
86
86
  getXapiStatements: (params: {
87
87
  verb?: string | undefined;
88
88
  activity?: string | undefined;
@@ -22,39 +22,28 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
26
  exports.lrsGateway = void 0;
30
- const formatISO_1 = __importDefault(require("date-fns/formatISO"));
31
27
  const queryString = __importStar(require("query-string"));
32
28
  const __1 = require("../..");
33
29
  const assertions_1 = require("../../assertions");
34
30
  const config_1 = require("../../config");
35
31
  const errors_1 = require("../../errors");
32
+ const fetchStatusRetry_1 = require("../../fetch/fetchStatusRetry");
36
33
  const guards_1 = require("../../guards");
37
34
  const routing_1 = require("../../routing");
35
+ const addStatementDefaultFields_1 = require("./addStatementDefaultFields");
38
36
  const lrsGateway = (initializer) => (configProvider) => {
39
37
  const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'lrs')];
40
38
  const lrsHost = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.lrsHost));
41
39
  const lrsAuthorization = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.lrsAuthorization));
40
+ const fetcher = (0, fetchStatusRetry_1.fetchStatusRetry)(initializer.fetch, { retries: 1, status: [502], onFail: true });
42
41
  return (authProvider) => {
43
42
  // Note: This method actually uses POST
44
43
  const putXapiStatements = async (statements) => {
45
44
  const user = (0, assertions_1.assertDefined)(await authProvider.getUser(), new errors_1.UnauthorizedError);
46
- const statementsWithDefaults = statements.map(statement => ({
47
- ...statement,
48
- actor: {
49
- account: {
50
- homePage: 'https://openstax.org',
51
- name: user.uuid,
52
- },
53
- objectType: 'Agent',
54
- },
55
- timestamp: (0, formatISO_1.default)(new Date())
56
- }));
57
- const response = await initializer.fetch((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements', {
45
+ const statementsWithDefaults = statements.map(statement => (0, addStatementDefaultFields_1.addStatementDefaultFields)(statement, user));
46
+ const response = await fetcher((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements', {
58
47
  body: JSON.stringify(statementsWithDefaults),
59
48
  headers: {
60
49
  Authorization: await lrsAuthorization(),
@@ -68,8 +57,8 @@ const lrsGateway = (initializer) => (configProvider) => {
68
57
 
69
58
  ${await response.text()}`);
70
59
  }
71
- const ids = await response.json();
72
- return ids.map((id, index) => ({ id, ...statementsWithDefaults[index] }));
60
+ await response.json();
61
+ return statementsWithDefaults;
73
62
  };
74
63
  // Note: This code does not currently handle a single statement response,
75
64
  // which can return 404 if the statement is not found
@@ -82,13 +71,13 @@ ${await response.text()}`);
82
71
  }
83
72
  return response.json();
84
73
  };
85
- const getMoreXapiStatements = async (more) => formatGetXapiStatementsResponse(initializer.fetch((await lrsHost()).replace(/\/+$/, '') + more, {
74
+ const getMoreXapiStatements = async (more) => formatGetXapiStatementsResponse(fetcher((await lrsHost()).replace(/\/+$/, '') + more, {
86
75
  headers: {
87
76
  Authorization: await lrsAuthorization(),
88
77
  'X-Experience-API-Version': '1.0.0',
89
78
  },
90
79
  }));
91
- const fetchXapiStatements = async ({ user, anyUser, ...options }) => initializer.fetch((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements?' + queryString.stringify({
80
+ const fetchXapiStatements = async ({ user, anyUser, ...options }) => fetcher((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements?' + queryString.stringify({
92
81
  ...options,
93
82
  ...(anyUser === true ? {} : {
94
83
  agent: JSON.stringify({