@conform-ed/contracts 0.0.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.
Files changed (187) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-format.log +6 -0
  3. package/.turbo/turbo-lint.log +4 -0
  4. package/.turbo/turbo-test.log +196 -0
  5. package/.turbo/turbo-typecheck.log +2 -0
  6. package/README.md +52 -0
  7. package/caliper-v1_2-zod-templates.md +123 -0
  8. package/case-v1_1-zod-templates.md +290 -0
  9. package/cat-v1_0-zod-templates.md +73 -0
  10. package/cc-v1_3-zod-templates.md +531 -0
  11. package/cc-v1_4-zod-templates.md +247 -0
  12. package/clr-v2_0-zod-templates.md +117 -0
  13. package/cmi5-v1_0-zod-templates.md +9 -0
  14. package/lti-zod-templates.md +11 -0
  15. package/oneroster-v1_2-zod-templates.md +76 -0
  16. package/open-badges-v3_0-zod-templates.md +66 -0
  17. package/package.json +42 -0
  18. package/qti-v2_1-zod-templates.md +45 -0
  19. package/qti-v2_2-zod-templates.md +32 -0
  20. package/qti-v3_0_1-zod-templates.md +421 -0
  21. package/src/adapter.ts +83 -0
  22. package/src/caliper/v1_2/caliper_v1p2_bootcamp_schema.ts +781 -0
  23. package/src/caliper/v1_2/index.ts +37 -0
  24. package/src/caliper/v1_2/shared.ts +122 -0
  25. package/src/caliper/v1_2/textual_requirements.ts +219 -0
  26. package/src/case/v1_1/case_v1p1_cfassociation_jsonschema1.ts +1 -0
  27. package/src/case/v1_1/case_v1p1_cfassociationgrouping_jsonschema1.ts +1 -0
  28. package/src/case/v1_1/case_v1p1_cfassociationset_jsonschema1.ts +1 -0
  29. package/src/case/v1_1/case_v1p1_cfconceptset_jsonschema1.ts +1 -0
  30. package/src/case/v1_1/case_v1p1_cfdocument_jsonschema1.ts +1 -0
  31. package/src/case/v1_1/case_v1p1_cfdocumentset_jsonschema1.ts +1 -0
  32. package/src/case/v1_1/case_v1p1_cfitem_jsonschema1.ts +1 -0
  33. package/src/case/v1_1/case_v1p1_cfitemtypeset_jsonschema1.ts +1 -0
  34. package/src/case/v1_1/case_v1p1_cflicense_jsonschema1.ts +1 -0
  35. package/src/case/v1_1/case_v1p1_cfpackage_jsonschema1.ts +1 -0
  36. package/src/case/v1_1/case_v1p1_cfrubric_jsonschema1.ts +1 -0
  37. package/src/case/v1_1/case_v1p1_cfsubjectset_jsonschema1.ts +1 -0
  38. package/src/case/v1_1/case_v1p1_imsx_statusinfo_jsonschema1.ts +1 -0
  39. package/src/case/v1_1/case_v1p1_openapi3_restbinding_schema.ts +113 -0
  40. package/src/case/v1_1/index.ts +95 -0
  41. package/src/case/v1_1/shared.ts +384 -0
  42. package/src/cat/v1_0/cat_v1p0_restbinding_operations_schema.ts +75 -0
  43. package/src/cat/v1_0/index.ts +124 -0
  44. package/src/cat/v1_0/shared.ts +345 -0
  45. package/src/clr/v2_0/clr_v2p0_achievementcredential_schema.ts +16 -0
  46. package/src/clr/v2_0/clr_v2p0_clrcredential_schema.ts +9 -0
  47. package/src/clr/v2_0/clr_v2p0_endorsementcredential_schema.ts +11 -0
  48. package/src/clr/v2_0/clr_v2p0_getclrcredentialsresponse_schema.ts +1 -0
  49. package/src/clr/v2_0/clr_v2p0_imsx_statusinfo_schema.ts +8 -0
  50. package/src/clr/v2_0/clr_v2p0_profile_schema.ts +9 -0
  51. package/src/clr/v2_0/index.ts +22 -0
  52. package/src/clr/v2_0/shared.ts +206 -0
  53. package/src/cmi5/index.ts +3 -0
  54. package/src/cmi5/v1_0/index.ts +134 -0
  55. package/src/common-cartridge/v1_3/ccv1p3_imsccauth_v1p3.ts +26 -0
  56. package/src/common-cartridge/v1_3/ccv1p3_imscp_v1p2_v1p0.ts +352 -0
  57. package/src/common-cartridge/v1_3/ccv1p3_imscsmd_v1p0.ts +35 -0
  58. package/src/common-cartridge/v1_3/ccv1p3_imsdt_v1p3.ts +33 -0
  59. package/src/common-cartridge/v1_3/ccv1p3_imswl_v1p3.ts +23 -0
  60. package/src/common-cartridge/v1_3/ccv1p3_lomccltilink_v1p0.ts +14 -0
  61. package/src/common-cartridge/v1_3/ccv1p3_lommanifest_v1p0.ts +14 -0
  62. package/src/common-cartridge/v1_3/ccv1p3_lomresource_v1p0.ts +14 -0
  63. package/src/common-cartridge/v1_3/ccv1p3_qtiasiv1p2p1_v1p0.ts +964 -0
  64. package/src/common-cartridge/v1_3/index.ts +41 -0
  65. package/src/common-cartridge/v1_3/lom-internal.ts +396 -0
  66. package/src/common-cartridge/v1_3/shared.ts +68 -0
  67. package/src/common-cartridge/v1_4/core/ccv1p4_imscp_v1p2_v1p0.ts +360 -0
  68. package/src/common-cartridge/v1_4/core/ccv1p4_lommanifest_v1p0.ts +14 -0
  69. package/src/common-cartridge/v1_4/core/ccv1p4_lomresource_v1p0.ts +14 -0
  70. package/src/common-cartridge/v1_4/extension/cc_extresource_assignmentv1p0_v1p0.ts +61 -0
  71. package/src/common-cartridge/v1_4/extension/ccv1p4_cpextensionv1p2_v1p0.ts +20 -0
  72. package/src/common-cartridge/v1_4/extension/ims_openvideov1p0_v1p0.ts +325 -0
  73. package/src/common-cartridge/v1_4/index.ts +104 -0
  74. package/src/common-cartridge/v1_4/k12/ccv1p4_imscp_v1p2_v1p0.ts +19 -0
  75. package/src/common-cartridge/v1_4/k12/ccv1p4_imscp_v1p2_v1p0_thin.ts +17 -0
  76. package/src/common-cartridge/v1_4/k12/ccv1p4_lommanifest_v1p0.ts +14 -0
  77. package/src/common-cartridge/v1_4/k12/ccv1p4_lomresource_v1p0.ts +14 -0
  78. package/src/common-cartridge/v1_4/lom-internal.ts +476 -0
  79. package/src/common-cartridge/v1_4/shared/ccv1p4_imsccauth_v1p4.ts +26 -0
  80. package/src/common-cartridge/v1_4/shared/ccv1p4_imscsmd_v1p1.ts +36 -0
  81. package/src/common-cartridge/v1_4/shared/ccv1p4_imsdt_v1p4.ts +33 -0
  82. package/src/common-cartridge/v1_4/shared/ccv1p4_imslticc_v1p4.ts +45 -0
  83. package/src/common-cartridge/v1_4/shared/ccv1p4_imswl_v1p4.ts +23 -0
  84. package/src/common-cartridge/v1_4/shared/ccv1p4_lomccltilink_v1p0.ts +14 -0
  85. package/src/common-cartridge/v1_4/shared/ccv1p4_qtiasiv1p2p1_v1p0.ts +964 -0
  86. package/src/common-cartridge/v1_4/shared/imsbasiclti_v1p0p1.ts +24 -0
  87. package/src/common-cartridge/v1_4/shared/imslticm_v1p0.ts +23 -0
  88. package/src/common-cartridge/v1_4/shared/imslticp_v1p0.ts +57 -0
  89. package/src/common-cartridge/v1_4/shared/lineitem_v1p0.ts +35 -0
  90. package/src/common-cartridge/v1_4/shared/resourcea11ymetadata-20210915.ts +110 -0
  91. package/src/common-cartridge/v1_4/shared.ts +68 -0
  92. package/src/common-cartridge/v1_4/thin/ccv1p4_imscp_v1p2_v1p0.ts +243 -0
  93. package/src/common-cartridge/v1_4/thin/ccv1p4_lommanifest_v1p0.ts +14 -0
  94. package/src/common-cartridge/v1_4/thin/ccv1p4_lomresource_v1p0.ts +14 -0
  95. package/src/common-cartridge/v1_4/vdex/imsmd_loose_v1p3p2.ts +13 -0
  96. package/src/common-cartridge/v1_4/vdex/imsvdex_v1p0.ts +124 -0
  97. package/src/config.ts +121 -0
  98. package/src/index.ts +32 -0
  99. package/src/lti/ags/v2_0/index.ts +97 -0
  100. package/src/lti/deep-linking/v2_0/index.ts +100 -0
  101. package/src/lti/index.ts +26 -0
  102. package/src/lti/nrps/v2_0/index.ts +69 -0
  103. package/src/lti/proctoring/v1_0/index.ts +131 -0
  104. package/src/lti/shared.ts +66 -0
  105. package/src/lti/v1_3/index.ts +84 -0
  106. package/src/oneroster/v1_2/index.ts +156 -0
  107. package/src/oneroster/v1_2/or_v1p2_csv_binding_schema.ts +427 -0
  108. package/src/oneroster/v1_2/or_v1p2_gradebook_restbinding_schema.ts +120 -0
  109. package/src/oneroster/v1_2/or_v1p2_gradebook_service_schema.ts +243 -0
  110. package/src/oneroster/v1_2/or_v1p2_resource_restbinding_schema.ts +24 -0
  111. package/src/oneroster/v1_2/or_v1p2_resource_service_schema.ts +47 -0
  112. package/src/oneroster/v1_2/or_v1p2_rostering_restbinding_schema.ts +84 -0
  113. package/src/oneroster/v1_2/or_v1p2_rostering_service_schema.ts +288 -0
  114. package/src/oneroster/v1_2/shared.ts +90 -0
  115. package/src/open-badges/v3_0/index.ts +20 -0
  116. package/src/open-badges/v3_0/ob_v3p0_achievementcredential_schema.ts +17 -0
  117. package/src/open-badges/v3_0/ob_v3p0_endorsementcredential_schema.ts +11 -0
  118. package/src/open-badges/v3_0/ob_v3p0_getopenbadgecredentialsresponse_schema.ts +1 -0
  119. package/src/open-badges/v3_0/ob_v3p0_imsx_statusinfo_schema.ts +8 -0
  120. package/src/open-badges/v3_0/ob_v3p0_profile_schema.ts +9 -0
  121. package/src/open-badges/v3_0/shared.ts +458 -0
  122. package/src/qti/v2-internal.ts +1683 -0
  123. package/src/qti/v2_1/apipv1p0_qtiextv2p1_v1p0.ts +3 -0
  124. package/src/qti/v2_1/imsqti_metadata_v2p1.ts +3 -0
  125. package/src/qti/v2_1/imsqti_result_v2p1.ts +3 -0
  126. package/src/qti/v2_1/imsqti_usagedata_v2p1.ts +3 -0
  127. package/src/qti/v2_1/imsqti_v2p1p2.ts +71 -0
  128. package/src/qti/v2_1/index.ts +53 -0
  129. package/src/qti/v2_1/qtiv2p1_imscpv1p2_v1p0.ts +3 -0
  130. package/src/qti/v2_1/schemas.ts +15 -0
  131. package/src/qti/v2_1/shared.ts +3 -0
  132. package/src/qti/v2_2/apipv1p0_qtiextv2p2_v1p0p1.ts +3 -0
  133. package/src/qti/v2_2/imsqti_metadata_v2p2.ts +3 -0
  134. package/src/qti/v2_2/imsqti_result_v2p2.ts +3 -0
  135. package/src/qti/v2_2/imsqti_usagedata_v2p2.ts +3 -0
  136. package/src/qti/v2_2/imsqti_v2p2p4.ts +76 -0
  137. package/src/qti/v2_2/imsqtiv2p2p4_html5_v1p0.ts +8 -0
  138. package/src/qti/v2_2/index.ts +59 -0
  139. package/src/qti/v2_2/qtiv2p2_csm_v2p2.ts +4 -0
  140. package/src/qti/v2_2/qtiv2p2_imscpv1p2_v1p0.ts +3 -0
  141. package/src/qti/v2_2/schemas.ts +19 -0
  142. package/src/qti/v2_2/shared.ts +3 -0
  143. package/src/qti/v3_0_1/assessment-internal.ts +1509 -0
  144. package/src/qti/v3_0_1/imsqti_asiv3p0p1_v1p0.ts +57 -0
  145. package/src/qti/v3_0_1/imsqti_itemv3p0p1_v1p0.ts +60 -0
  146. package/src/qti/v3_0_1/imsqti_metadatav3p0_v1p0.ts +73 -0
  147. package/src/qti/v3_0_1/imsqti_outcomev3p0p1_v1p0.ts +11 -0
  148. package/src/qti/v3_0_1/imsqti_responseprocessingv3p0p1_v1p0.ts +17 -0
  149. package/src/qti/v3_0_1/imsqti_resultv3p0_v1p0.ts +222 -0
  150. package/src/qti/v3_0_1/imsqti_sectionv3p0p1_v1p0.ts +15 -0
  151. package/src/qti/v3_0_1/imsqti_stimulusv3p0p1_v1p0.ts +15 -0
  152. package/src/qti/v3_0_1/imsqti_testv3p0p1_v1p0.ts +49 -0
  153. package/src/qti/v3_0_1/imsqti_usagedatav3p0_v1p0.ts +77 -0
  154. package/src/qti/v3_0_1/imsqtiv3p0_afa3p0pnp_v1p0.ts +269 -0
  155. package/src/qti/v3_0_1/index.ts +50 -0
  156. package/src/qti/v3_0_1/processing-internal.ts +667 -0
  157. package/src/qti/v3_0_1/shared.ts +146 -0
  158. package/src/qti/v3_0_1/variables-internal.ts +274 -0
  159. package/src/shared/imsx-status.ts +49 -0
  160. package/src/summary.ts +70 -0
  161. package/src/vc-data-model/v2_0/index.ts +27 -0
  162. package/src/vc-data-model/v2_0/shared.ts +206 -0
  163. package/src/xapi/index.ts +12 -0
  164. package/src/xapi/shared.ts +444 -0
  165. package/src/xapi/v1_0_3/index.ts +169 -0
  166. package/src/xapi/v2_0/index.ts +256 -0
  167. package/test/caliper-v1_2.test.ts +270 -0
  168. package/test/case-v1_1.test.ts +147 -0
  169. package/test/cat-v1_0.test.ts +338 -0
  170. package/test/cc-v1_4.test.ts +239 -0
  171. package/test/clr-v2_0.test.ts +225 -0
  172. package/test/cmi5-v1_0.test.ts +196 -0
  173. package/test/contracts.test.ts +125 -0
  174. package/test/fixtures/cmi5/extended-cmi5.xml +72 -0
  175. package/test/fixtures/cmi5/simple-cmi5.xml +26 -0
  176. package/test/lti.test.ts +146 -0
  177. package/test/oneroster-v1_2.test.ts +234 -0
  178. package/test/open-badges-v3_0.test.ts +144 -0
  179. package/test/qti-v2_1.test.ts +146 -0
  180. package/test/qti-v2_2.test.ts +154 -0
  181. package/test/qti-v3_0_1.test.ts +576 -0
  182. package/test/schema-examples.test.ts +101 -0
  183. package/test/vc-data-model-v2_0.test.ts +63 -0
  184. package/test/xapi.test.ts +384 -0
  185. package/tsconfig.json +7 -0
  186. package/vc-data-model-v2_0-zod-templates.md +43 -0
  187. package/xapi-zod-templates.md +95 -0
