@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,206 @@
1
+ import { z } from "zod";
2
+
3
+ export const LocaleTagSchema = z.string().regex(/^[a-z]{2}(-[A-Z]{2})?$/u);
4
+ export const LocalizedStringMapSchema = z.record(LocaleTagSchema, z.string());
5
+ export const NonEmptyLocalizedStringMapSchema = z.record(LocaleTagSchema, z.string().min(1));
6
+ export const W3cCredentialsV2ContextSchema = z.literal("https://www.w3.org/ns/credentials/v2");
7
+ export const CompactJwsSchema = z.string().regex(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+$/u);
8
+
9
+ export type LocalizedStringMap = Record<string, string>;
10
+ export type TextValue = string | LocalizedStringMap;
11
+ export type UriValue = string | LocalizedStringMap;
12
+ export type CompactJwsValue = string | LocalizedStringMap;
13
+ export type JsonLdContextEntry = Record<string, unknown> | UriValue;
14
+ export type OneOrManyValue<T> = T | T[];
15
+
16
+ export const TextValueSchema = z.union([z.string(), LocalizedStringMapSchema]);
17
+ export const UriValueSchema = z.union([z.string().min(1), NonEmptyLocalizedStringMapSchema]);
18
+ export const CompactJwsValueSchema = z.union([CompactJwsSchema, z.record(LocaleTagSchema, CompactJwsSchema)]);
19
+ export const JsonLdContextEntrySchema = z.union([z.record(z.string(), z.unknown()), UriValueSchema]);
20
+
21
+ export function strictObject<T extends z.ZodRawShape>(shape: T) {
22
+ return z.object(shape).strict();
23
+ }
24
+
25
+ export function passthroughObject<T extends z.ZodRawShape>(shape: T) {
26
+ return z.object(shape).passthrough();
27
+ }
28
+
29
+ export function oneOrMany<T extends z.ZodTypeAny>(schema: T) {
30
+ return z.union([schema, z.array(schema).min(1)]);
31
+ }
32
+
33
+ export function addIssue(context: z.RefinementCtx, path: Array<string | number>, message: string) {
34
+ context.addIssue({
35
+ code: z.ZodIssueCode.custom,
36
+ path,
37
+ message,
38
+ });
39
+ }
40
+
41
+ function valueMatchesLiteral(value: unknown, expected: string) {
42
+ if (typeof value === "string") {
43
+ return value === expected;
44
+ }
45
+
46
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
47
+ return false;
48
+ }
49
+
50
+ return Object.values(value).some((entry) => entry === expected);
51
+ }
52
+
53
+ export function literalOrLocalizedLiteralSchema(expected: string) {
54
+ return z.union([z.literal(expected), z.record(LocaleTagSchema, z.literal(expected))]);
55
+ }
56
+
57
+ export function localizedEnumValueSchema<T extends readonly [string, ...string[]]>(values: T) {
58
+ const allowed = new Set(values);
59
+ const message = `Expected one of: ${values.join(", ")}`;
60
+
61
+ return z.union([
62
+ z.string().refine((value) => allowed.has(value), { message }),
63
+ z.record(
64
+ LocaleTagSchema,
65
+ z.string().refine((value) => allowed.has(value), {
66
+ message,
67
+ }),
68
+ ),
69
+ ]);
70
+ }
71
+
72
+ export function singleTypeSchema(expected: string) {
73
+ return z.union([
74
+ literalOrLocalizedLiteralSchema(expected),
75
+ z
76
+ .array(UriValueSchema)
77
+ .min(1)
78
+ .superRefine((values, context) => {
79
+ if (!values.some((value) => valueMatchesLiteral(value, expected))) {
80
+ addIssue(context, [], `Expected type array to include "${expected}"`);
81
+ }
82
+ }),
83
+ ]);
84
+ }
85
+
86
+ export function credentialTypeSchema<T extends readonly [string, ...string[]]>(domainTypes: T) {
87
+ return z
88
+ .array(UriValueSchema)
89
+ .min(2)
90
+ .superRefine((values, context) => {
91
+ if (!values.some((value) => valueMatchesLiteral(value, "VerifiableCredential"))) {
92
+ addIssue(context, [], 'Expected type array to include "VerifiableCredential"');
93
+ }
94
+
95
+ if (!domainTypes.some((domainType) => values.some((value) => valueMatchesLiteral(value, domainType)))) {
96
+ addIssue(context, [], `Expected type array to include one of: ${domainTypes.join(", ")}`);
97
+ }
98
+ });
99
+ }
100
+
101
+ export function contextArraySchema(label: string, requiredEntries: readonly z.ZodTypeAny[]) {
102
+ return z
103
+ .array(JsonLdContextEntrySchema)
104
+ .min(requiredEntries.length)
105
+ .superRefine((values, context) => {
106
+ requiredEntries.forEach((schema, index) => {
107
+ const result = schema.safeParse(values[index]);
108
+ if (!result.success) {
109
+ addIssue(context, [index], `${label} context entry ${index} does not match the expected shape`);
110
+ }
111
+ });
112
+ });
113
+ }
114
+
115
+ const VerifiableCredentialContextSchema = contextArraySchema("VC Data Model 2.0", [W3cCredentialsV2ContextSchema]);
116
+ const VerifiablePresentationContextSchema = contextArraySchema("VC Data Model 2.0", [W3cCredentialsV2ContextSchema]);
117
+
118
+ export const CredentialSchemaSchema = passthroughObject({
119
+ id: UriValueSchema,
120
+ type: TextValueSchema,
121
+ });
122
+
123
+ export const CredentialStatusSchema = passthroughObject({
124
+ id: UriValueSchema.optional(),
125
+ type: TextValueSchema,
126
+ });
127
+
128
+ export const RefreshServiceSchema = passthroughObject({
129
+ id: UriValueSchema,
130
+ type: TextValueSchema,
131
+ });
132
+
133
+ export const TermsOfUseSchema = passthroughObject({
134
+ id: UriValueSchema.optional(),
135
+ type: TextValueSchema,
136
+ });
137
+
138
+ export const ProofSchema = passthroughObject({
139
+ type: TextValueSchema,
140
+ created: z.iso.datetime().optional(),
141
+ cryptosuite: TextValueSchema.optional(),
142
+ challenge: TextValueSchema.optional(),
143
+ domain: TextValueSchema.optional(),
144
+ nonce: TextValueSchema.optional(),
145
+ proofPurpose: TextValueSchema.optional(),
146
+ proofValue: TextValueSchema.optional(),
147
+ verificationMethod: UriValueSchema.optional(),
148
+ });
149
+
150
+ export const EvidenceSchema = passthroughObject({
151
+ id: UriValueSchema.optional(),
152
+ type: TextValueSchema.optional(),
153
+ narrative: TextValueSchema.optional(),
154
+ name: TextValueSchema.optional(),
155
+ description: TextValueSchema.optional(),
156
+ });
157
+
158
+ export const CredentialSubjectSchema = passthroughObject({
159
+ id: UriValueSchema.optional(),
160
+ });
161
+
162
+ const GenericEntityReferenceSchema = z.union([UriValueSchema, z.record(z.string(), z.unknown())]);
163
+
164
+ export const VerifiableCredentialSchema = passthroughObject({
165
+ "@context": VerifiableCredentialContextSchema,
166
+ id: UriValueSchema.optional(),
167
+ type: singleTypeSchema("VerifiableCredential"),
168
+ issuer: GenericEntityReferenceSchema,
169
+ validFrom: z.iso.datetime(),
170
+ validUntil: z.iso.datetime().optional(),
171
+ credentialSubject: z.union([CredentialSubjectSchema, z.array(CredentialSubjectSchema).min(1)]),
172
+ name: TextValueSchema.optional(),
173
+ description: TextValueSchema.optional(),
174
+ proof: oneOrMany(ProofSchema).optional(),
175
+ credentialSchema: oneOrMany(CredentialSchemaSchema).optional(),
176
+ credentialStatus: oneOrMany(CredentialStatusSchema).optional(),
177
+ refreshService: oneOrMany(RefreshServiceSchema).optional(),
178
+ termsOfUse: oneOrMany(TermsOfUseSchema).optional(),
179
+ evidence: oneOrMany(EvidenceSchema).optional(),
180
+ });
181
+
182
+ export const HolderSchema = GenericEntityReferenceSchema;
183
+
184
+ export const VerifiablePresentationSchema = passthroughObject({
185
+ "@context": VerifiablePresentationContextSchema,
186
+ type: singleTypeSchema("VerifiablePresentation"),
187
+ id: UriValueSchema.optional(),
188
+ holder: HolderSchema.optional(),
189
+ verifiableCredential: oneOrMany(z.union([VerifiableCredentialSchema, CompactJwsValueSchema])).optional(),
190
+ proof: oneOrMany(ProofSchema).optional(),
191
+ });
192
+ // Inferred types from exported Zod validators.
193
+ export type LocaleTag = z.infer<typeof LocaleTagSchema>;
194
+ export type NonEmptyLocalizedStringMap = z.infer<typeof NonEmptyLocalizedStringMapSchema>;
195
+ export type W3cCredentialsV2Context = z.infer<typeof W3cCredentialsV2ContextSchema>;
196
+ export type CompactJws = z.infer<typeof CompactJwsSchema>;
197
+ export type CredentialSchema = z.infer<typeof CredentialSchemaSchema>;
198
+ export type CredentialStatus = z.infer<typeof CredentialStatusSchema>;
199
+ export type RefreshService = z.infer<typeof RefreshServiceSchema>;
200
+ export type TermsOfUse = z.infer<typeof TermsOfUseSchema>;
201
+ export type Proof = z.infer<typeof ProofSchema>;
202
+ export type Evidence = z.infer<typeof EvidenceSchema>;
203
+ export type CredentialSubject = z.infer<typeof CredentialSubjectSchema>;
204
+ export type VerifiableCredential = z.infer<typeof VerifiableCredentialSchema>;
205
+ export type Holder = z.infer<typeof HolderSchema>;
206
+ export type VerifiablePresentation = z.infer<typeof VerifiablePresentationSchema>;
@@ -0,0 +1,12 @@
1
+ export * from "./shared";
2
+
3
+ export * as V1_0_3 from "./v1_0_3";
4
+ export * as V2_0 from "./v2_0";
5
+
6
+ import { XapiV1_0_3DerivedZodTemplates } from "./v1_0_3";
7
+ import { XapiV2_0DerivedZodTemplates } from "./v2_0";
8
+
9
+ export const XapiDerivedZodTemplates = {
10
+ v1_0_3: XapiV1_0_3DerivedZodTemplates,
11
+ v2_0: XapiV2_0DerivedZodTemplates,
12
+ } as const;
@@ -0,0 +1,444 @@
1
+ import { z } from "zod";
2
+
3
+ export function strictObject<T extends z.ZodRawShape>(shape: T) {
4
+ return z.object(shape).strict();
5
+ }
6
+
7
+ const UriSchema = z.string().regex(/^[a-zA-Z][a-zA-Z0-9+.-]*:.+$/u);
8
+
9
+ export const NonEmptyStringSchema = z.string().min(1);
10
+ export const UuidSchema = z.string().uuid();
11
+ export const UriSchemaStrict = UriSchema;
12
+ export const IriSchema = UriSchema;
13
+ export const MediaTypeSchema = z.string().min(1);
14
+ export const LanguageTagSchema = z.string().regex(/^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8})*$/u);
15
+ export const XapiVersionSchema = z.string().regex(/^\d+\.\d+(?:\.\d+)?$/u);
16
+ export const Iso8601TimestampSchema = z.string().datetime();
17
+ export const Iso8601DurationSchema = z
18
+ .string()
19
+ .regex(/^P(?=.+)(?:\d+Y)?(?:\d+M)?(?:\d+W)?(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$/u);
20
+
21
+ export const LanguageMapSchema = z.record(LanguageTagSchema, z.string());
22
+ export const ExtensionsSchema = z.record(UriSchema, z.unknown());
23
+ export const AttachmentSha2Schema = z.string().regex(/^[A-Fa-f0-9]{64}$/u);
24
+
25
+ export const AgentAccountSchema = strictObject({
26
+ homePage: UriSchema,
27
+ name: NonEmptyStringSchema,
28
+ });
29
+
30
+ function hasDefined(value: unknown): boolean {
31
+ return value !== undefined && value !== null;
32
+ }
33
+
34
+ function hasNonEmptyArray(value: unknown): boolean {
35
+ return Array.isArray(value) && value.length > 0;
36
+ }
37
+
38
+ export const AgentSchema = strictObject({
39
+ objectType: z.literal("Agent").optional(),
40
+ name: NonEmptyStringSchema.optional(),
41
+ mbox: z
42
+ .string()
43
+ .regex(/^mailto:.+@.+$/u)
44
+ .optional(),
45
+ mbox_sha1sum: z
46
+ .string()
47
+ .regex(/^[A-Fa-f0-9]{40}$/u)
48
+ .optional(),
49
+ openid: UriSchema.optional(),
50
+ account: AgentAccountSchema.optional(),
51
+ }).refine(
52
+ (value) =>
53
+ hasDefined(value.mbox) || hasDefined(value.mbox_sha1sum) || hasDefined(value.openid) || hasDefined(value.account),
54
+ {
55
+ message: "An xAPI Agent requires at least one identifier",
56
+ },
57
+ );
58
+
59
+ export const GroupSchema = strictObject({
60
+ objectType: z.literal("Group").optional(),
61
+ name: NonEmptyStringSchema.optional(),
62
+ mbox: z
63
+ .string()
64
+ .regex(/^mailto:.+@.+$/u)
65
+ .optional(),
66
+ mbox_sha1sum: z
67
+ .string()
68
+ .regex(/^[A-Fa-f0-9]{40}$/u)
69
+ .optional(),
70
+ openid: UriSchema.optional(),
71
+ account: AgentAccountSchema.optional(),
72
+ member: z.array(AgentSchema).min(1).optional(),
73
+ }).refine(
74
+ (value) =>
75
+ hasDefined(value.mbox) ||
76
+ hasDefined(value.mbox_sha1sum) ||
77
+ hasDefined(value.openid) ||
78
+ hasDefined(value.account) ||
79
+ hasDefined(value.member),
80
+ {
81
+ message: "An xAPI Group requires an identifier or member list",
82
+ },
83
+ );
84
+
85
+ export const PersonSchema = strictObject({
86
+ objectType: z.literal("Person"),
87
+ name: z.array(NonEmptyStringSchema).min(1).optional(),
88
+ mbox: z
89
+ .array(z.string().regex(/^mailto:.+@.+$/u))
90
+ .min(1)
91
+ .optional(),
92
+ mbox_sha1sum: z
93
+ .array(z.string().regex(/^[A-Fa-f0-9]{40}$/u))
94
+ .min(1)
95
+ .optional(),
96
+ openid: z.array(UriSchema).min(1).optional(),
97
+ account: z.array(AgentAccountSchema).min(1).optional(),
98
+ }).refine(
99
+ (value) =>
100
+ hasNonEmptyArray(value.name) ||
101
+ hasNonEmptyArray(value.mbox) ||
102
+ hasNonEmptyArray(value.mbox_sha1sum) ||
103
+ hasNonEmptyArray(value.openid) ||
104
+ hasNonEmptyArray(value.account),
105
+ {
106
+ message: "An xAPI Person requires at least one populated identifier or name array",
107
+ },
108
+ );
109
+
110
+ export const VerbSchema = strictObject({
111
+ id: IriSchema,
112
+ display: LanguageMapSchema.optional(),
113
+ });
114
+
115
+ export const InteractionTypeSchema = z.enum([
116
+ "true-false",
117
+ "choice",
118
+ "fill-in",
119
+ "long-fill-in",
120
+ "matching",
121
+ "performance",
122
+ "sequencing",
123
+ "likert",
124
+ "numeric",
125
+ "other",
126
+ ]);
127
+
128
+ export const InteractionComponentSchema = strictObject({
129
+ id: NonEmptyStringSchema,
130
+ description: LanguageMapSchema.optional(),
131
+ });
132
+
133
+ export const ActivityDefinitionSchema = strictObject({
134
+ name: LanguageMapSchema.optional(),
135
+ description: LanguageMapSchema.optional(),
136
+ type: IriSchema.optional(),
137
+ moreInfo: IriSchema.optional(),
138
+ interactionType: InteractionTypeSchema.optional(),
139
+ correctResponsesPattern: z.array(NonEmptyStringSchema).min(1).optional(),
140
+ choices: z.array(InteractionComponentSchema).min(1).optional(),
141
+ scale: z.array(InteractionComponentSchema).min(1).optional(),
142
+ source: z.array(InteractionComponentSchema).min(1).optional(),
143
+ target: z.array(InteractionComponentSchema).min(1).optional(),
144
+ steps: z.array(InteractionComponentSchema).min(1).optional(),
145
+ extensions: ExtensionsSchema.optional(),
146
+ });
147
+
148
+ export const ActivitySchema = strictObject({
149
+ objectType: z.literal("Activity").optional(),
150
+ id: IriSchema,
151
+ definition: ActivityDefinitionSchema.optional(),
152
+ });
153
+
154
+ export const StatementRefSchema = strictObject({
155
+ objectType: z.literal("StatementRef"),
156
+ id: UuidSchema,
157
+ });
158
+
159
+ export const ScoreSchema = strictObject({
160
+ scaled: z.number().min(-1).max(1).optional(),
161
+ raw: z.number().optional(),
162
+ min: z.number().optional(),
163
+ max: z.number().optional(),
164
+ });
165
+
166
+ export const ResultSchema = strictObject({
167
+ score: ScoreSchema.optional(),
168
+ success: z.boolean().optional(),
169
+ completion: z.boolean().optional(),
170
+ response: z.string().optional(),
171
+ duration: Iso8601DurationSchema.optional(),
172
+ extensions: ExtensionsSchema.optional(),
173
+ });
174
+
175
+ export const ContextActivitiesSchema = strictObject({
176
+ parent: z.array(ActivitySchema).min(1).optional(),
177
+ category: z.array(ActivitySchema).min(1).optional(),
178
+ grouping: z.array(ActivitySchema).min(1).optional(),
179
+ other: z.array(ActivitySchema).min(1).optional(),
180
+ });
181
+
182
+ export const ContextSchema = strictObject({
183
+ registration: UuidSchema.optional(),
184
+ instructor: z.union([AgentSchema, GroupSchema]).optional(),
185
+ team: z.union([AgentSchema, GroupSchema]).optional(),
186
+ contextActivities: ContextActivitiesSchema.optional(),
187
+ revision: NonEmptyStringSchema.optional(),
188
+ platform: NonEmptyStringSchema.optional(),
189
+ language: LanguageTagSchema.optional(),
190
+ statement: StatementRefSchema.optional(),
191
+ extensions: ExtensionsSchema.optional(),
192
+ });
193
+
194
+ export const AttachmentSchema = strictObject({
195
+ usageType: IriSchema,
196
+ display: LanguageMapSchema,
197
+ description: LanguageMapSchema.optional(),
198
+ contentType: MediaTypeSchema,
199
+ length: z.number().int().nonnegative(),
200
+ sha2: AttachmentSha2Schema,
201
+ fileUrl: z.url().optional(),
202
+ });
203
+
204
+ export const XapiDocumentSchema = strictObject({
205
+ contentType: MediaTypeSchema,
206
+ body: z.unknown(),
207
+ etag: NonEmptyStringSchema.optional(),
208
+ lastModified: Iso8601TimestampSchema.optional(),
209
+ });
210
+
211
+ export const StatementSubmissionSchema = z.union([
212
+ z.lazy(() => StatementSchema),
213
+ z.array(z.lazy(() => StatementSchema)).min(1),
214
+ ]);
215
+
216
+ export const AboutResourceSchema = strictObject({
217
+ version: z.array(XapiVersionSchema).min(1),
218
+ extensions: ExtensionsSchema.optional(),
219
+ });
220
+
221
+ export const StatementsQueryFormatSchema = z.enum(["ids", "exact", "canonical"]);
222
+
223
+ export const StatementsQuerySchema = strictObject({
224
+ statementId: UuidSchema.optional(),
225
+ voidedStatementId: UuidSchema.optional(),
226
+ agent: AgentSchema.optional(),
227
+ verb: IriSchema.optional(),
228
+ activity: IriSchema.optional(),
229
+ registration: UuidSchema.optional(),
230
+ related_activities: z.boolean().optional(),
231
+ related_agents: z.boolean().optional(),
232
+ since: Iso8601TimestampSchema.optional(),
233
+ until: Iso8601TimestampSchema.optional(),
234
+ limit: z.number().int().positive().optional(),
235
+ format: StatementsQueryFormatSchema.optional(),
236
+ attachments: z.boolean().optional(),
237
+ ascending: z.boolean().optional(),
238
+ }).refine((value) => !(hasDefined(value.statementId) && hasDefined(value.voidedStatementId)), {
239
+ message: "Statements queries cannot specify both statementId and voidedStatementId",
240
+ });
241
+
242
+ export const AgentsResourceQuerySchema = strictObject({
243
+ agent: AgentSchema,
244
+ });
245
+
246
+ export const ActivitiesResourceQuerySchema = strictObject({
247
+ activityId: IriSchema,
248
+ });
249
+
250
+ export const StateDocumentQuerySchema = strictObject({
251
+ activityId: IriSchema,
252
+ agent: AgentSchema,
253
+ registration: UuidSchema.optional(),
254
+ stateId: NonEmptyStringSchema.optional(),
255
+ });
256
+
257
+ export const StateDocumentListingQuerySchema = strictObject({
258
+ activityId: IriSchema,
259
+ agent: AgentSchema,
260
+ registration: UuidSchema.optional(),
261
+ since: Iso8601TimestampSchema.optional(),
262
+ });
263
+
264
+ export const AgentProfileDocumentQuerySchema = strictObject({
265
+ agent: AgentSchema,
266
+ profileId: NonEmptyStringSchema.optional(),
267
+ });
268
+
269
+ export const AgentProfileDocumentListingQuerySchema = strictObject({
270
+ agent: AgentSchema,
271
+ since: Iso8601TimestampSchema.optional(),
272
+ });
273
+
274
+ export const ActivityProfileDocumentQuerySchema = strictObject({
275
+ activityId: IriSchema,
276
+ profileId: NonEmptyStringSchema.optional(),
277
+ });
278
+
279
+ export const ActivityProfileDocumentListingQuerySchema = strictObject({
280
+ activityId: IriSchema,
281
+ since: Iso8601TimestampSchema.optional(),
282
+ });
283
+
284
+ export const XapiDocumentIdListSchema = z.array(NonEmptyStringSchema);
285
+
286
+ export const SubStatementSchema = strictObject({
287
+ objectType: z.literal("SubStatement"),
288
+ actor: z.union([AgentSchema, GroupSchema]),
289
+ verb: VerbSchema,
290
+ object: z.union([ActivitySchema, AgentSchema, GroupSchema, StatementRefSchema]),
291
+ result: ResultSchema.optional(),
292
+ context: ContextSchema.optional(),
293
+ timestamp: Iso8601TimestampSchema.optional(),
294
+ });
295
+
296
+ export const StatementObjectSchema = z.union([
297
+ ActivitySchema,
298
+ AgentSchema,
299
+ GroupSchema,
300
+ StatementRefSchema,
301
+ SubStatementSchema,
302
+ ]);
303
+
304
+ export const StatementSchema = strictObject({
305
+ id: UuidSchema.optional(),
306
+ actor: z.union([AgentSchema, GroupSchema]),
307
+ verb: VerbSchema,
308
+ object: StatementObjectSchema,
309
+ result: ResultSchema.optional(),
310
+ context: ContextSchema.optional(),
311
+ timestamp: Iso8601TimestampSchema.optional(),
312
+ stored: Iso8601TimestampSchema.optional(),
313
+ authority: z.union([AgentSchema, GroupSchema]).optional(),
314
+ version: XapiVersionSchema.optional(),
315
+ attachments: z.array(AttachmentSchema).min(1).optional(),
316
+ });
317
+
318
+ export const StatementResultMoreSchema = z.string().regex(/^$|^(?![A-Za-z][A-Za-z0-9+.-]*:)\S+$/u);
319
+
320
+ export const StatementResultSchema = strictObject({
321
+ statements: z.array(StatementSchema),
322
+ more: StatementResultMoreSchema.optional(),
323
+ });
324
+
325
+ export const XapiHttpMethodSchema = z.enum(["GET", "HEAD", "PUT", "POST", "DELETE"]);
326
+
327
+ export const XapiResourceSchema = strictObject({
328
+ name: NonEmptyStringSchema,
329
+ description: NonEmptyStringSchema,
330
+ methods: z.array(XapiHttpMethodSchema).min(1),
331
+ });
332
+
333
+ export const XapiRequestHeaderSchema = z.enum([
334
+ "Accept",
335
+ "Accept-Encoding",
336
+ "Accept-Language",
337
+ "Authorization",
338
+ "Content-Type",
339
+ "Content-Length",
340
+ "Content-Transfer-Encoding",
341
+ "If-Match",
342
+ "If-None-Match",
343
+ "X-Experience-API-Hash",
344
+ "X-Experience-API-Version",
345
+ ]);
346
+
347
+ export const XapiResponseHeaderSchema = z.enum([
348
+ "Content-Type",
349
+ "Content-Length",
350
+ "Last-Modified",
351
+ "ETag",
352
+ "Status",
353
+ "X-Experience-API-Version",
354
+ "X-Experience-API-Consistent-Through",
355
+ ]);
356
+
357
+ export const XapiErrorCodeSchema = z.enum(["400", "401", "403", "404", "409", "411", "412", "413", "500", "501"]);
358
+
359
+ export const XapiErrorResponseSchema = strictObject({
360
+ code: XapiErrorCodeSchema,
361
+ message: NonEmptyStringSchema,
362
+ details: NonEmptyStringSchema.optional(),
363
+ });
364
+
365
+ export const XapiConcurrencySchema = strictObject({
366
+ etag: NonEmptyStringSchema.optional(),
367
+ ifMatch: NonEmptyStringSchema.optional(),
368
+ ifNoneMatch: NonEmptyStringSchema.optional(),
369
+ });
370
+
371
+ export const XapiMultipartAttachmentPartSchema = strictObject({
372
+ headers: strictObject({
373
+ "Content-Type": MediaTypeSchema,
374
+ "Content-Transfer-Encoding": z.literal("binary"),
375
+ "X-Experience-API-Hash": AttachmentSha2Schema,
376
+ }),
377
+ body: z.unknown(),
378
+ });
379
+
380
+ export const XapiMultipartRequestSchema = strictObject({
381
+ contentType: z.literal("multipart/mixed"),
382
+ parts: z.tuple([
383
+ strictObject({
384
+ contentType: z.literal("application/json"),
385
+ body: z.union([StatementSchema, z.array(StatementSchema).min(1)]),
386
+ }),
387
+ z.array(XapiMultipartAttachmentPartSchema).min(1),
388
+ ]),
389
+ });
390
+ // Inferred types from exported Zod validators.
391
+ export type NonEmptyString = z.infer<typeof NonEmptyStringSchema>;
392
+ export type Uuid = z.infer<typeof UuidSchema>;
393
+ export type Iri = z.infer<typeof IriSchema>;
394
+ export type MediaType = z.infer<typeof MediaTypeSchema>;
395
+ export type LanguageTag = z.infer<typeof LanguageTagSchema>;
396
+ export type XapiVersion = z.infer<typeof XapiVersionSchema>;
397
+ export type Iso8601Timestamp = z.infer<typeof Iso8601TimestampSchema>;
398
+ export type Iso8601Duration = z.infer<typeof Iso8601DurationSchema>;
399
+ export type LanguageMap = z.infer<typeof LanguageMapSchema>;
400
+ export type Extensions = z.infer<typeof ExtensionsSchema>;
401
+ export type AttachmentSha2 = z.infer<typeof AttachmentSha2Schema>;
402
+ export type AgentAccount = z.infer<typeof AgentAccountSchema>;
403
+ export type Agent = z.infer<typeof AgentSchema>;
404
+ export type Group = z.infer<typeof GroupSchema>;
405
+ export type Person = z.infer<typeof PersonSchema>;
406
+ export type Verb = z.infer<typeof VerbSchema>;
407
+ export type InteractionType = z.infer<typeof InteractionTypeSchema>;
408
+ export type InteractionComponent = z.infer<typeof InteractionComponentSchema>;
409
+ export type ActivityDefinition = z.infer<typeof ActivityDefinitionSchema>;
410
+ export type Activity = z.infer<typeof ActivitySchema>;
411
+ export type StatementRef = z.infer<typeof StatementRefSchema>;
412
+ export type Score = z.infer<typeof ScoreSchema>;
413
+ export type Result = z.infer<typeof ResultSchema>;
414
+ export type ContextActivities = z.infer<typeof ContextActivitiesSchema>;
415
+ export type Context = z.infer<typeof ContextSchema>;
416
+ export type Attachment = z.infer<typeof AttachmentSchema>;
417
+ export type XapiDocument = z.infer<typeof XapiDocumentSchema>;
418
+ export type StatementSubmission = z.infer<typeof StatementSubmissionSchema>;
419
+ export type AboutResource = z.infer<typeof AboutResourceSchema>;
420
+ export type StatementsQueryFormat = z.infer<typeof StatementsQueryFormatSchema>;
421
+ export type StatementsQuery = z.infer<typeof StatementsQuerySchema>;
422
+ export type AgentsResourceQuery = z.infer<typeof AgentsResourceQuerySchema>;
423
+ export type ActivitiesResourceQuery = z.infer<typeof ActivitiesResourceQuerySchema>;
424
+ export type StateDocumentQuery = z.infer<typeof StateDocumentQuerySchema>;
425
+ export type StateDocumentListingQuery = z.infer<typeof StateDocumentListingQuerySchema>;
426
+ export type AgentProfileDocumentQuery = z.infer<typeof AgentProfileDocumentQuerySchema>;
427
+ export type AgentProfileDocumentListingQuery = z.infer<typeof AgentProfileDocumentListingQuerySchema>;
428
+ export type ActivityProfileDocumentQuery = z.infer<typeof ActivityProfileDocumentQuerySchema>;
429
+ export type ActivityProfileDocumentListingQuery = z.infer<typeof ActivityProfileDocumentListingQuerySchema>;
430
+ export type XapiDocumentIdList = z.infer<typeof XapiDocumentIdListSchema>;
431
+ export type SubStatement = z.infer<typeof SubStatementSchema>;
432
+ export type StatementObject = z.infer<typeof StatementObjectSchema>;
433
+ export type Statement = z.infer<typeof StatementSchema>;
434
+ export type StatementResultMore = z.infer<typeof StatementResultMoreSchema>;
435
+ export type StatementResult = z.infer<typeof StatementResultSchema>;
436
+ export type XapiHttpMethod = z.infer<typeof XapiHttpMethodSchema>;
437
+ export type XapiResource = z.infer<typeof XapiResourceSchema>;
438
+ export type XapiRequestHeader = z.infer<typeof XapiRequestHeaderSchema>;
439
+ export type XapiResponseHeader = z.infer<typeof XapiResponseHeaderSchema>;
440
+ export type XapiErrorCode = z.infer<typeof XapiErrorCodeSchema>;
441
+ export type XapiErrorResponse = z.infer<typeof XapiErrorResponseSchema>;
442
+ export type XapiConcurrency = z.infer<typeof XapiConcurrencySchema>;
443
+ export type XapiMultipartAttachmentPart = z.infer<typeof XapiMultipartAttachmentPartSchema>;
444
+ export type XapiMultipartRequest = z.infer<typeof XapiMultipartRequestSchema>;