scorm-again 2.0.0 → 2.1.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.
- package/.github/workflows/stale.yml +14 -0
- package/.run/{Mocha Unit Tests.run.xml → Mocha Unit Tests (watch).run.xml } +1 -1
- package/.run/Template Mocha.run.xml +17 -0
- package/README.md +171 -72
- package/dist/aicc.js +1441 -1140
- package/dist/aicc.js.map +1 -1
- package/dist/aicc.min.js +1 -1
- package/dist/aicc.min.js.map +1 -1
- package/dist/scorm-again.js +2703 -2212
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +1 -1
- package/dist/scorm-again.min.js.map +1 -1
- package/dist/scorm12.js +1069 -852
- package/dist/scorm12.js.map +1 -1
- package/dist/scorm12.min.js +1 -1
- package/dist/scorm12.min.js.map +1 -1
- package/dist/scorm2004.js +1861 -1571
- package/dist/scorm2004.js.map +1 -1
- package/dist/scorm2004.min.js +1 -1
- package/dist/scorm2004.min.js.map +1 -1
- package/package.json +10 -6
- package/src/AICC.ts +15 -17
- package/src/BaseAPI.ts +268 -417
- package/src/Scorm12API.ts +65 -38
- package/src/Scorm2004API.ts +151 -117
- package/src/cmi/aicc/attempts.ts +94 -0
- package/src/cmi/aicc/cmi.ts +100 -0
- package/src/cmi/aicc/core.ts +360 -0
- package/src/cmi/aicc/evaluation.ts +157 -0
- package/src/cmi/aicc/paths.ts +180 -0
- package/src/cmi/aicc/student_data.ts +86 -0
- package/src/cmi/aicc/student_demographics.ts +367 -0
- package/src/cmi/aicc/student_preferences.ts +176 -0
- package/src/cmi/aicc/tries.ts +116 -0
- package/src/cmi/aicc/validation.ts +25 -0
- package/src/cmi/common/array.ts +77 -0
- package/src/cmi/common/base_cmi.ts +46 -0
- package/src/cmi/common/score.ts +203 -0
- package/src/cmi/common/validation.ts +60 -0
- package/src/cmi/scorm12/cmi.ts +224 -0
- package/src/cmi/scorm12/interactions.ts +368 -0
- package/src/cmi/scorm12/nav.ts +54 -0
- package/src/cmi/scorm12/objectives.ts +112 -0
- package/src/cmi/scorm12/student_data.ts +130 -0
- package/src/cmi/scorm12/student_preference.ts +158 -0
- package/src/cmi/scorm12/validation.ts +48 -0
- package/src/cmi/scorm2004/adl.ts +272 -0
- package/src/cmi/scorm2004/cmi.ts +599 -0
- package/src/cmi/scorm2004/comments.ts +163 -0
- package/src/cmi/scorm2004/interactions.ts +466 -0
- package/src/cmi/scorm2004/learner_preference.ts +152 -0
- package/src/cmi/scorm2004/objectives.ts +212 -0
- package/src/cmi/scorm2004/score.ts +78 -0
- package/src/cmi/scorm2004/validation.ts +42 -0
- package/src/constants/default_settings.ts +81 -0
- package/src/constants/enums.ts +5 -0
- package/src/constants/regex.ts +2 -2
- package/src/constants/response_constants.ts +2 -0
- package/src/exceptions.ts +22 -1
- package/src/helpers/scheduled_commit.ts +42 -0
- package/src/interfaces/IBaseAPI.ts +35 -0
- package/src/types/api_types.ts +32 -0
- package/src/utilities/debounce.ts +31 -0
- package/src/utilities.ts +56 -0
- package/test/AICC.spec.ts +11 -1
- package/test/Scorm12API.spec.ts +262 -9
- package/test/Scorm2004API.spec.ts +488 -2
- package/test/cmi/aicc_cmi.spec.ts +188 -11
- package/test/cmi/scorm12_cmi.spec.ts +5 -5
- package/test/cmi/scorm2004_cmi.spec.ts +8 -8
- package/test/cmi_helpers.ts +1 -1
- package/test/types/api_types.spec.ts +126 -0
- package/test/utilities/debounce.spec.ts +56 -0
- package/src/cmi/aicc_cmi.ts +0 -1248
- package/src/cmi/common.ts +0 -411
- package/src/cmi/scorm12_cmi.ts +0 -1426
- package/src/cmi/scorm2004_cmi.ts +0 -1874
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class for SCORM 2004's cmi.learner_preference object
|
|
3
|
+
*/
|
|
4
|
+
import { BaseCMI } from "../common/base_cmi";
|
|
5
|
+
import APIConstants from "../../constants/api_constants";
|
|
6
|
+
import { Scorm2004ValidationError } from "../../exceptions";
|
|
7
|
+
import ErrorCodes from "../../constants/error_codes";
|
|
8
|
+
import { check2004ValidFormat, check2004ValidRange } from "./validation";
|
|
9
|
+
import Regex from "../../constants/regex";
|
|
10
|
+
|
|
11
|
+
export class CMILearnerPreference extends BaseCMI {
|
|
12
|
+
private __children = APIConstants.scorm2004.student_preference_children;
|
|
13
|
+
private _audio_level = "1";
|
|
14
|
+
private _language = "";
|
|
15
|
+
private _delivery_speed = "1";
|
|
16
|
+
private _audio_captioning = "0";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Constructor for cmi.learner_preference
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Getter for __children
|
|
27
|
+
* @return {string}
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
get _children(): string {
|
|
31
|
+
return this.__children;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Setter for __children. Just throws an error.
|
|
36
|
+
* @param {string} _children
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
set _children(_children: string) {
|
|
40
|
+
throw new Scorm2004ValidationError(ErrorCodes.scorm2004.READ_ONLY_ELEMENT);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Getter for _audio_level
|
|
45
|
+
* @return {string}
|
|
46
|
+
*/
|
|
47
|
+
get audio_level(): string {
|
|
48
|
+
return this._audio_level;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Setter for _audio_level
|
|
53
|
+
* @param {string} audio_level
|
|
54
|
+
*/
|
|
55
|
+
set audio_level(audio_level: string) {
|
|
56
|
+
if (
|
|
57
|
+
check2004ValidFormat(audio_level, Regex.scorm2004.CMIDecimal) &&
|
|
58
|
+
check2004ValidRange(audio_level, Regex.scorm2004.audio_range)
|
|
59
|
+
) {
|
|
60
|
+
this._audio_level = audio_level;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Getter for _language
|
|
66
|
+
* @return {string}
|
|
67
|
+
*/
|
|
68
|
+
get language(): string {
|
|
69
|
+
return this._language;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Setter for _language
|
|
74
|
+
* @param {string} language
|
|
75
|
+
*/
|
|
76
|
+
set language(language: string) {
|
|
77
|
+
if (check2004ValidFormat(language, Regex.scorm2004.CMILang)) {
|
|
78
|
+
this._language = language;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Getter for _delivery_speed
|
|
84
|
+
* @return {string}
|
|
85
|
+
*/
|
|
86
|
+
get delivery_speed(): string {
|
|
87
|
+
return this._delivery_speed;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Setter for _delivery_speed
|
|
92
|
+
* @param {string} delivery_speed
|
|
93
|
+
*/
|
|
94
|
+
set delivery_speed(delivery_speed: string) {
|
|
95
|
+
if (
|
|
96
|
+
check2004ValidFormat(delivery_speed, Regex.scorm2004.CMIDecimal) &&
|
|
97
|
+
check2004ValidRange(delivery_speed, Regex.scorm2004.speed_range)
|
|
98
|
+
) {
|
|
99
|
+
this._delivery_speed = delivery_speed;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Getter for _audio_captioning
|
|
105
|
+
* @return {string}
|
|
106
|
+
*/
|
|
107
|
+
get audio_captioning(): string {
|
|
108
|
+
return this._audio_captioning;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Setter for _audio_captioning
|
|
113
|
+
* @param {string} audio_captioning
|
|
114
|
+
*/
|
|
115
|
+
set audio_captioning(audio_captioning: string) {
|
|
116
|
+
if (
|
|
117
|
+
check2004ValidFormat(audio_captioning, Regex.scorm2004.CMISInteger) &&
|
|
118
|
+
check2004ValidRange(audio_captioning, Regex.scorm2004.text_range)
|
|
119
|
+
) {
|
|
120
|
+
this._audio_captioning = audio_captioning;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* toJSON for cmi.learner_preference
|
|
126
|
+
*
|
|
127
|
+
* @return {
|
|
128
|
+
* {
|
|
129
|
+
* audio_level: string,
|
|
130
|
+
* language: string,
|
|
131
|
+
* delivery_speed: string,
|
|
132
|
+
* audio_captioning: string
|
|
133
|
+
* }
|
|
134
|
+
* }
|
|
135
|
+
*/
|
|
136
|
+
toJSON(): {
|
|
137
|
+
audio_level: string;
|
|
138
|
+
language: string;
|
|
139
|
+
delivery_speed: string;
|
|
140
|
+
audio_captioning: string;
|
|
141
|
+
} {
|
|
142
|
+
this.jsonString = true;
|
|
143
|
+
const result = {
|
|
144
|
+
audio_level: this.audio_level,
|
|
145
|
+
language: this.language,
|
|
146
|
+
delivery_speed: this.delivery_speed,
|
|
147
|
+
audio_captioning: this.audio_captioning,
|
|
148
|
+
};
|
|
149
|
+
delete this.jsonString;
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { CMIArray } from "../common/array";
|
|
2
|
+
import APIConstants from "../../constants/api_constants";
|
|
3
|
+
import ErrorCodes from "../../constants/error_codes";
|
|
4
|
+
import { Scorm2004ValidationError } from "../../exceptions";
|
|
5
|
+
import { BaseCMI } from "../common/base_cmi";
|
|
6
|
+
import { Scorm2004CMIScore } from "./score";
|
|
7
|
+
import { check2004ValidFormat, check2004ValidRange } from "./validation";
|
|
8
|
+
import Regex from "../../constants/regex";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Class representing SCORM 2004's `cmi.objectives` object
|
|
12
|
+
* @extends CMIArray
|
|
13
|
+
*/
|
|
14
|
+
export class CMIObjectives extends CMIArray {
|
|
15
|
+
/**
|
|
16
|
+
* Constructor for `cmi.objectives` Array
|
|
17
|
+
*/
|
|
18
|
+
constructor() {
|
|
19
|
+
super({
|
|
20
|
+
children: APIConstants.scorm2004.objectives_children,
|
|
21
|
+
errorCode: ErrorCodes.scorm2004.READ_ONLY_ELEMENT,
|
|
22
|
+
errorClass: Scorm2004ValidationError,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Class for SCORM 2004's cmi.objectives.n object
|
|
29
|
+
*/
|
|
30
|
+
export class CMIObjectivesObject extends BaseCMI {
|
|
31
|
+
private _id = "";
|
|
32
|
+
private _success_status = "unknown";
|
|
33
|
+
private _completion_status = "unknown";
|
|
34
|
+
private _progress_measure = "";
|
|
35
|
+
private _description = "";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Constructor for cmi.objectives.n
|
|
39
|
+
*/
|
|
40
|
+
constructor() {
|
|
41
|
+
super();
|
|
42
|
+
this.score = new Scorm2004CMIScore();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public score: Scorm2004CMIScore;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Called when the API has been initialized after the CMI has been created
|
|
49
|
+
*/
|
|
50
|
+
initialize() {
|
|
51
|
+
super.initialize();
|
|
52
|
+
this.score?.initialize();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Getter for _id
|
|
57
|
+
* @return {string}
|
|
58
|
+
*/
|
|
59
|
+
get id(): string {
|
|
60
|
+
return this._id;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Setter for _id
|
|
65
|
+
* @param {string} id
|
|
66
|
+
*/
|
|
67
|
+
set id(id: string) {
|
|
68
|
+
if (check2004ValidFormat(id, Regex.scorm2004.CMILongIdentifier)) {
|
|
69
|
+
this._id = id;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Getter for _success_status
|
|
75
|
+
* @return {string}
|
|
76
|
+
*/
|
|
77
|
+
get success_status(): string {
|
|
78
|
+
return this._success_status;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Setter for _success_status
|
|
83
|
+
* @param {string} success_status
|
|
84
|
+
*/
|
|
85
|
+
set success_status(success_status: string) {
|
|
86
|
+
if (this.initialized && this._id === "") {
|
|
87
|
+
throw new Scorm2004ValidationError(
|
|
88
|
+
ErrorCodes.scorm2004.DEPENDENCY_NOT_ESTABLISHED,
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
if (check2004ValidFormat(success_status, Regex.scorm2004.CMISStatus)) {
|
|
92
|
+
this._success_status = success_status;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Getter for _completion_status
|
|
99
|
+
* @return {string}
|
|
100
|
+
*/
|
|
101
|
+
get completion_status(): string {
|
|
102
|
+
return this._completion_status;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Setter for _completion_status
|
|
107
|
+
* @param {string} completion_status
|
|
108
|
+
*/
|
|
109
|
+
set completion_status(completion_status: string) {
|
|
110
|
+
if (this.initialized && this._id === "") {
|
|
111
|
+
throw new Scorm2004ValidationError(
|
|
112
|
+
ErrorCodes.scorm2004.DEPENDENCY_NOT_ESTABLISHED,
|
|
113
|
+
);
|
|
114
|
+
} else {
|
|
115
|
+
if (check2004ValidFormat(completion_status, Regex.scorm2004.CMICStatus)) {
|
|
116
|
+
this._completion_status = completion_status;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Getter for _progress_measure
|
|
123
|
+
* @return {string}
|
|
124
|
+
*/
|
|
125
|
+
get progress_measure(): string {
|
|
126
|
+
return this._progress_measure;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Setter for _progress_measure
|
|
131
|
+
* @param {string} progress_measure
|
|
132
|
+
*/
|
|
133
|
+
set progress_measure(progress_measure: string) {
|
|
134
|
+
if (this.initialized && this._id === "") {
|
|
135
|
+
throw new Scorm2004ValidationError(
|
|
136
|
+
ErrorCodes.scorm2004.DEPENDENCY_NOT_ESTABLISHED,
|
|
137
|
+
);
|
|
138
|
+
} else {
|
|
139
|
+
if (
|
|
140
|
+
check2004ValidFormat(progress_measure, Regex.scorm2004.CMIDecimal) &&
|
|
141
|
+
check2004ValidRange(progress_measure, Regex.scorm2004.progress_range)
|
|
142
|
+
) {
|
|
143
|
+
this._progress_measure = progress_measure;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Getter for _description
|
|
150
|
+
* @return {string}
|
|
151
|
+
*/
|
|
152
|
+
get description(): string {
|
|
153
|
+
return this._description;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Setter for _description
|
|
158
|
+
* @param {string} description
|
|
159
|
+
*/
|
|
160
|
+
set description(description: string) {
|
|
161
|
+
if (this.initialized && this._id === "") {
|
|
162
|
+
throw new Scorm2004ValidationError(
|
|
163
|
+
ErrorCodes.scorm2004.DEPENDENCY_NOT_ESTABLISHED,
|
|
164
|
+
);
|
|
165
|
+
} else {
|
|
166
|
+
if (
|
|
167
|
+
check2004ValidFormat(
|
|
168
|
+
description,
|
|
169
|
+
Regex.scorm2004.CMILangString250,
|
|
170
|
+
true,
|
|
171
|
+
)
|
|
172
|
+
) {
|
|
173
|
+
this._description = description;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* toJSON for cmi.objectives.n
|
|
180
|
+
*
|
|
181
|
+
* @return {
|
|
182
|
+
* {
|
|
183
|
+
* id: string,
|
|
184
|
+
* success_status: string,
|
|
185
|
+
* completion_status: string,
|
|
186
|
+
* progress_measure: string,
|
|
187
|
+
* description: string,
|
|
188
|
+
* score: Scorm2004CMIScore
|
|
189
|
+
* }
|
|
190
|
+
* }
|
|
191
|
+
*/
|
|
192
|
+
toJSON(): {
|
|
193
|
+
id: string;
|
|
194
|
+
success_status: string;
|
|
195
|
+
completion_status: string;
|
|
196
|
+
progress_measure: string;
|
|
197
|
+
description: string;
|
|
198
|
+
score: Scorm2004CMIScore;
|
|
199
|
+
} {
|
|
200
|
+
this.jsonString = true;
|
|
201
|
+
const result = {
|
|
202
|
+
id: this.id,
|
|
203
|
+
success_status: this.success_status,
|
|
204
|
+
completion_status: this.completion_status,
|
|
205
|
+
progress_measure: this.progress_measure,
|
|
206
|
+
description: this.description,
|
|
207
|
+
score: this.score,
|
|
208
|
+
};
|
|
209
|
+
delete this.jsonString;
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class for SCORM 2004's cmi *.score object
|
|
3
|
+
*/
|
|
4
|
+
import { CMIScore } from "../common/score";
|
|
5
|
+
import APIConstants from "../../constants/api_constants";
|
|
6
|
+
import ErrorCodes from "../../constants/error_codes";
|
|
7
|
+
import Regex from "../../constants/regex";
|
|
8
|
+
import { Scorm2004ValidationError } from "../../exceptions";
|
|
9
|
+
import { check2004ValidFormat, check2004ValidRange } from "./validation";
|
|
10
|
+
|
|
11
|
+
export class Scorm2004CMIScore extends CMIScore {
|
|
12
|
+
private _scaled = "";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Constructor for cmi *.score
|
|
16
|
+
*/
|
|
17
|
+
constructor() {
|
|
18
|
+
super({
|
|
19
|
+
score_children: APIConstants.scorm2004.score_children,
|
|
20
|
+
max: "",
|
|
21
|
+
invalidErrorCode: ErrorCodes.scorm2004.READ_ONLY_ELEMENT,
|
|
22
|
+
invalidTypeCode: ErrorCodes.scorm2004.TYPE_MISMATCH,
|
|
23
|
+
invalidRangeCode: ErrorCodes.scorm2004.VALUE_OUT_OF_RANGE,
|
|
24
|
+
decimalRegex: Regex.scorm2004.CMIDecimal,
|
|
25
|
+
errorClass: Scorm2004ValidationError,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Getter for _scaled
|
|
31
|
+
* @return {string}
|
|
32
|
+
*/
|
|
33
|
+
get scaled(): string {
|
|
34
|
+
return this._scaled;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Setter for _scaled
|
|
39
|
+
* @param {string} scaled
|
|
40
|
+
*/
|
|
41
|
+
set scaled(scaled: string) {
|
|
42
|
+
if (
|
|
43
|
+
check2004ValidFormat(scaled, Regex.scorm2004.CMIDecimal) &&
|
|
44
|
+
check2004ValidRange(scaled, Regex.scorm2004.scaled_range)
|
|
45
|
+
) {
|
|
46
|
+
this._scaled = scaled;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* toJSON for cmi *.score
|
|
52
|
+
*
|
|
53
|
+
* @return {
|
|
54
|
+
* {
|
|
55
|
+
* scaled: string,
|
|
56
|
+
* raw: string,
|
|
57
|
+
* min: string,
|
|
58
|
+
* max: string
|
|
59
|
+
* }
|
|
60
|
+
* }
|
|
61
|
+
*/
|
|
62
|
+
toJSON(): {
|
|
63
|
+
scaled: string;
|
|
64
|
+
raw: string;
|
|
65
|
+
min: string;
|
|
66
|
+
max: string;
|
|
67
|
+
} {
|
|
68
|
+
this.jsonString = true;
|
|
69
|
+
const result = {
|
|
70
|
+
scaled: this.scaled,
|
|
71
|
+
raw: this.raw,
|
|
72
|
+
min: this.min,
|
|
73
|
+
max: this.max,
|
|
74
|
+
};
|
|
75
|
+
delete this.jsonString;
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { checkValidFormat, checkValidRange } from "../common/validation";
|
|
2
|
+
import ErrorCodes from "../../constants/error_codes";
|
|
3
|
+
import { Scorm2004ValidationError } from "../../exceptions";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Helper method, no reason to have to pass the same error codes every time
|
|
7
|
+
* @param {string} value
|
|
8
|
+
* @param {string} regexPattern
|
|
9
|
+
* @param {boolean} allowEmptyString
|
|
10
|
+
* @return {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function check2004ValidFormat(
|
|
13
|
+
value: string,
|
|
14
|
+
regexPattern: string,
|
|
15
|
+
allowEmptyString?: boolean,
|
|
16
|
+
): boolean {
|
|
17
|
+
return checkValidFormat(
|
|
18
|
+
value,
|
|
19
|
+
regexPattern,
|
|
20
|
+
ErrorCodes.scorm2004.TYPE_MISMATCH,
|
|
21
|
+
Scorm2004ValidationError,
|
|
22
|
+
allowEmptyString,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Helper method, no reason to have to pass the same error codes every time
|
|
28
|
+
* @param {string} value
|
|
29
|
+
* @param {string} rangePattern
|
|
30
|
+
* @return {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export function check2004ValidRange(
|
|
33
|
+
value: string,
|
|
34
|
+
rangePattern: string,
|
|
35
|
+
): boolean {
|
|
36
|
+
return checkValidRange(
|
|
37
|
+
value,
|
|
38
|
+
rangePattern,
|
|
39
|
+
ErrorCodes.scorm2004.VALUE_OUT_OF_RANGE,
|
|
40
|
+
Scorm2004ValidationError,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ResultObject, Settings } from "../types/api_types";
|
|
2
|
+
import APIConstants from "./api_constants";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default settings for the SCORM API
|
|
6
|
+
*/
|
|
7
|
+
export const DefaultSettings: Settings = {
|
|
8
|
+
autocommit: false,
|
|
9
|
+
autocommitSeconds: 10,
|
|
10
|
+
asyncCommit: false,
|
|
11
|
+
sendFullCommit: true,
|
|
12
|
+
lmsCommitUrl: false,
|
|
13
|
+
dataCommitFormat: "json",
|
|
14
|
+
commitRequestDataType: "application/json;charset=UTF-8",
|
|
15
|
+
autoProgress: false,
|
|
16
|
+
logLevel: APIConstants.global.LOG_LEVEL_ERROR,
|
|
17
|
+
selfReportSessionTime: false,
|
|
18
|
+
alwaysSendTotalTime: false,
|
|
19
|
+
strict_errors: true,
|
|
20
|
+
xhrHeaders: {},
|
|
21
|
+
xhrWithCredentials: false,
|
|
22
|
+
responseHandler: async function (response: Response): Promise<ResultObject> {
|
|
23
|
+
if (typeof response !== "undefined") {
|
|
24
|
+
const httpResult = JSON.parse(await response.text());
|
|
25
|
+
if (
|
|
26
|
+
httpResult === null ||
|
|
27
|
+
!{}.hasOwnProperty.call(httpResult, "result")
|
|
28
|
+
) {
|
|
29
|
+
if (response.status === 200) {
|
|
30
|
+
return {
|
|
31
|
+
result: APIConstants.global.SCORM_TRUE,
|
|
32
|
+
errorCode: 0,
|
|
33
|
+
};
|
|
34
|
+
} else {
|
|
35
|
+
return {
|
|
36
|
+
result: APIConstants.global.SCORM_FALSE,
|
|
37
|
+
errorCode: 101,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
return {
|
|
42
|
+
result: httpResult.result,
|
|
43
|
+
errorCode: httpResult.errorCode
|
|
44
|
+
? httpResult.errorCode
|
|
45
|
+
: httpResult.result === APIConstants.global.SCORM_TRUE
|
|
46
|
+
? 0
|
|
47
|
+
: 101,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
result: APIConstants.global.SCORM_FALSE,
|
|
53
|
+
errorCode: 101,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
requestHandler: function (commitObject) {
|
|
57
|
+
return commitObject;
|
|
58
|
+
},
|
|
59
|
+
onLogMessage: function (messageLevel, logMessage) {
|
|
60
|
+
switch (messageLevel) {
|
|
61
|
+
case APIConstants.global.LOG_LEVEL_ERROR:
|
|
62
|
+
console.error(logMessage);
|
|
63
|
+
break;
|
|
64
|
+
case APIConstants.global.LOG_LEVEL_WARNING:
|
|
65
|
+
console.warn(logMessage);
|
|
66
|
+
break;
|
|
67
|
+
case APIConstants.global.LOG_LEVEL_INFO:
|
|
68
|
+
console.info(logMessage);
|
|
69
|
+
break;
|
|
70
|
+
case APIConstants.global.LOG_LEVEL_DEBUG:
|
|
71
|
+
if (console.debug) {
|
|
72
|
+
console.debug(logMessage);
|
|
73
|
+
} else {
|
|
74
|
+
console.log(logMessage);
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
scoItemIds: [],
|
|
80
|
+
scoItemIdValidator: false,
|
|
81
|
+
};
|
package/src/constants/regex.ts
CHANGED
|
@@ -78,10 +78,10 @@ const scorm2004 = {
|
|
|
78
78
|
CMIResult:
|
|
79
79
|
"^(correct|incorrect|unanticipated|neutral|-?([0-9]{1,4})(\\.[0-9]{1,18})?)$",
|
|
80
80
|
NAVEvent:
|
|
81
|
-
"^(previous|continue|exit|exitAll|abandon|abandonAll|suspendAll|{target=\\S{0,
|
|
81
|
+
"^(previous|continue|exit|exitAll|abandon|abandonAll|suspendAll|_none_|(\\{target=\\S{0,}[a-zA-Z0-9-_]+})?choice|(\\{target=\\S{0,}[a-zA-Z0-9-_]+})?jump)$",
|
|
82
82
|
|
|
83
83
|
NAVBoolean: "^(unknown|true|false$)",
|
|
84
|
-
NAVTarget: "^
|
|
84
|
+
NAVTarget: "^{target=\\S{0,}[a-zA-Z0-9-_]+}$",
|
|
85
85
|
// Data ranges
|
|
86
86
|
scaled_range: "-1#1",
|
|
87
87
|
audio_range: "0#*",
|
|
@@ -111,6 +111,7 @@ export const CorrectResponses: Responses = {
|
|
|
111
111
|
max: 250,
|
|
112
112
|
delimiter: "[,]",
|
|
113
113
|
delimiter2: "[.]",
|
|
114
|
+
delimiter3: "[:]",
|
|
114
115
|
unique: false,
|
|
115
116
|
duplicate: false,
|
|
116
117
|
format: "^$|" + scorm2004_regex.CMIShortIdentifier,
|
|
@@ -159,6 +160,7 @@ export type ResponseType = {
|
|
|
159
160
|
format2?: string;
|
|
160
161
|
delimiter2?: string;
|
|
161
162
|
limit?: number;
|
|
163
|
+
delimiter3?: string;
|
|
162
164
|
};
|
|
163
165
|
|
|
164
166
|
export type Responses = {
|
package/src/exceptions.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import APIConstants from "./constants/api_constants";
|
|
2
|
-
import { BaseScormValidationError } from "./cmi/common";
|
|
3
2
|
|
|
4
3
|
const scorm12_errors = APIConstants.scorm12.error_descriptions;
|
|
5
4
|
const aicc_errors = APIConstants.aicc.error_descriptions;
|
|
@@ -11,6 +10,28 @@ type APIError = {
|
|
|
11
10
|
detailedMessage: string;
|
|
12
11
|
};
|
|
13
12
|
|
|
13
|
+
export class BaseScormValidationError extends Error {
|
|
14
|
+
constructor(errorCode: number) {
|
|
15
|
+
super(errorCode.toString());
|
|
16
|
+
this._errorCode = errorCode;
|
|
17
|
+
this.name = "ScormValidationError";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private readonly _errorCode: number;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Getter for _errorCode
|
|
24
|
+
* @return {number}
|
|
25
|
+
*/
|
|
26
|
+
get errorCode(): number {
|
|
27
|
+
return this._errorCode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setMessage(message: string) {
|
|
31
|
+
this.message = message;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
/**
|
|
15
36
|
* Base Validation Exception
|
|
16
37
|
*/
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import BaseAPI from "../BaseAPI";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Private class that wraps a timeout call to the commit() function
|
|
5
|
+
*/
|
|
6
|
+
export class ScheduledCommit {
|
|
7
|
+
private _API;
|
|
8
|
+
private _cancelled = false;
|
|
9
|
+
private readonly _timeout;
|
|
10
|
+
private readonly _callback;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Constructor for ScheduledCommit
|
|
14
|
+
* @param {BaseAPI} API
|
|
15
|
+
* @param {number} when
|
|
16
|
+
* @param {string} callback
|
|
17
|
+
*/
|
|
18
|
+
constructor(API: BaseAPI, when: number, callback: string) {
|
|
19
|
+
this._API = API;
|
|
20
|
+
this._timeout = setTimeout(this.wrapper.bind(this), when);
|
|
21
|
+
this._callback = callback;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Cancel any currently scheduled commit
|
|
26
|
+
*/
|
|
27
|
+
cancel() {
|
|
28
|
+
this._cancelled = true;
|
|
29
|
+
if (this._timeout) {
|
|
30
|
+
clearTimeout(this._timeout);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Wrap the API commit call to check if the call has already been cancelled
|
|
36
|
+
*/
|
|
37
|
+
wrapper() {
|
|
38
|
+
if (!this._cancelled) {
|
|
39
|
+
(async () => await this._API.commit(this._callback))();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|