@superbuilders/primer-tives 1.1.2 → 1.1.3
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/README.md +74 -8
- package/dist/client/choice-state.d.ts +8 -0
- package/dist/client/choice-state.d.ts.map +1 -0
- package/dist/client/consumed.d.ts +3 -0
- package/dist/client/consumed.d.ts.map +1 -0
- package/dist/client/content.d.ts +20 -0
- package/dist/client/content.d.ts.map +1 -0
- package/dist/client/create.d.ts +20 -0
- package/dist/client/create.d.ts.map +1 -0
- package/dist/client/extended-text-state.d.ts +8 -0
- package/dist/client/extended-text-state.d.ts.map +1 -0
- package/dist/client/feedback-state.d.ts +7 -0
- package/dist/client/feedback-state.d.ts.map +1 -0
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +1095 -0
- package/dist/client/index.js.map +26 -0
- package/dist/client/match-state.d.ts +8 -0
- package/dist/client/match-state.d.ts.map +1 -0
- package/dist/client/observation-state.d.ts +6 -0
- package/dist/client/observation-state.d.ts.map +1 -0
- package/dist/client/order-state.d.ts +8 -0
- package/dist/client/order-state.d.ts.map +1 -0
- package/dist/client/pci-state.d.ts +6 -0
- package/dist/client/pci-state.d.ts.map +1 -0
- package/dist/client/pci.d.ts +38 -0
- package/dist/client/pci.d.ts.map +1 -0
- package/dist/client/session-context.d.ts +19 -0
- package/dist/client/session-context.d.ts.map +1 -0
- package/dist/client/session.d.ts +18 -0
- package/dist/client/session.d.ts.map +1 -0
- package/dist/client/text-entry-state.d.ts +8 -0
- package/dist/client/text-entry-state.d.ts.map +1 -0
- package/dist/client/transport.d.ts +46 -0
- package/dist/client/transport.d.ts.map +1 -0
- package/dist/client/types.d.ts +194 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/contracts/index.d.ts +4 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +300 -0
- package/dist/contracts/index.js.map +11 -0
- package/dist/contracts/pci-schemas.d.ts +25 -0
- package/dist/contracts/pci-schemas.d.ts.map +1 -0
- package/dist/contracts/types.d.ts +118 -0
- package/dist/contracts/types.d.ts.map +1 -0
- package/dist/contracts/validation.d.ts +92 -0
- package/dist/contracts/validation.d.ts.map +1 -0
- package/dist/errors.d.ts +23 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +10 -0
- package/dist/grade-level.d.ts +5 -0
- package/dist/grade-level.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +344 -0
- package/dist/index.js.map +12 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/server/create-server.d.ts +44 -0
- package/dist/server/create-server.d.ts.map +1 -0
- package/dist/server/exchange.d.ts +22 -0
- package/dist/server/exchange.d.ts.map +1 -0
- package/dist/server/hints.d.ts +25 -0
- package/dist/server/hints.d.ts.map +1 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +531 -0
- package/dist/server/index.js.map +15 -0
- package/dist/server/students.d.ts +12 -0
- package/dist/server/students.d.ts.map +1 -0
- package/dist/subject.d.ts +6 -0
- package/dist/subject.d.ts.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { ContentBlock, ContentInline } from "../client/content";
|
|
2
|
+
import type { PciId, PciProps, PciValue } from "../client/pci";
|
|
3
|
+
interface MatchPair {
|
|
4
|
+
source: string;
|
|
5
|
+
target: string;
|
|
6
|
+
}
|
|
7
|
+
interface BodyStimulus {
|
|
8
|
+
type: "body";
|
|
9
|
+
body: ContentBlock[];
|
|
10
|
+
}
|
|
11
|
+
interface ImageStimulus {
|
|
12
|
+
type: "image";
|
|
13
|
+
description: ContentInline[];
|
|
14
|
+
src: string;
|
|
15
|
+
}
|
|
16
|
+
type RendererStimulus = BodyStimulus | ImageStimulus;
|
|
17
|
+
interface RendererChoice {
|
|
18
|
+
identifier: string;
|
|
19
|
+
content: ContentInline[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A choice in a match interaction — QTI 3.0 simpleAssociableChoice.
|
|
23
|
+
*
|
|
24
|
+
* matchMax: maximum number of pairs this choice may participate in.
|
|
25
|
+
* 0 = unbounded (QTI convention).
|
|
26
|
+
* matchMin: minimum number of pairs this choice must participate in.
|
|
27
|
+
* 0 = no minimum (QTI default).
|
|
28
|
+
*/
|
|
29
|
+
interface RendererMatchChoice {
|
|
30
|
+
identifier: string;
|
|
31
|
+
content: ContentInline[];
|
|
32
|
+
matchMax: number;
|
|
33
|
+
matchMin: number;
|
|
34
|
+
}
|
|
35
|
+
type PciInteraction<Pcis extends PciId = PciId> = {
|
|
36
|
+
[K in Pcis]: {
|
|
37
|
+
type: "portable-custom";
|
|
38
|
+
prompt: ContentInline[];
|
|
39
|
+
pciId: K;
|
|
40
|
+
properties: PciProps<K>;
|
|
41
|
+
};
|
|
42
|
+
}[Pcis];
|
|
43
|
+
type StandardRendererInteraction = {
|
|
44
|
+
type: "choice";
|
|
45
|
+
prompt: ContentInline[];
|
|
46
|
+
options: RendererChoice[];
|
|
47
|
+
shuffle: boolean;
|
|
48
|
+
maxChoices: number;
|
|
49
|
+
minChoices: number;
|
|
50
|
+
} | {
|
|
51
|
+
type: "text-entry";
|
|
52
|
+
prompt: ContentInline[];
|
|
53
|
+
base: 10;
|
|
54
|
+
expectedLength?: number;
|
|
55
|
+
patternMask?: string;
|
|
56
|
+
placeholderText?: string;
|
|
57
|
+
} | {
|
|
58
|
+
type: "extended-text";
|
|
59
|
+
cardinality: "single";
|
|
60
|
+
prompt: ContentInline[];
|
|
61
|
+
format: "plain";
|
|
62
|
+
expectedLength?: number;
|
|
63
|
+
expectedLines?: number;
|
|
64
|
+
patternMask?: string;
|
|
65
|
+
placeholderText?: string;
|
|
66
|
+
} | {
|
|
67
|
+
type: "extended-text";
|
|
68
|
+
cardinality: "multiple";
|
|
69
|
+
prompt: ContentInline[];
|
|
70
|
+
format: "plain";
|
|
71
|
+
expectedLength?: number;
|
|
72
|
+
expectedLines?: number;
|
|
73
|
+
patternMask?: string;
|
|
74
|
+
placeholderText?: string;
|
|
75
|
+
minStrings: number;
|
|
76
|
+
maxStrings: number;
|
|
77
|
+
} | {
|
|
78
|
+
type: "order";
|
|
79
|
+
prompt: ContentInline[];
|
|
80
|
+
choices: RendererChoice[];
|
|
81
|
+
shuffle: boolean;
|
|
82
|
+
minChoices: number;
|
|
83
|
+
maxChoices: number;
|
|
84
|
+
} | {
|
|
85
|
+
type: "match";
|
|
86
|
+
prompt: ContentInline[];
|
|
87
|
+
sourceChoices: RendererMatchChoice[];
|
|
88
|
+
targetChoices: RendererMatchChoice[];
|
|
89
|
+
shuffle: boolean;
|
|
90
|
+
minAssociations: number;
|
|
91
|
+
maxAssociations: number;
|
|
92
|
+
};
|
|
93
|
+
type RendererInteraction<Pcis extends PciId = PciId> = StandardRendererInteraction | PciInteraction<Pcis>;
|
|
94
|
+
type PciSubmission<Pcis extends PciId = PciId> = {
|
|
95
|
+
[K in Pcis]: {
|
|
96
|
+
type: "portable-custom";
|
|
97
|
+
pciId: K;
|
|
98
|
+
value: PciValue<K>;
|
|
99
|
+
};
|
|
100
|
+
}[Pcis];
|
|
101
|
+
type RendererSubmission<Pcis extends PciId = PciId> = {
|
|
102
|
+
type: "choice";
|
|
103
|
+
selectedKeys: string[];
|
|
104
|
+
} | {
|
|
105
|
+
type: "text-entry";
|
|
106
|
+
value: string;
|
|
107
|
+
} | {
|
|
108
|
+
type: "extended-text";
|
|
109
|
+
values: string[];
|
|
110
|
+
} | {
|
|
111
|
+
type: "order";
|
|
112
|
+
orderedKeys: string[];
|
|
113
|
+
} | {
|
|
114
|
+
type: "match";
|
|
115
|
+
pairs: MatchPair[];
|
|
116
|
+
} | PciSubmission<Pcis>;
|
|
117
|
+
export type { BodyStimulus, ImageStimulus, MatchPair, PciInteraction, PciSubmission, RendererChoice, RendererInteraction, RendererMatchChoice, RendererStimulus, RendererSubmission, StandardRendererInteraction };
|
|
118
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contracts/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { RendererInteraction, RendererSubmission } from "./types";
|
|
3
|
+
declare const MatchPairSchema: z.ZodObject<{
|
|
4
|
+
source: z.ZodString;
|
|
5
|
+
target: z.ZodString;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
declare const ChoiceSubmissionSchema: z.ZodObject<{
|
|
8
|
+
type: z.ZodLiteral<"choice">;
|
|
9
|
+
selectedKeys: z.ZodArray<z.ZodString>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
declare const TextEntrySubmissionSchema: z.ZodObject<{
|
|
12
|
+
type: z.ZodLiteral<"text-entry">;
|
|
13
|
+
value: z.ZodString;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
declare const ExtendedTextSubmissionSchema: z.ZodObject<{
|
|
16
|
+
type: z.ZodLiteral<"extended-text">;
|
|
17
|
+
values: z.ZodArray<z.ZodString>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
declare const OrderSubmissionSchema: z.ZodObject<{
|
|
20
|
+
type: z.ZodLiteral<"order">;
|
|
21
|
+
orderedKeys: z.ZodArray<z.ZodString>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
declare const MatchSubmissionSchema: z.ZodObject<{
|
|
24
|
+
type: z.ZodLiteral<"match">;
|
|
25
|
+
pairs: z.ZodArray<z.ZodObject<{
|
|
26
|
+
source: z.ZodString;
|
|
27
|
+
target: z.ZodString;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
declare const DivisionRemainderPciSubmissionSchema: z.ZodObject<{
|
|
31
|
+
type: z.ZodLiteral<"portable-custom">;
|
|
32
|
+
pciId: z.ZodLiteral<"urn:primer:pci:division-remainder">;
|
|
33
|
+
value: z.ZodObject<{
|
|
34
|
+
quotient: z.ZodString;
|
|
35
|
+
remainder: z.ZodString;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
declare const FractionAdditionPciSubmissionSchema: z.ZodObject<{
|
|
39
|
+
type: z.ZodLiteral<"portable-custom">;
|
|
40
|
+
pciId: z.ZodLiteral<"urn:primer:pci:fraction-addition">;
|
|
41
|
+
value: z.ZodObject<{
|
|
42
|
+
numerator: z.ZodString;
|
|
43
|
+
denominator: z.ZodString;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
declare const RendererSubmissionSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
47
|
+
type: z.ZodLiteral<"choice">;
|
|
48
|
+
selectedKeys: z.ZodArray<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
50
|
+
type: z.ZodLiteral<"text-entry">;
|
|
51
|
+
value: z.ZodString;
|
|
52
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
53
|
+
type: z.ZodLiteral<"extended-text">;
|
|
54
|
+
values: z.ZodArray<z.ZodString>;
|
|
55
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
56
|
+
type: z.ZodLiteral<"order">;
|
|
57
|
+
orderedKeys: z.ZodArray<z.ZodString>;
|
|
58
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
59
|
+
type: z.ZodLiteral<"match">;
|
|
60
|
+
pairs: z.ZodArray<z.ZodObject<{
|
|
61
|
+
source: z.ZodString;
|
|
62
|
+
target: z.ZodString;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
65
|
+
type: z.ZodLiteral<"portable-custom">;
|
|
66
|
+
pciId: z.ZodLiteral<"urn:primer:pci:division-remainder">;
|
|
67
|
+
value: z.ZodObject<{
|
|
68
|
+
quotient: z.ZodString;
|
|
69
|
+
remainder: z.ZodString;
|
|
70
|
+
}, z.core.$strip>;
|
|
71
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
72
|
+
type: z.ZodLiteral<"portable-custom">;
|
|
73
|
+
pciId: z.ZodLiteral<"urn:primer:pci:fraction-addition">;
|
|
74
|
+
value: z.ZodObject<{
|
|
75
|
+
numerator: z.ZodString;
|
|
76
|
+
denominator: z.ZodString;
|
|
77
|
+
}, z.core.$strip>;
|
|
78
|
+
}, z.core.$strip>]>;
|
|
79
|
+
type SubmissionValidationSuccess = {
|
|
80
|
+
ok: true;
|
|
81
|
+
value: RendererSubmission;
|
|
82
|
+
};
|
|
83
|
+
type SubmissionValidationFailure = {
|
|
84
|
+
ok: false;
|
|
85
|
+
issues: readonly string[];
|
|
86
|
+
};
|
|
87
|
+
type SubmissionValidationResult = SubmissionValidationSuccess | SubmissionValidationFailure;
|
|
88
|
+
declare function validateSubmissionForInteraction(interaction: RendererInteraction, submission: RendererSubmission): SubmissionValidationResult;
|
|
89
|
+
declare function submissionValidationMessage(result: SubmissionValidationFailure): string;
|
|
90
|
+
export { ChoiceSubmissionSchema, DivisionRemainderPciSubmissionSchema, ExtendedTextSubmissionSchema, FractionAdditionPciSubmissionSchema, MatchPairSchema, MatchSubmissionSchema, OrderSubmissionSchema, RendererSubmissionSchema, TextEntrySubmissionSchema, submissionValidationMessage, validateSubmissionForInteraction };
|
|
91
|
+
export type { SubmissionValidationFailure, SubmissionValidationResult, SubmissionValidationSuccess };
|
|
92
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/contracts/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB,OAAO,KAAK,EAGX,mBAAmB,EAEnB,kBAAkB,EAClB,MAAM,6CAA6C,CAAA;AAEpD,QAAA,MAAM,eAAe;;;iBAGnB,CAAA;AAEF,QAAA,MAAM,sBAAsB;;;iBAG1B,CAAA;AAEF,QAAA,MAAM,yBAAyB;;;iBAG7B,CAAA;AAEF,QAAA,MAAM,4BAA4B;;;iBAGhC,CAAA;AAEF,QAAA,MAAM,qBAAqB;;;iBAGzB,CAAA;AAEF,QAAA,MAAM,qBAAqB;;;;;;iBAGzB,CAAA;AAEF,QAAA,MAAM,oCAAoC;;;;;;;iBAIxC,CAAA;AAEF,QAAA,MAAM,mCAAmC;;;;;;;iBAIvC,CAAA;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAQ5B,CAAA;AAuEF,KAAK,2BAA2B,GAAG;IAClC,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,kBAAkB,CAAA;CACzB,CAAA;AAED,KAAK,2BAA2B,GAAG;IAClC,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CACzB,CAAA;AAED,KAAK,0BAA0B,GAAG,2BAA2B,GAAG,2BAA2B,CAAA;AAuJ3F,iBAAS,gCAAgC,CACxC,WAAW,EAAE,mBAAmB,EAChC,UAAU,EAAE,kBAAkB,GAC5B,0BAA0B,CAiC5B;AAED,iBAAS,2BAA2B,CAAC,MAAM,EAAE,2BAA2B,GAAG,MAAM,CAEhF;AAED,OAAO,EACN,sBAAsB,EACtB,oCAAoC,EACpC,4BAA4B,EAC5B,mCAAmC,EACnC,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,gCAAgC,EAChC,CAAA;AACD,YAAY,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,CAAA"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
declare const ErrNetwork: Error;
|
|
2
|
+
declare const ErrJsonParse: Error;
|
|
3
|
+
declare const ErrUnsupportedPci: Error;
|
|
4
|
+
declare const ErrInvalidAccessToken: Error;
|
|
5
|
+
declare const ErrMalformedAccessToken: Error;
|
|
6
|
+
declare const ErrTokenExpired: Error;
|
|
7
|
+
declare const ErrBadRequest: Error;
|
|
8
|
+
declare const ErrServerError: Error;
|
|
9
|
+
declare const ErrTimeout: Error;
|
|
10
|
+
declare const ErrForbidden: Error;
|
|
11
|
+
declare const ErrNotFound: Error;
|
|
12
|
+
declare const ErrConflict: Error;
|
|
13
|
+
declare const ErrExternalAuthorityRequired: Error;
|
|
14
|
+
declare const ErrRateLimited: Error;
|
|
15
|
+
declare const ErrServiceUnavailable: Error;
|
|
16
|
+
declare const ErrNotSerializable: Error;
|
|
17
|
+
declare const ErrInvalidSubmission: Error;
|
|
18
|
+
declare const ErrInvalidSecretKey: Error;
|
|
19
|
+
declare const ErrStudentNotFound: Error;
|
|
20
|
+
declare const ErrUnsupportedGrade: Error;
|
|
21
|
+
declare const ErrTimebackUnavailable: Error;
|
|
22
|
+
export { ErrBadRequest, ErrConflict, ErrExternalAuthorityRequired, ErrForbidden, ErrInvalidAccessToken, ErrInvalidSecretKey, ErrInvalidSubmission, ErrJsonParse, ErrMalformedAccessToken, ErrNetwork, ErrNotFound, ErrNotSerializable, ErrRateLimited, ErrServerError, ErrServiceUnavailable, ErrStudentNotFound, ErrTimebackUnavailable, ErrTimeout, ErrTokenExpired, ErrUnsupportedGrade, ErrUnsupportedPci };
|
|
23
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,UAAU,OAAwB,CAAA;AACxC,QAAA,MAAM,YAAY,OAA2B,CAAA;AAC7C,QAAA,MAAM,iBAAiB,OAAgC,CAAA;AACvD,QAAA,MAAM,qBAAqB,OAAqC,CAAA;AAChE,QAAA,MAAM,uBAAuB,OAAuC,CAAA;AACpE,QAAA,MAAM,eAAe,OAAqC,CAAA;AAC1D,QAAA,MAAM,aAAa,OAA4B,CAAA;AAC/C,QAAA,MAAM,cAAc,OAA6B,CAAA;AACjD,QAAA,MAAM,UAAU,OAAwB,CAAA;AACxC,QAAA,MAAM,YAAY,OAA0B,CAAA;AAC5C,QAAA,MAAM,WAAW,OAA0B,CAAA;AAC3C,QAAA,MAAM,WAAW,OAAyB,CAAA;AAC1C,QAAA,MAAM,4BAA4B,OAA4C,CAAA;AAC9E,QAAA,MAAM,cAAc,OAA6B,CAAA;AACjD,QAAA,MAAM,qBAAqB,OAAoC,CAAA;AAC/D,QAAA,MAAM,kBAAkB,OAEvB,CAAA;AACD,QAAA,MAAM,oBAAoB,OAAmC,CAAA;AAE7D,QAAA,MAAM,mBAAmB,OAAmC,CAAA;AAC5D,QAAA,MAAM,kBAAkB,OAAkC,CAAA;AAC1D,QAAA,MAAM,mBAAmB,OAAkC,CAAA;AAC3D,QAAA,MAAM,sBAAsB,OAAqC,CAAA;AAEjE,OAAO,EACN,aAAa,EACb,WAAW,EACX,4BAA4B,EAC5B,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,CAAA"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
import * as errors from "@superbuilders/errors";
|
|
3
|
+
var ErrNetwork = errors.new("network");
|
|
4
|
+
var ErrJsonParse = errors.new("json parse");
|
|
5
|
+
var ErrUnsupportedPci = errors.new("unsupported pci");
|
|
6
|
+
var ErrInvalidAccessToken = errors.new("invalid access token");
|
|
7
|
+
var ErrMalformedAccessToken = errors.new("malformed access token");
|
|
8
|
+
var ErrTokenExpired = errors.new("access token expired");
|
|
9
|
+
var ErrBadRequest = errors.new("bad request");
|
|
10
|
+
var ErrServerError = errors.new("server error");
|
|
11
|
+
var ErrTimeout = errors.new("timeout");
|
|
12
|
+
var ErrForbidden = errors.new("forbidden");
|
|
13
|
+
var ErrNotFound = errors.new("not found");
|
|
14
|
+
var ErrConflict = errors.new("conflict");
|
|
15
|
+
var ErrExternalAuthorityRequired = errors.new("external authority required");
|
|
16
|
+
var ErrRateLimited = errors.new("rate limited");
|
|
17
|
+
var ErrServiceUnavailable = errors.new("service unavailable");
|
|
18
|
+
var ErrNotSerializable = errors.new("PrimerState is live in-memory state and must not be serialized or stored");
|
|
19
|
+
var ErrInvalidSubmission = errors.new("invalid submission");
|
|
20
|
+
var ErrInvalidSecretKey = errors.new("invalid secret key");
|
|
21
|
+
var ErrStudentNotFound = errors.new("student not found");
|
|
22
|
+
var ErrUnsupportedGrade = errors.new("unsupported grade");
|
|
23
|
+
var ErrTimebackUnavailable = errors.new("timeback unavailable");
|
|
24
|
+
export {
|
|
25
|
+
ErrUnsupportedPci,
|
|
26
|
+
ErrUnsupportedGrade,
|
|
27
|
+
ErrTokenExpired,
|
|
28
|
+
ErrTimeout,
|
|
29
|
+
ErrTimebackUnavailable,
|
|
30
|
+
ErrStudentNotFound,
|
|
31
|
+
ErrServiceUnavailable,
|
|
32
|
+
ErrServerError,
|
|
33
|
+
ErrRateLimited,
|
|
34
|
+
ErrNotSerializable,
|
|
35
|
+
ErrNotFound,
|
|
36
|
+
ErrNetwork,
|
|
37
|
+
ErrMalformedAccessToken,
|
|
38
|
+
ErrJsonParse,
|
|
39
|
+
ErrInvalidSubmission,
|
|
40
|
+
ErrInvalidSecretKey,
|
|
41
|
+
ErrInvalidAccessToken,
|
|
42
|
+
ErrForbidden,
|
|
43
|
+
ErrExternalAuthorityRequired,
|
|
44
|
+
ErrConflict,
|
|
45
|
+
ErrBadRequest
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
//# debugId=4F60AD86845EC38864756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/errors.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import * as errors from \"@superbuilders/errors\"\n\nconst ErrNetwork = errors.new(\"network\")\nconst ErrJsonParse = errors.new(\"json parse\")\nconst ErrUnsupportedPci = errors.new(\"unsupported pci\")\nconst ErrInvalidAccessToken = errors.new(\"invalid access token\")\nconst ErrMalformedAccessToken = errors.new(\"malformed access token\")\nconst ErrTokenExpired = errors.new(\"access token expired\")\nconst ErrBadRequest = errors.new(\"bad request\")\nconst ErrServerError = errors.new(\"server error\")\nconst ErrTimeout = errors.new(\"timeout\")\nconst ErrForbidden = errors.new(\"forbidden\")\nconst ErrNotFound = errors.new(\"not found\")\nconst ErrConflict = errors.new(\"conflict\")\nconst ErrExternalAuthorityRequired = errors.new(\"external authority required\")\nconst ErrRateLimited = errors.new(\"rate limited\")\nconst ErrServiceUnavailable = errors.new(\"service unavailable\")\nconst ErrNotSerializable = errors.new(\n\t\"PrimerState is live in-memory state and must not be serialized or stored\"\n)\nconst ErrInvalidSubmission = errors.new(\"invalid submission\")\n\nconst ErrInvalidSecretKey = errors.new(\"invalid secret key\")\nconst ErrStudentNotFound = errors.new(\"student not found\")\nconst ErrUnsupportedGrade = errors.new(\"unsupported grade\")\nconst ErrTimebackUnavailable = errors.new(\"timeback unavailable\")\n\nexport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrExternalAuthorityRequired,\n\tErrForbidden,\n\tErrInvalidAccessToken,\n\tErrInvalidSecretKey,\n\tErrInvalidSubmission,\n\tErrJsonParse,\n\tErrMalformedAccessToken,\n\tErrNetwork,\n\tErrNotFound,\n\tErrNotSerializable,\n\tErrRateLimited,\n\tErrServerError,\n\tErrServiceUnavailable,\n\tErrStudentNotFound,\n\tErrTimebackUnavailable,\n\tErrTimeout,\n\tErrTokenExpired,\n\tErrUnsupportedGrade,\n\tErrUnsupportedPci\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAAA;AAEA,IAAM,aAAoB,WAAI,SAAS;AACvC,IAAM,eAAsB,WAAI,YAAY;AAC5C,IAAM,oBAA2B,WAAI,iBAAiB;AACtD,IAAM,wBAA+B,WAAI,sBAAsB;AAC/D,IAAM,0BAAiC,WAAI,wBAAwB;AACnE,IAAM,kBAAyB,WAAI,sBAAsB;AACzD,IAAM,gBAAuB,WAAI,aAAa;AAC9C,IAAM,iBAAwB,WAAI,cAAc;AAChD,IAAM,aAAoB,WAAI,SAAS;AACvC,IAAM,eAAsB,WAAI,WAAW;AAC3C,IAAM,cAAqB,WAAI,WAAW;AAC1C,IAAM,cAAqB,WAAI,UAAU;AACzC,IAAM,+BAAsC,WAAI,6BAA6B;AAC7E,IAAM,iBAAwB,WAAI,cAAc;AAChD,IAAM,wBAA+B,WAAI,qBAAqB;AAC9D,IAAM,qBAA4B,WACjC,0EACD;AACA,IAAM,uBAA8B,WAAI,oBAAoB;AAE5D,IAAM,sBAA6B,WAAI,oBAAoB;AAC3D,IAAM,qBAA4B,WAAI,mBAAmB;AACzD,IAAM,sBAA6B,WAAI,mBAAmB;AAC1D,IAAM,yBAAgC,WAAI,sBAAsB;",
|
|
8
|
+
"debugId": "4F60AD86845EC38864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grade-level.d.ts","sourceRoot":"","sources":["../src/grade-level.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,YAAY,+EAAgF,CAAA;AAElG,KAAK,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,UAAU,EAAE,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
// src/contracts/validation.ts
|
|
2
|
+
import { z as z2 } from "zod";
|
|
3
|
+
|
|
4
|
+
// src/contracts/pci-schemas.ts
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var DivisionRemainderPropsSchema = z.object({
|
|
7
|
+
dividend: z.number(),
|
|
8
|
+
divisor: z.number()
|
|
9
|
+
});
|
|
10
|
+
var DivisionRemainderSubmissionSchema = z.object({
|
|
11
|
+
quotient: z.string(),
|
|
12
|
+
remainder: z.string()
|
|
13
|
+
});
|
|
14
|
+
var FractionOperandSchema = z.object({
|
|
15
|
+
numerator: z.number(),
|
|
16
|
+
denominator: z.number()
|
|
17
|
+
});
|
|
18
|
+
var FractionAdditionPropsSchema = z.object({
|
|
19
|
+
left: FractionOperandSchema,
|
|
20
|
+
right: FractionOperandSchema
|
|
21
|
+
});
|
|
22
|
+
var FractionAdditionSubmissionSchema = z.object({
|
|
23
|
+
numerator: z.string(),
|
|
24
|
+
denominator: z.string()
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// src/contracts/validation.ts
|
|
28
|
+
var MatchPairSchema = z2.object({
|
|
29
|
+
source: z2.string(),
|
|
30
|
+
target: z2.string()
|
|
31
|
+
});
|
|
32
|
+
var ChoiceSubmissionSchema = z2.object({
|
|
33
|
+
type: z2.literal("choice"),
|
|
34
|
+
selectedKeys: z2.array(z2.string())
|
|
35
|
+
});
|
|
36
|
+
var TextEntrySubmissionSchema = z2.object({
|
|
37
|
+
type: z2.literal("text-entry"),
|
|
38
|
+
value: z2.string()
|
|
39
|
+
});
|
|
40
|
+
var ExtendedTextSubmissionSchema = z2.object({
|
|
41
|
+
type: z2.literal("extended-text"),
|
|
42
|
+
values: z2.array(z2.string()).min(1)
|
|
43
|
+
});
|
|
44
|
+
var OrderSubmissionSchema = z2.object({
|
|
45
|
+
type: z2.literal("order"),
|
|
46
|
+
orderedKeys: z2.array(z2.string())
|
|
47
|
+
});
|
|
48
|
+
var MatchSubmissionSchema = z2.object({
|
|
49
|
+
type: z2.literal("match"),
|
|
50
|
+
pairs: z2.array(MatchPairSchema)
|
|
51
|
+
});
|
|
52
|
+
var DivisionRemainderPciSubmissionSchema = z2.object({
|
|
53
|
+
type: z2.literal("portable-custom"),
|
|
54
|
+
pciId: z2.literal("urn:primer:pci:division-remainder"),
|
|
55
|
+
value: DivisionRemainderSubmissionSchema
|
|
56
|
+
});
|
|
57
|
+
var FractionAdditionPciSubmissionSchema = z2.object({
|
|
58
|
+
type: z2.literal("portable-custom"),
|
|
59
|
+
pciId: z2.literal("urn:primer:pci:fraction-addition"),
|
|
60
|
+
value: FractionAdditionSubmissionSchema
|
|
61
|
+
});
|
|
62
|
+
var RendererSubmissionSchema = z2.union([
|
|
63
|
+
ChoiceSubmissionSchema,
|
|
64
|
+
TextEntrySubmissionSchema,
|
|
65
|
+
ExtendedTextSubmissionSchema,
|
|
66
|
+
OrderSubmissionSchema,
|
|
67
|
+
MatchSubmissionSchema,
|
|
68
|
+
DivisionRemainderPciSubmissionSchema,
|
|
69
|
+
FractionAdditionPciSubmissionSchema
|
|
70
|
+
]);
|
|
71
|
+
function duplicates(values, keyOf) {
|
|
72
|
+
const seen = new Set;
|
|
73
|
+
const duplicated = new Set;
|
|
74
|
+
for (const value of values) {
|
|
75
|
+
const key = keyOf(value);
|
|
76
|
+
if (seen.has(key)) {
|
|
77
|
+
duplicated.add(key);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
seen.add(key);
|
|
81
|
+
}
|
|
82
|
+
return [...duplicated];
|
|
83
|
+
}
|
|
84
|
+
function findUnknownIds(values, choices) {
|
|
85
|
+
const ids = new Set(choices.map(function getId(choice) {
|
|
86
|
+
return choice.identifier;
|
|
87
|
+
}));
|
|
88
|
+
return values.filter(function isUnknown(value) {
|
|
89
|
+
return !ids.has(value);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function countByIdentifier(pairs, side) {
|
|
93
|
+
const counts = new Map;
|
|
94
|
+
for (const pair of pairs) {
|
|
95
|
+
const key = pair[side];
|
|
96
|
+
const currentCount = counts.get(key);
|
|
97
|
+
if (currentCount === undefined) {
|
|
98
|
+
counts.set(key, 1);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
counts.set(key, currentCount + 1);
|
|
102
|
+
}
|
|
103
|
+
return counts;
|
|
104
|
+
}
|
|
105
|
+
function validateUsageBounds(choices, counts, side) {
|
|
106
|
+
const issues = [];
|
|
107
|
+
for (const choice of choices) {
|
|
108
|
+
const maybeCount = counts.get(choice.identifier);
|
|
109
|
+
const count = maybeCount === undefined ? 0 : maybeCount;
|
|
110
|
+
if (choice.matchMax !== 0 && count > choice.matchMax) {
|
|
111
|
+
issues.push(`${side} '${choice.identifier}' used ${count} times, max ${choice.matchMax}`);
|
|
112
|
+
}
|
|
113
|
+
if (count < choice.matchMin) {
|
|
114
|
+
issues.push(`${side} '${choice.identifier}' used ${count} times, min ${choice.matchMin}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return issues;
|
|
118
|
+
}
|
|
119
|
+
function pciSubmissionSchema(pciId) {
|
|
120
|
+
switch (pciId) {
|
|
121
|
+
case "urn:primer:pci:division-remainder":
|
|
122
|
+
return DivisionRemainderSubmissionSchema;
|
|
123
|
+
case "urn:primer:pci:fraction-addition":
|
|
124
|
+
return FractionAdditionSubmissionSchema;
|
|
125
|
+
}
|
|
126
|
+
const exhaustiveCheck = pciId;
|
|
127
|
+
return exhaustiveCheck;
|
|
128
|
+
}
|
|
129
|
+
function typeMismatch(interactionType, submissionType) {
|
|
130
|
+
return `submission type '${submissionType}' does not match interaction type '${interactionType}'`;
|
|
131
|
+
}
|
|
132
|
+
function buildResult(submission, issues) {
|
|
133
|
+
if (issues.length > 0) {
|
|
134
|
+
return { ok: false, issues };
|
|
135
|
+
}
|
|
136
|
+
return { ok: true, value: submission };
|
|
137
|
+
}
|
|
138
|
+
function validateChoice(interaction, submission) {
|
|
139
|
+
const issues = [];
|
|
140
|
+
if (submission.selectedKeys.length < interaction.minChoices) {
|
|
141
|
+
issues.push(`need at least ${interaction.minChoices} selections`);
|
|
142
|
+
}
|
|
143
|
+
if (submission.selectedKeys.length > interaction.maxChoices) {
|
|
144
|
+
issues.push(`at most ${interaction.maxChoices} selections`);
|
|
145
|
+
}
|
|
146
|
+
const duplicateKeys = duplicates(submission.selectedKeys, function keyOf(value) {
|
|
147
|
+
return value;
|
|
148
|
+
});
|
|
149
|
+
if (duplicateKeys.length > 0) {
|
|
150
|
+
issues.push("duplicate selections");
|
|
151
|
+
}
|
|
152
|
+
const unknownKeys = findUnknownIds(submission.selectedKeys, interaction.options);
|
|
153
|
+
if (unknownKeys.length > 0) {
|
|
154
|
+
issues.push(`unknown options: ${unknownKeys.join(", ")}`);
|
|
155
|
+
}
|
|
156
|
+
return issues;
|
|
157
|
+
}
|
|
158
|
+
function validateExtendedText(interaction, submission) {
|
|
159
|
+
const issues = [];
|
|
160
|
+
if (interaction.cardinality === "single") {
|
|
161
|
+
if (submission.values.length !== 1) {
|
|
162
|
+
issues.push("single-cardinality extended-text requires exactly one value");
|
|
163
|
+
}
|
|
164
|
+
return issues;
|
|
165
|
+
}
|
|
166
|
+
if (submission.values.length < interaction.minStrings) {
|
|
167
|
+
issues.push(`need at least ${interaction.minStrings} values`);
|
|
168
|
+
}
|
|
169
|
+
if (submission.values.length > interaction.maxStrings) {
|
|
170
|
+
issues.push(`at most ${interaction.maxStrings} values`);
|
|
171
|
+
}
|
|
172
|
+
const duplicateValues = duplicates(submission.values, function keyOf(value) {
|
|
173
|
+
return value;
|
|
174
|
+
});
|
|
175
|
+
if (duplicateValues.length > 0) {
|
|
176
|
+
issues.push("duplicate values are not allowed for multiple-cardinality extended-text");
|
|
177
|
+
}
|
|
178
|
+
return issues;
|
|
179
|
+
}
|
|
180
|
+
function validateOrder(interaction, submission) {
|
|
181
|
+
const issues = [];
|
|
182
|
+
if (submission.orderedKeys.length < interaction.minChoices) {
|
|
183
|
+
issues.push(`need at least ${interaction.minChoices} selections`);
|
|
184
|
+
}
|
|
185
|
+
if (submission.orderedKeys.length > interaction.maxChoices) {
|
|
186
|
+
issues.push(`at most ${interaction.maxChoices} selections`);
|
|
187
|
+
}
|
|
188
|
+
const duplicateKeys = duplicates(submission.orderedKeys, function keyOf(value) {
|
|
189
|
+
return value;
|
|
190
|
+
});
|
|
191
|
+
if (duplicateKeys.length > 0) {
|
|
192
|
+
issues.push("duplicate selections");
|
|
193
|
+
}
|
|
194
|
+
const unknownKeys = findUnknownIds(submission.orderedKeys, interaction.choices);
|
|
195
|
+
if (unknownKeys.length > 0) {
|
|
196
|
+
issues.push(`unknown choices: ${unknownKeys.join(", ")}`);
|
|
197
|
+
}
|
|
198
|
+
return issues;
|
|
199
|
+
}
|
|
200
|
+
function validateMatch(interaction, submission) {
|
|
201
|
+
const issues = [];
|
|
202
|
+
if (submission.pairs.length < interaction.minAssociations) {
|
|
203
|
+
issues.push(`need at least ${interaction.minAssociations} associations`);
|
|
204
|
+
}
|
|
205
|
+
if (submission.pairs.length > interaction.maxAssociations) {
|
|
206
|
+
issues.push(`at most ${interaction.maxAssociations} associations`);
|
|
207
|
+
}
|
|
208
|
+
const duplicatePairs = duplicates(submission.pairs, function keyOf(pair) {
|
|
209
|
+
return `${pair.source}->${pair.target}`;
|
|
210
|
+
});
|
|
211
|
+
if (duplicatePairs.length > 0) {
|
|
212
|
+
issues.push("duplicate associations are not allowed");
|
|
213
|
+
}
|
|
214
|
+
const sourceIds = new Set(interaction.sourceChoices.map(function getId(choice) {
|
|
215
|
+
return choice.identifier;
|
|
216
|
+
}));
|
|
217
|
+
const targetIds = new Set(interaction.targetChoices.map(function getId(choice) {
|
|
218
|
+
return choice.identifier;
|
|
219
|
+
}));
|
|
220
|
+
for (const pair of submission.pairs) {
|
|
221
|
+
if (!sourceIds.has(pair.source)) {
|
|
222
|
+
issues.push(`unknown source '${pair.source}'`);
|
|
223
|
+
}
|
|
224
|
+
if (!targetIds.has(pair.target)) {
|
|
225
|
+
issues.push(`unknown target '${pair.target}'`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const sourceCounts = countByIdentifier(submission.pairs, "source");
|
|
229
|
+
const targetCounts = countByIdentifier(submission.pairs, "target");
|
|
230
|
+
issues.push(...validateUsageBounds(interaction.sourceChoices, sourceCounts, "source"));
|
|
231
|
+
issues.push(...validateUsageBounds(interaction.targetChoices, targetCounts, "target"));
|
|
232
|
+
return issues;
|
|
233
|
+
}
|
|
234
|
+
function validatePortableCustom(interaction, submission) {
|
|
235
|
+
if (submission.pciId !== interaction.pciId) {
|
|
236
|
+
return [
|
|
237
|
+
`submission PCI '${submission.pciId}' does not match interaction PCI '${interaction.pciId}'`
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
const schema = pciSubmissionSchema(interaction.pciId);
|
|
241
|
+
const result = schema.safeParse(submission.value);
|
|
242
|
+
if (!result.success) {
|
|
243
|
+
return result.error.issues.map(function toIssue(issue) {
|
|
244
|
+
return issue.message;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return [];
|
|
248
|
+
}
|
|
249
|
+
function validateSubmissionForInteraction(interaction, submission) {
|
|
250
|
+
switch (interaction.type) {
|
|
251
|
+
case "choice":
|
|
252
|
+
if (submission.type !== "choice") {
|
|
253
|
+
return { ok: false, issues: [typeMismatch(interaction.type, submission.type)] };
|
|
254
|
+
}
|
|
255
|
+
return buildResult(submission, validateChoice(interaction, submission));
|
|
256
|
+
case "text-entry":
|
|
257
|
+
if (submission.type !== "text-entry") {
|
|
258
|
+
return { ok: false, issues: [typeMismatch(interaction.type, submission.type)] };
|
|
259
|
+
}
|
|
260
|
+
return { ok: true, value: submission };
|
|
261
|
+
case "extended-text":
|
|
262
|
+
if (submission.type !== "extended-text") {
|
|
263
|
+
return { ok: false, issues: [typeMismatch(interaction.type, submission.type)] };
|
|
264
|
+
}
|
|
265
|
+
return buildResult(submission, validateExtendedText(interaction, submission));
|
|
266
|
+
case "order":
|
|
267
|
+
if (submission.type !== "order") {
|
|
268
|
+
return { ok: false, issues: [typeMismatch(interaction.type, submission.type)] };
|
|
269
|
+
}
|
|
270
|
+
return buildResult(submission, validateOrder(interaction, submission));
|
|
271
|
+
case "match":
|
|
272
|
+
if (submission.type !== "match") {
|
|
273
|
+
return { ok: false, issues: [typeMismatch(interaction.type, submission.type)] };
|
|
274
|
+
}
|
|
275
|
+
return buildResult(submission, validateMatch(interaction, submission));
|
|
276
|
+
case "portable-custom":
|
|
277
|
+
if (submission.type !== "portable-custom") {
|
|
278
|
+
return { ok: false, issues: [typeMismatch(interaction.type, submission.type)] };
|
|
279
|
+
}
|
|
280
|
+
return buildResult(submission, validatePortableCustom(interaction, submission));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function submissionValidationMessage(result) {
|
|
284
|
+
return result.issues.join("; ");
|
|
285
|
+
}
|
|
286
|
+
// src/errors.ts
|
|
287
|
+
import * as errors from "@superbuilders/errors";
|
|
288
|
+
var ErrNetwork = errors.new("network");
|
|
289
|
+
var ErrJsonParse = errors.new("json parse");
|
|
290
|
+
var ErrUnsupportedPci = errors.new("unsupported pci");
|
|
291
|
+
var ErrInvalidAccessToken = errors.new("invalid access token");
|
|
292
|
+
var ErrMalformedAccessToken = errors.new("malformed access token");
|
|
293
|
+
var ErrTokenExpired = errors.new("access token expired");
|
|
294
|
+
var ErrBadRequest = errors.new("bad request");
|
|
295
|
+
var ErrServerError = errors.new("server error");
|
|
296
|
+
var ErrTimeout = errors.new("timeout");
|
|
297
|
+
var ErrForbidden = errors.new("forbidden");
|
|
298
|
+
var ErrNotFound = errors.new("not found");
|
|
299
|
+
var ErrConflict = errors.new("conflict");
|
|
300
|
+
var ErrExternalAuthorityRequired = errors.new("external authority required");
|
|
301
|
+
var ErrRateLimited = errors.new("rate limited");
|
|
302
|
+
var ErrServiceUnavailable = errors.new("service unavailable");
|
|
303
|
+
var ErrNotSerializable = errors.new("PrimerState is live in-memory state and must not be serialized or stored");
|
|
304
|
+
var ErrInvalidSubmission = errors.new("invalid submission");
|
|
305
|
+
var ErrInvalidSecretKey = errors.new("invalid secret key");
|
|
306
|
+
var ErrStudentNotFound = errors.new("student not found");
|
|
307
|
+
var ErrUnsupportedGrade = errors.new("unsupported grade");
|
|
308
|
+
var ErrTimebackUnavailable = errors.new("timeback unavailable");
|
|
309
|
+
export {
|
|
310
|
+
validateSubmissionForInteraction,
|
|
311
|
+
submissionValidationMessage,
|
|
312
|
+
TextEntrySubmissionSchema,
|
|
313
|
+
RendererSubmissionSchema,
|
|
314
|
+
OrderSubmissionSchema,
|
|
315
|
+
MatchSubmissionSchema,
|
|
316
|
+
MatchPairSchema,
|
|
317
|
+
FractionAdditionPciSubmissionSchema,
|
|
318
|
+
ExtendedTextSubmissionSchema,
|
|
319
|
+
ErrUnsupportedPci,
|
|
320
|
+
ErrUnsupportedGrade,
|
|
321
|
+
ErrTokenExpired,
|
|
322
|
+
ErrTimeout,
|
|
323
|
+
ErrTimebackUnavailable,
|
|
324
|
+
ErrStudentNotFound,
|
|
325
|
+
ErrServiceUnavailable,
|
|
326
|
+
ErrServerError,
|
|
327
|
+
ErrRateLimited,
|
|
328
|
+
ErrNotSerializable,
|
|
329
|
+
ErrNotFound,
|
|
330
|
+
ErrNetwork,
|
|
331
|
+
ErrMalformedAccessToken,
|
|
332
|
+
ErrJsonParse,
|
|
333
|
+
ErrInvalidSubmission,
|
|
334
|
+
ErrInvalidSecretKey,
|
|
335
|
+
ErrInvalidAccessToken,
|
|
336
|
+
ErrForbidden,
|
|
337
|
+
ErrExternalAuthorityRequired,
|
|
338
|
+
ErrConflict,
|
|
339
|
+
ErrBadRequest,
|
|
340
|
+
DivisionRemainderPciSubmissionSchema,
|
|
341
|
+
ChoiceSubmissionSchema
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
//# debugId=7E9B1E6A8E723B5D64756E2164756E21
|