@@ -0,0 +1,667 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ addIssue,
5
+ QtiBaseTypeSchema,
6
+ QtiCoordsSchema,
7
+ QtiIdentifierSchema,
8
+ QtiIdentifierListSchema,
9
+ QtiIntegerOrVariableSchema,
10
+ QtiNumberOrVariableSchema,
11
+ QtiShapeSchema,
12
+ strictObject,
13
+ } from "./shared";
14
+
15
+ const unaryExpressionKinds = [
16
+ "not",
17
+ "random",
18
+ "round",
19
+ "truncate",
20
+ "containerSize",
21
+ "isNull",
22
+ "integerToFloat",
23
+ ] as const;
24
+
25
+ const binaryExpressionKinds = [
26
+ "gt",
27
+ "lt",
28
+ "gte",
29
+ "lte",
30
+ "durationLt",
31
+ "durationGte",
32
+ "subtract",
33
+ "divide",
34
+ "delete",
35
+ "match",
36
+ "equal",
37
+ "integerDivide",
38
+ "integerModulus",
39
+ "contains",
40
+ "member",
41
+ "power",
42
+ ] as const;
43
+
44
+ const oneToManyExpressionKinds = ["and", "or", "sum", "product", "lcm", "gcd", "min", "max"] as const;
45
+
46
+ const containerExpressionKinds = ["multiple", "ordered"] as const;
47
+
48
+ const qtiRoundingModeValues = ["decimalPlaces", "significantFigures"] as const;
49
+ const qtiStatsOperatorNames = ["mean", "sampleVariance", "sampleSD", "popVariance", "popSD"] as const;
50
+ const qtiMathOperatorNames = [
51
+ "sin",
52
+ "cos",
53
+ "tan",
54
+ "sec",
55
+ "csc",
56
+ "cot",
57
+ "asin",
58
+ "acos",
59
+ "atan",
60
+ "atan2",
61
+ "asec",
62
+ "acsc",
63
+ "acot",
64
+ "sinh",
65
+ "cosh",
66
+ "tanh",
67
+ "sech",
68
+ "csch",
69
+ "coth",
70
+ "log",
71
+ "ln",
72
+ "exp",
73
+ "abs",
74
+ "signum",
75
+ "floor",
76
+ "ceil",
77
+ "toDegrees",
78
+ "toRadians",
79
+ ] as const;
80
+
81
+ const QtiRoundingModeSchema = z.enum(qtiRoundingModeValues);
82
+ const QtiStatsOperatorNameSchema = z.enum(qtiStatsOperatorNames);
83
+ const QtiMathOperatorNameSchema = z.enum(qtiMathOperatorNames);
84
+
85
+ const QtiOutcomeSubsetSelectionShape = {
86
+ sectionIdentifier: QtiIdentifierSchema.optional(),
87
+ includeCategory: QtiIdentifierListSchema.optional(),
88
+ excludeCategory: QtiIdentifierListSchema.optional(),
89
+ };
90
+
91
+ function validatePositiveNumericLiteral(
92
+ value: number | string | undefined,
93
+ context: z.RefinementCtx,
94
+ path: Array<string | number>,
95
+ label: string,
96
+ minimum = 1,
97
+ ) {
98
+ if (typeof value === "number" && value < minimum) {
99
+ addIssue(context, path, `${label} must be greater than or equal to ${minimum}.`);
100
+ }
101
+ }
102
+
103
+ function validateOrderedNumericLiteralRange(
104
+ min: number | string | undefined,
105
+ max: number | string | undefined,
106
+ context: z.RefinementCtx,
107
+ path: Array<string | number>,
108
+ label: string,
109
+ ) {
110
+ if (typeof min === "number" && typeof max === "number" && min > max) {
111
+ addIssue(context, path, `${label} minimum must not exceed its maximum.`);
112
+ }
113
+ }
114
+
115
+ export const QtiIncludeSchema = strictObject({
116
+ kind: z.literal("include"),
117
+ href: z.string().optional(),
118
+ parse: z.string().optional(),
119
+ xpointer: z.string().optional(),
120
+ });
121
+
122
+ export const QtiNullExpressionSchema = strictObject({
123
+ kind: z.literal("null"),
124
+ });
125
+
126
+ export const QtiBaseValueExpressionSchema = strictObject({
127
+ kind: z.literal("baseValue"),
128
+ baseType: QtiBaseTypeSchema,
129
+ value: z.string(),
130
+ });
131
+
132
+ export const QtiVariableExpressionSchema = strictObject({
133
+ kind: z.literal("variable"),
134
+ identifier: QtiIdentifierSchema,
135
+ weightIdentifier: QtiIdentifierSchema.optional(),
136
+ });
137
+
138
+ export const QtiCorrectExpressionSchema = strictObject({
139
+ kind: z.literal("correct"),
140
+ identifier: QtiIdentifierSchema,
141
+ });
142
+
143
+ export const QtiDefaultExpressionSchema = strictObject({
144
+ kind: z.literal("default"),
145
+ identifier: QtiIdentifierSchema,
146
+ });
147
+
148
+ export const QtiMapResponseExpressionSchema = strictObject({
149
+ kind: z.literal("mapResponse"),
150
+ identifier: QtiIdentifierSchema,
151
+ });
152
+
153
+ export const QtiMapResponsePointExpressionSchema = strictObject({
154
+ kind: z.literal("mapResponsePoint"),
155
+ identifier: QtiIdentifierSchema,
156
+ });
157
+
158
+ export const QtiRandomIntegerExpressionSchema = strictObject({
159
+ kind: z.literal("randomInteger"),
160
+ min: QtiIntegerOrVariableSchema.optional(),
161
+ max: QtiIntegerOrVariableSchema,
162
+ step: QtiIntegerOrVariableSchema.optional(),
163
+ }).superRefine((value, context) => {
164
+ validateOrderedNumericLiteralRange(value.min, value.max, context, ["max"], "randomInteger");
165
+ validatePositiveNumericLiteral(value.step, context, ["step"], "randomInteger step");
166
+ });
167
+
168
+ export const QtiRandomFloatExpressionSchema = strictObject({
169
+ kind: z.literal("randomFloat"),
170
+ min: QtiNumberOrVariableSchema.optional(),
171
+ max: QtiNumberOrVariableSchema,
172
+ }).superRefine((value, context) => {
173
+ validateOrderedNumericLiteralRange(value.min, value.max, context, ["max"], "randomFloat");
174
+ });
175
+
176
+ export const QtiMathConstantExpressionSchema = strictObject({
177
+ kind: z.literal("mathConstant"),
178
+ name: z.enum(["pi", "e"]),
179
+ });
180
+
181
+ export const QtiUnaryExpressionSchema: z.ZodTypeAny = z.lazy(() =>
182
+ strictObject({
183
+ kind: z.enum(unaryExpressionKinds),
184
+ children: z.tuple([QtiExpressionSchema]),
185
+ }),
186
+ );
187
+
188
+ export const QtiBinaryExpressionSchema: z.ZodTypeAny = z.lazy(() =>
189
+ strictObject({
190
+ kind: z.enum(binaryExpressionKinds),
191
+ children: z.tuple([QtiExpressionSchema, QtiExpressionSchema]),
192
+ }),
193
+ );
194
+
195
+ export const QtiOneToManyExpressionSchema: z.ZodTypeAny = z.lazy(() =>
196
+ strictObject({
197
+ kind: z.enum(oneToManyExpressionKinds),
198
+ children: z.array(QtiExpressionSchema).min(1),
199
+ }),
200
+ );
201
+
202
+ export const QtiContainerExpressionSchema: z.ZodTypeAny = z.lazy(() =>
203
+ strictObject({
204
+ kind: z.enum(containerExpressionKinds),
205
+ children: z.array(QtiExpressionSchema),
206
+ }),
207
+ );
208
+
209
+ export const QtiCustomOperatorExpressionSchema: z.ZodTypeAny = z.lazy(() =>
210
+ strictObject({
211
+ kind: z.literal("customOperator"),
212
+ children: z.array(QtiExpressionSchema).optional(),
213
+ class: QtiIdentifierSchema.optional(),
214
+ definition: z.string().optional(),
215
+ attributes: z.record(z.string(), z.unknown()).optional(),
216
+ }),
217
+ );
218
+
219
+ export const QtiAnyNExpressionSchema: z.ZodTypeAny = z.lazy(() =>
220
+ strictObject({
221
+ kind: z.literal("anyN"),
222
+ children: z.array(QtiExpressionSchema).min(1),
223
+ min: QtiIntegerOrVariableSchema,
224
+ max: QtiIntegerOrVariableSchema,
225
+ }).superRefine((value, context) => {
226
+ validatePositiveNumericLiteral(value.min, context, ["min"], "anyN min", 0);
227
+ validatePositiveNumericLiteral(value.max, context, ["max"], "anyN max", 0);
228
+ validateOrderedNumericLiteralRange(value.min, value.max, context, ["max"], "anyN");
229
+
230
+ if (typeof value.min === "number" && value.min > value.children.length) {
231
+ addIssue(context, ["min"], "anyN min must not exceed the number of child expressions.");
232
+ }
233
+
234
+ if (typeof value.max === "number" && value.max > value.children.length) {
235
+ addIssue(context, ["max"], "anyN max must not exceed the number of child expressions.");
236
+ }
237
+ }),
238
+ );
239
+
240
+ export const QtiEqualRoundedExpressionSchema: z.ZodTypeAny = z.lazy(() =>
241
+ strictObject({
242
+ kind: z.literal("equalRounded"),
243
+ children: z.tuple([QtiExpressionSchema, QtiExpressionSchema]),
244
+ roundingMode: QtiRoundingModeSchema.optional(),
245
+ figures: QtiIntegerOrVariableSchema,
246
+ }).superRefine((value, context) => {
247
+ validatePositiveNumericLiteral(value.figures, context, ["figures"], "equalRounded figures");
248
+ }),
249
+ );
250
+
251
+ export const QtiFieldValueExpressionSchema: z.ZodTypeAny = z.lazy(() =>
252
+ strictObject({
253
+ kind: z.literal("fieldValue"),
254
+ children: z.tuple([QtiExpressionSchema]),
255
+ fieldIdentifier: QtiIdentifierSchema,
256
+ }),
257
+ );
258
+
259
+ export const QtiIndexExpressionSchema: z.ZodTypeAny = z.lazy(() =>
260
+ strictObject({
261
+ kind: z.literal("index"),
262
+ children: z.tuple([QtiExpressionSchema]),
263
+ n: QtiIntegerOrVariableSchema,
264
+ }).superRefine((value, context) => {
265
+ validatePositiveNumericLiteral(value.n, context, ["n"], "index n");
266
+ }),
267
+ );
268
+
269
+ export const QtiInsideExpressionSchema: z.ZodTypeAny = z.lazy(() =>
270
+ strictObject({
271
+ kind: z.literal("inside"),
272
+ children: z.tuple([QtiExpressionSchema]),
273
+ shape: QtiShapeSchema,
274
+ coords: QtiCoordsSchema,
275
+ }),
276
+ );
277
+
278
+ export const QtiMathOperatorExpressionSchema: z.ZodTypeAny = z.lazy(() =>
279
+ strictObject({
280
+ kind: z.literal("mathOperator"),
281
+ children: z.array(QtiExpressionSchema).min(1),
282
+ name: QtiMathOperatorNameSchema,
283
+ }).superRefine((value, context) => {
284
+ const expectedArity = value.name === "atan2" ? 2 : 1;
285
+
286
+ if (value.children.length !== expectedArity) {
287
+ addIssue(
288
+ context,
289
+ ["children"],
290
+ `mathOperator '${value.name}' requires exactly ${expectedArity} operand${expectedArity === 1 ? "" : "s"}.`,
291
+ );
292
+ }
293
+ }),
294
+ );
295
+
296
+ export const QtiPatternMatchExpressionSchema: z.ZodTypeAny = z.lazy(() =>
297
+ strictObject({
298
+ kind: z.literal("patternMatch"),
299
+ children: z.tuple([QtiExpressionSchema]),
300
+ pattern: z.string(),
301
+ }),
302
+ );
303
+
304
+ export const QtiRepeatExpressionSchema: z.ZodTypeAny = z.lazy(() =>
305
+ strictObject({
306
+ kind: z.literal("repeat"),
307
+ children: z.array(QtiExpressionSchema).min(1),
308
+ numberRepeats: QtiIntegerOrVariableSchema,
309
+ }).superRefine((value, context) => {
310
+ validatePositiveNumericLiteral(value.numberRepeats, context, ["numberRepeats"], "repeat numberRepeats");
311
+ }),
312
+ );
313
+
314
+ export const QtiRoundToExpressionSchema: z.ZodTypeAny = z.lazy(() =>
315
+ strictObject({
316
+ kind: z.literal("roundTo"),
317
+ children: z.tuple([QtiExpressionSchema]),
318
+ roundingMode: QtiRoundingModeSchema,
319
+ figures: QtiIntegerOrVariableSchema,
320
+ }).superRefine((value, context) => {
321
+ validatePositiveNumericLiteral(value.figures, context, ["figures"], "roundTo figures");
322
+ }),
323
+ );
324
+
325
+ export const QtiStatsOperatorExpressionSchema: z.ZodTypeAny = z.lazy(() =>
326
+ strictObject({
327
+ kind: z.literal("statsOperator"),
328
+ children: z.tuple([QtiExpressionSchema]),
329
+ name: QtiStatsOperatorNameSchema,
330
+ }),
331
+ );
332
+
333
+ export const QtiStringMatchExpressionSchema: z.ZodTypeAny = z.lazy(() =>
334
+ strictObject({
335
+ kind: z.literal("stringMatch"),
336
+ children: z.tuple([QtiExpressionSchema, QtiExpressionSchema]),
337
+ caseSensitive: z.boolean(),
338
+ substring: z.boolean().optional(),
339
+ }),
340
+ );
341
+
342
+ export const QtiSubstringExpressionSchema: z.ZodTypeAny = z.lazy(() =>
343
+ strictObject({
344
+ kind: z.literal("substring"),
345
+ children: z.tuple([QtiExpressionSchema, QtiExpressionSchema]),
346
+ caseSensitive: z.boolean(),
347
+ }),
348
+ );
349
+
350
+ export const QtiNumberCorrectExpressionSchema = strictObject({
351
+ kind: z.literal("numberCorrect"),
352
+ ...QtiOutcomeSubsetSelectionShape,
353
+ });
354
+
355
+ export const QtiNumberIncorrectExpressionSchema = strictObject({
356
+ kind: z.literal("numberIncorrect"),
357
+ ...QtiOutcomeSubsetSelectionShape,
358
+ });
359
+
360
+ export const QtiNumberPresentedExpressionSchema = strictObject({
361
+ kind: z.literal("numberPresented"),
362
+ ...QtiOutcomeSubsetSelectionShape,
363
+ });
364
+
365
+ export const QtiNumberRespondedExpressionSchema = strictObject({
366
+ kind: z.literal("numberResponded"),
367
+ ...QtiOutcomeSubsetSelectionShape,
368
+ });
369
+
370
+ export const QtiNumberSelectedExpressionSchema = strictObject({
371
+ kind: z.literal("numberSelected"),
372
+ ...QtiOutcomeSubsetSelectionShape,
373
+ });
374
+
375
+ export const QtiOutcomeMinimumExpressionSchema = strictObject({
376
+ kind: z.literal("outcomeMinimum"),
377
+ ...QtiOutcomeSubsetSelectionShape,
378
+ outcomeIdentifier: QtiIdentifierSchema,
379
+ weightIdentifier: QtiIdentifierSchema.optional(),
380
+ });
381
+
382
+ export const QtiOutcomeMaximumExpressionSchema = strictObject({
383
+ kind: z.literal("outcomeMaximum"),
384
+ ...QtiOutcomeSubsetSelectionShape,
385
+ outcomeIdentifier: QtiIdentifierSchema,
386
+ weightIdentifier: QtiIdentifierSchema.optional(),
387
+ });
388
+
389
+ export const QtiTestVariablesExpressionSchema = strictObject({
390
+ kind: z.literal("testVariables"),
391
+ ...QtiOutcomeSubsetSelectionShape,
392
+ variableIdentifier: QtiIdentifierSchema,
393
+ weightIdentifier: QtiIdentifierSchema.optional(),
394
+ baseType: QtiBaseTypeSchema.optional(),
395
+ });
396
+
397
+ export const QtiExpressionSchema: z.ZodTypeAny = z.lazy(() =>
398
+ z.union([
399
+ QtiNullExpressionSchema,
400
+ QtiBaseValueExpressionSchema,
401
+ QtiVariableExpressionSchema,
402
+ QtiCorrectExpressionSchema,
403
+ QtiDefaultExpressionSchema,
404
+ QtiMapResponseExpressionSchema,
405
+ QtiMapResponsePointExpressionSchema,
406
+ QtiRandomIntegerExpressionSchema,
407
+ QtiRandomFloatExpressionSchema,
408
+ QtiMathConstantExpressionSchema,
409
+ QtiUnaryExpressionSchema,
410
+ QtiBinaryExpressionSchema,
411
+ QtiOneToManyExpressionSchema,
412
+ QtiContainerExpressionSchema,
413
+ QtiCustomOperatorExpressionSchema,
414
+ QtiAnyNExpressionSchema,
415
+ QtiEqualRoundedExpressionSchema,
416
+ QtiFieldValueExpressionSchema,
417
+ QtiIndexExpressionSchema,
418
+ QtiInsideExpressionSchema,
419
+ QtiMathOperatorExpressionSchema,
420
+ QtiPatternMatchExpressionSchema,
421
+ QtiRepeatExpressionSchema,
422
+ QtiRoundToExpressionSchema,
423
+ QtiStatsOperatorExpressionSchema,
424
+ QtiStringMatchExpressionSchema,
425
+ QtiSubstringExpressionSchema,
426
+ QtiNumberCorrectExpressionSchema,
427
+ QtiNumberIncorrectExpressionSchema,
428
+ QtiNumberPresentedExpressionSchema,
429
+ QtiNumberRespondedExpressionSchema,
430
+ QtiNumberSelectedExpressionSchema,
431
+ QtiOutcomeMinimumExpressionSchema,
432
+ QtiOutcomeMaximumExpressionSchema,
433
+ QtiTestVariablesExpressionSchema,
434
+ ]),
435
+ );
436
+
437
+ export const QtiPreConditionSchema = strictObject({
438
+ kind: z.literal("preCondition"),
439
+ expression: QtiExpressionSchema,
440
+ });
441
+
442
+ export const QtiBranchRuleSchema = strictObject({
443
+ kind: z.literal("branchRule"),
444
+ target: QtiIdentifierSchema,
445
+ expression: QtiExpressionSchema,
446
+ });
447
+
448
+ export const QtiLookupOutcomeValueSchema = strictObject({
449
+ kind: z.literal("lookupOutcomeValue"),
450
+ identifier: QtiIdentifierSchema,
451
+ expression: QtiExpressionSchema,
452
+ });
453
+
454
+ export const QtiSetOutcomeValueSchema = strictObject({
455
+ kind: z.literal("setOutcomeValue"),
456
+ identifier: QtiIdentifierSchema,
457
+ expression: QtiExpressionSchema,
458
+ });
459
+
460
+ export const QtiSetTemplateValueSchema = strictObject({
461
+ kind: z.literal("setTemplateValue"),
462
+ identifier: QtiIdentifierSchema,
463
+ expression: QtiExpressionSchema,
464
+ });
465
+
466
+ export const QtiSetDefaultValueSchema = strictObject({
467
+ kind: z.literal("setDefaultValue"),
468
+ identifier: QtiIdentifierSchema,
469
+ expression: QtiExpressionSchema,
470
+ });
471
+
472
+ export const QtiSetCorrectResponseSchema = strictObject({
473
+ kind: z.literal("setCorrectResponse"),
474
+ identifier: QtiIdentifierSchema,
475
+ expression: QtiExpressionSchema,
476
+ });
477
+
478
+ export const QtiTemplateDefaultSchema = strictObject({
479
+ kind: z.literal("templateDefault"),
480
+ templateIdentifier: QtiIdentifierSchema,
481
+ expression: QtiExpressionSchema,
482
+ });
483
+
484
+ export const QtiTemplateConstraintSchema = strictObject({
485
+ kind: z.literal("templateConstraint"),
486
+ expression: QtiExpressionSchema,
487
+ });
488
+
489
+ export const QtiExitResponseSchema = strictObject({
490
+ kind: z.literal("exitResponse"),
491
+ });
492
+
493
+ export const QtiExitTemplateSchema = strictObject({
494
+ kind: z.literal("exitTemplate"),
495
+ });
496
+
497
+ export const QtiExitTestSchema = strictObject({
498
+ kind: z.literal("exitTest"),
499
+ });
500
+
501
+ export const QtiResponseElseSchema: z.ZodTypeAny = z.lazy(() =>
502
+ strictObject({
503
+ kind: z.literal("responseElse"),
504
+ actions: z.array(QtiResponseRuleSchema).optional(),
505
+ }),
506
+ );
507
+
508
+ export const QtiResponseIfSchema: z.ZodTypeAny = z.lazy(() =>
509
+ strictObject({
510
+ kind: z.literal("responseIf"),
511
+ expression: QtiExpressionSchema,
512
+ actions: z.array(QtiResponseRuleSchema).optional(),
513
+ }),
514
+ );
515
+
516
+ export const QtiResponseConditionSchema: z.ZodTypeAny = z.lazy(() =>
517
+ strictObject({
518
+ kind: z.literal("responseCondition"),
519
+ responseIf: QtiResponseIfSchema,
520
+ responseElseIf: z.array(QtiResponseIfSchema).optional(),
521
+ responseElse: QtiResponseElseSchema.optional(),
522
+ }),
523
+ );
524
+
525
+ export const QtiResponseProcessingFragmentSchema: z.ZodTypeAny = z.lazy(() =>
526
+ strictObject({
527
+ kind: z.literal("responseProcessingFragment"),
528
+ rules: z.array(QtiResponseRuleSchema).optional(),
529
+ }),
530
+ );
531
+
532
+ export const QtiResponseRuleSchema: z.ZodTypeAny = z.lazy(() =>
533
+ z.union([
534
+ QtiIncludeSchema,
535
+ QtiResponseConditionSchema,
536
+ QtiResponseProcessingFragmentSchema,
537
+ QtiSetOutcomeValueSchema,
538
+ QtiExitResponseSchema,
539
+ QtiLookupOutcomeValueSchema,
540
+ ]),
541
+ );
542
+
543
+ export const QtiResponseProcessingSchema = strictObject({
544
+ rules: z.array(QtiResponseRuleSchema).optional(),
545
+ template: z.string().optional(),
546
+ templateLocation: z.string().optional(),
547
+ });
548
+
549
+ export const QtiOutcomeElseSchema: z.ZodTypeAny = z.lazy(() =>
550
+ strictObject({
551
+ kind: z.literal("outcomeElse"),
552
+ actions: z.array(QtiOutcomeRuleSchema).optional(),
553
+ }),
554
+ );
555
+
556
+ export const QtiOutcomeIfSchema: z.ZodTypeAny = z.lazy(() =>
557
+ strictObject({
558
+ kind: z.literal("outcomeIf"),
559
+ expression: QtiExpressionSchema,
560
+ actions: z.array(QtiOutcomeRuleSchema).optional(),
561
+ }),
562
+ );
563
+
564
+ export const QtiOutcomeConditionSchema: z.ZodTypeAny = z.lazy(() =>
565
+ strictObject({
566
+ kind: z.literal("outcomeCondition"),
567
+ outcomeIf: QtiOutcomeIfSchema,
568
+ outcomeElseIf: z.array(QtiOutcomeIfSchema).optional(),
569
+ outcomeElse: QtiOutcomeElseSchema.optional(),
570
+ }),
571
+ );
572
+
573
+ export const QtiOutcomeProcessingFragmentSchema: z.ZodTypeAny = z.lazy(() =>
574
+ strictObject({
575
+ kind: z.literal("outcomeProcessingFragment"),
576
+ rules: z.array(QtiOutcomeRuleSchema).optional(),
577
+ }),
578
+ );
579
+
580
+ export const QtiOutcomeRuleSchema: z.ZodTypeAny = z.lazy(() =>
581
+ z.union([
582
+ QtiIncludeSchema,
583
+ QtiOutcomeConditionSchema,
584
+ QtiOutcomeProcessingFragmentSchema,
585
+ QtiSetOutcomeValueSchema,
586
+ QtiExitTestSchema,
587
+ QtiLookupOutcomeValueSchema,
588
+ ]),
589
+ );
590
+
591
+ export const QtiOutcomeProcessingSchema = strictObject({
592
+ rules: z.array(QtiOutcomeRuleSchema).optional(),
593
+ });
594
+
595
+ export const QtiTemplateElseSchema: z.ZodTypeAny = z.lazy(() =>
596
+ strictObject({
597
+ kind: z.literal("templateElse"),
598
+ actions: z.array(QtiTemplateRuleSchema).optional(),
599
+ }),
600
+ );
601
+
602
+ export const QtiTemplateIfSchema: z.ZodTypeAny = z.lazy(() =>
603
+ strictObject({
604
+ kind: z.literal("templateIf"),
605
+ expression: QtiExpressionSchema,
606
+ actions: z.array(QtiTemplateRuleSchema).optional(),
607
+ }),
608
+ );
609
+
610
+ export const QtiTemplateConditionSchema: z.ZodTypeAny = z.lazy(() =>
611
+ strictObject({
612
+ kind: z.literal("templateCondition"),
613
+ templateIf: QtiTemplateIfSchema,
614
+ templateElseIf: z.array(QtiTemplateIfSchema).optional(),
615
+ templateElse: QtiTemplateElseSchema.optional(),
616
+ }),
617
+ );
618
+
619
+ export const QtiTemplateRuleSchema: z.ZodTypeAny = z.lazy(() =>
620
+ z.union([
621
+ QtiTemplateConditionSchema,
622
+ QtiSetTemplateValueSchema,
623
+ QtiSetDefaultValueSchema,
624
+ QtiSetCorrectResponseSchema,
625
+ QtiTemplateConstraintSchema,
626
+ QtiExitTemplateSchema,
627
+ ]),
628
+ );
629
+
630
+ export const QtiTemplateProcessingSchema = strictObject({
631
+ rules: z.array(QtiTemplateRuleSchema).min(1),
632
+ });
633
+ // Inferred types from exported Zod validators.
634
+ export type QtiInclude = z.infer<typeof QtiIncludeSchema>;
635
+ export type QtiNullExpression = z.infer<typeof QtiNullExpressionSchema>;
636
+ export type QtiBaseValueExpression = z.infer<typeof QtiBaseValueExpressionSchema>;
637
+ export type QtiVariableExpression = z.infer<typeof QtiVariableExpressionSchema>;
638
+ export type QtiCorrectExpression = z.infer<typeof QtiCorrectExpressionSchema>;
639
+ export type QtiDefaultExpression = z.infer<typeof QtiDefaultExpressionSchema>;
640
+ export type QtiMapResponseExpression = z.infer<typeof QtiMapResponseExpressionSchema>;
641
+ export type QtiMapResponsePointExpression = z.infer<typeof QtiMapResponsePointExpressionSchema>;
642
+ export type QtiRandomIntegerExpression = z.infer<typeof QtiRandomIntegerExpressionSchema>;
643
+ export type QtiRandomFloatExpression = z.infer<typeof QtiRandomFloatExpressionSchema>;
644
+ export type QtiMathConstantExpression = z.infer<typeof QtiMathConstantExpressionSchema>;
645
+ export type QtiNumberCorrectExpression = z.infer<typeof QtiNumberCorrectExpressionSchema>;
646
+ export type QtiNumberIncorrectExpression = z.infer<typeof QtiNumberIncorrectExpressionSchema>;
647
+ export type QtiNumberPresentedExpression = z.infer<typeof QtiNumberPresentedExpressionSchema>;
648
+ export type QtiNumberRespondedExpression = z.infer<typeof QtiNumberRespondedExpressionSchema>;
649
+ export type QtiNumberSelectedExpression = z.infer<typeof QtiNumberSelectedExpressionSchema>;
650
+ export type QtiOutcomeMinimumExpression = z.infer<typeof QtiOutcomeMinimumExpressionSchema>;
651
+ export type QtiOutcomeMaximumExpression = z.infer<typeof QtiOutcomeMaximumExpressionSchema>;
652
+ export type QtiTestVariablesExpression = z.infer<typeof QtiTestVariablesExpressionSchema>;
653
+ export type QtiPreCondition = z.infer<typeof QtiPreConditionSchema>;
654
+ export type QtiBranchRule = z.infer<typeof QtiBranchRuleSchema>;
655
+ export type QtiLookupOutcomeValue = z.infer<typeof QtiLookupOutcomeValueSchema>;
656
+ export type QtiSetOutcomeValue = z.infer<typeof QtiSetOutcomeValueSchema>;
657
+ export type QtiSetTemplateValue = z.infer<typeof QtiSetTemplateValueSchema>;
658
+ export type QtiSetDefaultValue = z.infer<typeof QtiSetDefaultValueSchema>;
659
+ export type QtiSetCorrectResponse = z.infer<typeof QtiSetCorrectResponseSchema>;
660
+ export type QtiTemplateDefault = z.infer<typeof QtiTemplateDefaultSchema>;
661
+ export type QtiTemplateConstraint = z.infer<typeof QtiTemplateConstraintSchema>;
662
+ export type QtiExitResponse = z.infer<typeof QtiExitResponseSchema>;
663
+ export type QtiExitTemplate = z.infer<typeof QtiExitTemplateSchema>;
664
+ export type QtiExitTest = z.infer<typeof QtiExitTestSchema>;
665
+ export type QtiResponseProcessing = z.infer<typeof QtiResponseProcessingSchema>;
666
+ export type QtiOutcomeProcessing = z.infer<typeof QtiOutcomeProcessingSchema>;
667
+ export type QtiTemplateProcessing = z.infer<typeof QtiTemplateProcessingSchema>;