scorm-again 1.7.1 → 2.0.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.
Files changed (85) hide show
  1. package/.babelrc +18 -7
  2. package/.github/dependabot.yml +5 -0
  3. package/.github/workflows/main.yml +79 -0
  4. package/.jsdoc.json +4 -5
  5. package/.mocharc.json +8 -0
  6. package/.run/Mocha Unit Tests.run.xml +5 -2
  7. package/CONTRIBUTING.md +1 -1
  8. package/README.md +14 -1
  9. package/dist/aicc.js +3661 -7170
  10. package/dist/aicc.js.map +1 -1
  11. package/dist/aicc.min.js +2 -40
  12. package/dist/aicc.min.js.map +1 -0
  13. package/dist/scorm-again.js +5671 -10695
  14. package/dist/scorm-again.js.map +1 -1
  15. package/dist/scorm-again.min.js +2 -52
  16. package/dist/scorm-again.min.js.map +1 -0
  17. package/dist/scorm12.js +2871 -5433
  18. package/dist/scorm12.js.map +1 -1
  19. package/dist/scorm12.min.js +2 -34
  20. package/dist/scorm12.min.js.map +1 -0
  21. package/dist/scorm2004.js +3868 -6797
  22. package/dist/scorm2004.js.map +1 -1
  23. package/dist/scorm2004.min.js +2 -40
  24. package/dist/scorm2004.min.js.map +1 -0
  25. package/eslint.config.js +21 -0
  26. package/package.json +72 -34
  27. package/results.json +34254 -0
  28. package/src/{AICC.js → AICC.ts} +27 -21
  29. package/src/BaseAPI.ts +1449 -0
  30. package/src/Scorm12API.ts +360 -0
  31. package/src/{Scorm2004API.js → Scorm2004API.ts} +245 -163
  32. package/src/cmi/aicc_cmi.ts +1248 -0
  33. package/src/cmi/common.ts +411 -0
  34. package/src/cmi/scorm12_cmi.ts +1426 -0
  35. package/src/cmi/scorm2004_cmi.ts +1874 -0
  36. package/src/constants/api_constants.ts +318 -0
  37. package/src/constants/error_codes.ts +88 -0
  38. package/src/constants/language_constants.ts +394 -0
  39. package/src/constants/regex.ts +97 -0
  40. package/src/constants/{response_constants.js → response_constants.ts} +67 -62
  41. package/src/exceptions.ts +133 -0
  42. package/src/exports/aicc.js +1 -1
  43. package/src/exports/scorm-again.js +3 -3
  44. package/src/exports/scorm12.js +1 -1
  45. package/src/exports/scorm2004.js +1 -1
  46. package/src/{utilities.js → utilities.ts} +114 -74
  47. package/tea.yaml +6 -0
  48. package/test/{AICC.spec.js → AICC.spec.ts} +70 -72
  49. package/test/Scorm12API.spec.ts +580 -0
  50. package/test/Scorm2004API.spec.ts +812 -0
  51. package/test/api_helpers.ts +176 -0
  52. package/test/cmi/{aicc_cmi.spec.js → aicc_cmi.spec.ts} +193 -209
  53. package/test/cmi/{scorm12_cmi.spec.js → scorm12_cmi.spec.ts} +251 -269
  54. package/test/cmi/scorm2004_cmi.spec.ts +1031 -0
  55. package/test/cmi_helpers.ts +207 -0
  56. package/test/exceptions.spec.ts +79 -0
  57. package/test/field_values.ts +202 -0
  58. package/test/utilities.spec.ts +322 -0
  59. package/tsconfig.json +18 -0
  60. package/webpack.config.js +65 -0
  61. package/.circleci/config.yml +0 -99
  62. package/.codeclimate.yml +0 -7
  63. package/.eslintrc.js +0 -36
  64. package/src/.flowconfig +0 -11
  65. package/src/BaseAPI.js +0 -1275
  66. package/src/Scorm12API.js +0 -308
  67. package/src/cmi/aicc_cmi.js +0 -1141
  68. package/src/cmi/common.js +0 -328
  69. package/src/cmi/scorm12_cmi.js +0 -1312
  70. package/src/cmi/scorm2004_cmi.js +0 -1692
  71. package/src/constants/api_constants.js +0 -218
  72. package/src/constants/error_codes.js +0 -87
  73. package/src/constants/language_constants.js +0 -76
  74. package/src/constants/regex.js +0 -84
  75. package/src/exceptions.js +0 -104
  76. package/test/Scorm12API.spec.js +0 -528
  77. package/test/Scorm2004API.spec.js +0 -775
  78. package/test/abstract_classes.spec.js +0 -17
  79. package/test/api_helpers.js +0 -128
  80. package/test/cmi/scorm2004_cmi.spec.js +0 -1066
  81. package/test/cmi_helpers.js +0 -161
  82. package/test/exceptions.spec.js +0 -71
  83. package/test/field_values.js +0 -353
  84. package/test/utilities.spec.js +0 -339
  85. package/webpack.js +0 -78
@@ -0,0 +1,360 @@
1
+ import BaseAPI, { RefObject, ResultObject, Settings } from "./BaseAPI";
2
+ import {
3
+ CMI,
4
+ CMIInteractionsCorrectResponsesObject,
5
+ CMIInteractionsObject,
6
+ CMIInteractionsObjectivesObject,
7
+ CMIObjectivesObject,
8
+ NAV,
9
+ } from "./cmi/scorm12_cmi";
10
+ import * as Utilities from "./utilities";
11
+ import APIConstants from "./constants/api_constants";
12
+ import ErrorCodes, { ErrorCode } from "./constants/error_codes";
13
+ import { BaseCMI } from "./cmi/common";
14
+
15
+ const scorm12_constants = APIConstants.scorm12;
16
+ const global_constants = APIConstants.global;
17
+ const scorm12_error_codes: ErrorCode = ErrorCodes.scorm12;
18
+
19
+ /**
20
+ * API class for SCORM 1.2
21
+ */
22
+ export default class Scorm12API extends BaseAPI {
23
+ /**
24
+ * Constructor for SCORM 1.2 API
25
+ * @param {object} settings
26
+ */
27
+ constructor(settings?: Settings) {
28
+ if (settings) {
29
+ if (settings.mastery_override === undefined) {
30
+ settings.mastery_override = false;
31
+ }
32
+ }
33
+
34
+ super(scorm12_error_codes, settings);
35
+
36
+ this.cmi = new CMI();
37
+ this.nav = new NAV();
38
+
39
+ // Rename functions to match 1.2 Spec and expose to modules
40
+ this.LMSInitialize = this.lmsInitialize;
41
+ this.LMSFinish = this.lmsFinish;
42
+ this.LMSGetValue = this.lmsGetValue;
43
+ this.LMSSetValue = this.lmsSetValue;
44
+ this.LMSCommit = this.lmsCommit;
45
+ this.LMSGetLastError = this.lmsGetLastError;
46
+ this.LMSGetErrorString = this.lmsGetErrorString;
47
+ this.LMSGetDiagnostic = this.lmsGetDiagnostic;
48
+ }
49
+
50
+ public cmi: CMI;
51
+ public nav: NAV;
52
+
53
+ public LMSInitialize: () => string;
54
+ public LMSFinish: () => string;
55
+ public LMSGetValue: (CMIElement: string) => string;
56
+ public LMSSetValue: (CMIElement: string, value: any) => string;
57
+ public LMSCommit: () => string;
58
+ public LMSGetLastError: () => string;
59
+ public LMSGetErrorString: (CMIErrorCode: string) => string;
60
+ public LMSGetDiagnostic: (CMIErrorCode: string) => string;
61
+
62
+ /**
63
+ * lmsInitialize function from SCORM 1.2 Spec
64
+ *
65
+ * @return {string} bool
66
+ */
67
+ lmsInitialize(): string {
68
+ this.cmi.initialize();
69
+ return this.initialize(
70
+ "LMSInitialize",
71
+ "LMS was already initialized!",
72
+ "LMS is already finished!",
73
+ );
74
+ }
75
+
76
+ /**
77
+ * LMSFinish function from SCORM 1.2 Spec
78
+ *
79
+ * @return {string} bool
80
+ */
81
+ lmsFinish(): string {
82
+ const result = this.terminate("LMSFinish", true);
83
+
84
+ if (result === global_constants.SCORM_TRUE) {
85
+ if (this.nav.event !== "") {
86
+ if (this.nav.event === "continue") {
87
+ this.processListeners("SequenceNext");
88
+ } else {
89
+ this.processListeners("SequencePrevious");
90
+ }
91
+ } else if (this.settings.autoProgress) {
92
+ this.processListeners("SequenceNext");
93
+ }
94
+ }
95
+
96
+ return result;
97
+ }
98
+
99
+ /**
100
+ * LMSGetValue function from SCORM 1.2 Spec
101
+ *
102
+ * @param {string} CMIElement
103
+ * @return {string}
104
+ */
105
+ lmsGetValue(CMIElement: string): string {
106
+ return this.getValue("LMSGetValue", false, CMIElement);
107
+ }
108
+
109
+ /**
110
+ * LMSSetValue function from SCORM 1.2 Spec
111
+ *
112
+ * @param {string} CMIElement
113
+ * @param {*} value
114
+ * @return {string}
115
+ */
116
+ lmsSetValue(CMIElement: string, value: any): string {
117
+ return this.setValue("LMSSetValue", "LMSCommit", false, CMIElement, value);
118
+ }
119
+
120
+ /**
121
+ * LMSCommit function from SCORM 1.2 Spec
122
+ *
123
+ * @return {string} bool
124
+ */
125
+ lmsCommit(): string {
126
+ return this.commit("LMSCommit", false);
127
+ }
128
+
129
+ /**
130
+ * LMSGetLastError function from SCORM 1.2 Spec
131
+ *
132
+ * @return {string}
133
+ */
134
+ lmsGetLastError(): string {
135
+ return this.getLastError("LMSGetLastError");
136
+ }
137
+
138
+ /**
139
+ * LMSGetErrorString function from SCORM 1.2 Spec
140
+ *
141
+ * @param {string} CMIErrorCode
142
+ * @return {string}
143
+ */
144
+ lmsGetErrorString(CMIErrorCode: string): string {
145
+ return this.getErrorString("LMSGetErrorString", CMIErrorCode);
146
+ }
147
+
148
+ /**
149
+ * LMSGetDiagnostic function from SCORM 1.2 Spec
150
+ *
151
+ * @param {string} CMIErrorCode
152
+ * @return {string}
153
+ */
154
+ lmsGetDiagnostic(CMIErrorCode: string): string {
155
+ return this.getDiagnostic("LMSGetDiagnostic", CMIErrorCode);
156
+ }
157
+
158
+ /**
159
+ * Sets a value on the CMI Object
160
+ *
161
+ * @param {string} CMIElement
162
+ * @param {*} value
163
+ * @return {string}
164
+ */
165
+ setCMIValue(CMIElement: string, value: any): string {
166
+ return this._commonSetCMIValue("LMSSetValue", false, CMIElement, value);
167
+ }
168
+
169
+ /**
170
+ * Gets a value from the CMI Object
171
+ *
172
+ * @param {string} CMIElement
173
+ * @return {*}
174
+ */
175
+ getCMIValue(CMIElement: string): any {
176
+ return this._commonGetCMIValue("getCMIValue", false, CMIElement);
177
+ }
178
+
179
+ /**
180
+ * Gets or builds a new child element to add to the array.
181
+ *
182
+ * @param {string} CMIElement
183
+ * @param {*} _value
184
+ * @param {boolean} foundFirstIndex
185
+ * @return {BaseCMI|null}
186
+ */
187
+ getChildElement(
188
+ CMIElement: string,
189
+ _value: any,
190
+ foundFirstIndex: boolean,
191
+ ): BaseCMI | null {
192
+ if (this.stringMatches(CMIElement, "cmi\\.objectives\\.\\d+")) {
193
+ return new CMIObjectivesObject();
194
+ } else if (
195
+ foundFirstIndex &&
196
+ this.stringMatches(
197
+ CMIElement,
198
+ "cmi\\.interactions\\.\\d+\\.correct_responses\\.\\d+",
199
+ )
200
+ ) {
201
+ return new CMIInteractionsCorrectResponsesObject();
202
+ } else if (
203
+ foundFirstIndex &&
204
+ this.stringMatches(
205
+ CMIElement,
206
+ "cmi\\.interactions\\.\\d+\\.objectives\\.\\d+",
207
+ )
208
+ ) {
209
+ return new CMIInteractionsObjectivesObject();
210
+ } else if (
211
+ !foundFirstIndex &&
212
+ this.stringMatches(CMIElement, "cmi\\.interactions\\.\\d+")
213
+ ) {
214
+ return new CMIInteractionsObject();
215
+ }
216
+
217
+ return null;
218
+ }
219
+
220
+ /**
221
+ * Validates Correct Response values
222
+ *
223
+ * @param {string} _CMIElement
224
+ * @param {*} _value
225
+ */
226
+ validateCorrectResponse(_CMIElement: string, _value: any) {
227
+ // do nothing
228
+ }
229
+
230
+ /**
231
+ * Returns the message that corresponds to errorNumber.
232
+ *
233
+ * @param {number|string} errorNumber
234
+ * @param {boolean} detail
235
+ * @return {string}
236
+ */
237
+ getLmsErrorMessageDetails(
238
+ errorNumber: number | string,
239
+ detail: boolean,
240
+ ): string {
241
+ let basicMessage = "No Error";
242
+ let detailMessage = "No Error";
243
+
244
+ // Set error number to string since inconsistent from modules if string or number
245
+ errorNumber = String(errorNumber);
246
+ if (scorm12_constants.error_descriptions[errorNumber]) {
247
+ basicMessage =
248
+ scorm12_constants.error_descriptions[errorNumber].basicMessage;
249
+ detailMessage =
250
+ scorm12_constants.error_descriptions[errorNumber].detailMessage;
251
+ }
252
+
253
+ return detail ? detailMessage : basicMessage;
254
+ }
255
+
256
+ /**
257
+ * Replace the whole API with another
258
+ *
259
+ * @param {Scorm12API} newAPI
260
+ */
261
+ replaceWithAnotherScormAPI(newAPI: Scorm12API) {
262
+ // Data Model
263
+ this.cmi = newAPI.cmi;
264
+ }
265
+
266
+ /**
267
+ * Render the cmi object to the proper format for LMS commit
268
+ *
269
+ * @param {boolean} terminateCommit
270
+ * @return {object|Array}
271
+ */
272
+ renderCommitCMI(terminateCommit: boolean): object | Array<any> {
273
+ const cmiExport: RefObject = this.renderCMIToJSONObject();
274
+
275
+ if (terminateCommit) {
276
+ cmiExport.cmi.core.total_time = this.cmi.getCurrentTotalTime();
277
+ }
278
+
279
+ const result = [];
280
+ const flattened: RefObject = Utilities.flatten(cmiExport);
281
+ switch (this.settings.dataCommitFormat) {
282
+ case "flattened":
283
+ return Utilities.flatten(cmiExport);
284
+ case "params":
285
+ for (const item in flattened) {
286
+ if ({}.hasOwnProperty.call(flattened, item)) {
287
+ result.push(`${item}=${flattened[item]}`);
288
+ }
289
+ }
290
+ return result;
291
+ case "json":
292
+ default:
293
+ return cmiExport;
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Attempts to store the data to the LMS
299
+ *
300
+ * @param {boolean} terminateCommit
301
+ * @return {ResultObject}
302
+ */
303
+ storeData(terminateCommit: boolean): ResultObject {
304
+ if (terminateCommit) {
305
+ const originalStatus = this.cmi.core.lesson_status;
306
+ if (originalStatus === "not attempted") {
307
+ this.cmi.core.lesson_status = "completed";
308
+ }
309
+
310
+ if (this.cmi.core.lesson_mode === "normal") {
311
+ if (this.cmi.core.credit === "credit") {
312
+ if (
313
+ this.settings.mastery_override &&
314
+ this.cmi.student_data.mastery_score !== "" &&
315
+ this.cmi.core.score.raw !== ""
316
+ ) {
317
+ if (
318
+ parseFloat(this.cmi.core.score.raw) >=
319
+ parseFloat(this.cmi.student_data.mastery_score)
320
+ ) {
321
+ this.cmi.core.lesson_status = "passed";
322
+ } else {
323
+ this.cmi.core.lesson_status = "failed";
324
+ }
325
+ }
326
+ }
327
+ } else if (this.cmi.core.lesson_mode === "browse") {
328
+ if (
329
+ (this.startingData?.cmi?.core?.lesson_status || "") === "" &&
330
+ originalStatus === "not attempted"
331
+ ) {
332
+ this.cmi.core.lesson_status = "browsed";
333
+ }
334
+ }
335
+ }
336
+
337
+ const commitObject = this.renderCommitCMI(
338
+ terminateCommit || this.settings.alwaysSendTotalTime,
339
+ );
340
+
341
+ if (this.apiLogLevel === global_constants.LOG_LEVEL_DEBUG) {
342
+ console.debug(
343
+ "Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
344
+ );
345
+ console.debug(commitObject);
346
+ }
347
+ if (typeof this.settings.lmsCommitUrl === "string") {
348
+ return this.processHttpRequest(
349
+ this.settings.lmsCommitUrl,
350
+ commitObject,
351
+ terminateCommit,
352
+ );
353
+ } else {
354
+ return {
355
+ result: global_constants.SCORM_TRUE,
356
+ errorCode: 0,
357
+ };
358
+ }
359
+ }
360
+ }