@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,41 @@
1
+ export { XmlExtensionNodeListSchema, XmlExtensionNodeSchema } from "./shared";
2
+
3
+ export * from "./ccv1p3_imscsmd_v1p0";
4
+ export * from "./ccv1p3_imsdt_v1p3";
5
+ export * from "./ccv1p3_imswl_v1p3";
6
+ export * from "./ccv1p3_lommanifest_v1p0";
7
+ export * from "./ccv1p3_lomresource_v1p0";
8
+ export * from "./ccv1p3_lomccltilink_v1p0";
9
+ export * from "./ccv1p3_imsccauth_v1p3";
10
+ export * from "./ccv1p3_imscp_v1p2_v1p0";
11
+ export * from "./ccv1p3_qtiasiv1p2p1_v1p0";
12
+
13
+ import { CurriculumStandardsMetadataSetDocumentSchema } from "./ccv1p3_imscsmd_v1p0";
14
+ import { DiscussionTopicDocumentSchema } from "./ccv1p3_imsdt_v1p3";
15
+ import { WebLinkDocumentSchema } from "./ccv1p3_imswl_v1p3";
16
+ import { CommonCartridgeAuthorizationsDocumentSchema } from "./ccv1p3_imsccauth_v1p3";
17
+ import {
18
+ CommonCartridgeManifestProfileDocumentSchema,
19
+ CommonCartridgeManifestRawDocumentSchema,
20
+ } from "./ccv1p3_imscp_v1p2_v1p0";
21
+ import { LomCcLtiLinkDocumentSchema } from "./ccv1p3_lomccltilink_v1p0";
22
+ import { LomManifestDocumentSchema } from "./ccv1p3_lommanifest_v1p0";
23
+ import { LomResourceDocumentSchema } from "./ccv1p3_lomresource_v1p0";
24
+ import {
25
+ QtiQuestestinteropProfileDocumentSchema,
26
+ QtiQuestestinteropRawDocumentSchema,
27
+ } from "./ccv1p3_qtiasiv1p2p1_v1p0";
28
+
29
+ export const CommonCartridgeDerivedZodTemplates = {
30
+ curriculumStandardsMetadataSetDocument: CurriculumStandardsMetadataSetDocumentSchema,
31
+ discussionTopicDocument: DiscussionTopicDocumentSchema,
32
+ webLinkDocument: WebLinkDocumentSchema,
33
+ lomManifestDocument: LomManifestDocumentSchema,
34
+ lomResourceDocument: LomResourceDocumentSchema,
35
+ lomCcLtiLinkDocument: LomCcLtiLinkDocumentSchema,
36
+ commonCartridgeAuthorizationsDocument: CommonCartridgeAuthorizationsDocumentSchema,
37
+ commonCartridgeManifestRawDocument: CommonCartridgeManifestRawDocumentSchema,
38
+ commonCartridgeManifestProfileDocument: CommonCartridgeManifestProfileDocumentSchema,
39
+ qtiQuestestinteropRawDocument: QtiQuestestinteropRawDocumentSchema,
40
+ qtiQuestestinteropProfileDocument: QtiQuestestinteropProfileDocumentSchema,
41
+ } as const;
@@ -0,0 +1,396 @@
1
+ import { z } from "zod";
2
+
3
+ import { LowerYesNoSchema, addIssue, looseObject, strictObject } from "./shared";
4
+
5
+ const LomAggregationLevelValueSchema = z.enum(["1", "2", "3", "4"]);
6
+ const LomContextValueSchema = z.enum(["school", "higher education", "training", "other"]);
7
+ const LomDifficultyValueSchema = z.enum(["very easy", "easy", "medium", "difficult", "very difficult"]);
8
+ const LomInteractivityLevelValueSchema = z.enum(["very low", "low", "medium", "high", "very high"]);
9
+ const LomInteractivityTypeValueSchema = z.enum(["active", "expositive", "mixed"]);
10
+ const LomKindValueSchema = z.enum([
11
+ "ispartof",
12
+ "haspart",
13
+ "isversionof",
14
+ "hasversion",
15
+ "isformatof",
16
+ "hasformat",
17
+ "references",
18
+ "isreferencedby",
19
+ "isbasedon",
20
+ "isbasisfor",
21
+ "requires",
22
+ "isrequiredby",
23
+ ]);
24
+ const LomLearningResourceTypeValueSchema = z.enum([
25
+ "exercise",
26
+ "simulation",
27
+ "questionnaire",
28
+ "diagram",
29
+ "figure",
30
+ "graph",
31
+ "index",
32
+ "slide",
33
+ "table",
34
+ "narrative text",
35
+ "exam",
36
+ "experiment",
37
+ "problem statement",
38
+ "self assessment",
39
+ "lecture",
40
+ ]);
41
+ const LomNameValueSchema = z.enum([
42
+ "pc-dos",
43
+ "ms-windows",
44
+ "macos",
45
+ "unix",
46
+ "multi-os",
47
+ "none",
48
+ "any",
49
+ "netscape communicator",
50
+ "ms-internet explorer",
51
+ "opera",
52
+ "amaya",
53
+ ]);
54
+ const LomPurposeValueSchema = z.enum([
55
+ "discipline",
56
+ "idea",
57
+ "prerequisite",
58
+ "educational objective",
59
+ "accessibility restrictions",
60
+ "educational level",
61
+ "skill level",
62
+ "security level",
63
+ "competency",
64
+ ]);
65
+ const LomRoleLifeCycleValueSchema = z.enum([
66
+ "author",
67
+ "publisher",
68
+ "unknown",
69
+ "initiator",
70
+ "terminator",
71
+ "validator",
72
+ "editor",
73
+ "graphical designer",
74
+ "technical implementer",
75
+ "content provider",
76
+ "technical validator",
77
+ "educational validator",
78
+ "script writer",
79
+ "instructional designer",
80
+ "subject matter expert",
81
+ ]);
82
+ const LomRoleMetaMetadataValueSchema = z.enum(["creator", "validator"]);
83
+ const LomSemanticDensityValueSchema = z.enum(["very low", "low", "medium", "high", "very high"]);
84
+ const LomStatusValueSchema = z.enum(["draft", "final", "revised", "unavailable"]);
85
+ const LomStructureValueSchema = z.enum(["atomic", "collection", "networked", "hierarchical", "linear"]);
86
+ const LomTypeValueSchema = z.enum(["operating system", "browser"]);
87
+
88
+ type LomVocabularySchemaConfig = {
89
+ aggregationLevel: z.ZodTypeAny;
90
+ context: z.ZodTypeAny;
91
+ copyrightAndOtherRestrictions: z.ZodTypeAny;
92
+ cost: z.ZodTypeAny;
93
+ difficulty: z.ZodTypeAny;
94
+ intendedEndUserRole: z.ZodTypeAny;
95
+ interactivityLevel: z.ZodTypeAny;
96
+ interactivityType: z.ZodTypeAny;
97
+ kind: z.ZodTypeAny;
98
+ learningResourceType: z.ZodTypeAny;
99
+ name: z.ZodTypeAny;
100
+ purpose: z.ZodTypeAny;
101
+ roleLifeCycle: z.ZodTypeAny;
102
+ roleMetaMetadata: z.ZodTypeAny;
103
+ semanticDensity: z.ZodTypeAny;
104
+ status: z.ZodTypeAny;
105
+ structure: z.ZodTypeAny;
106
+ type: z.ZodTypeAny;
107
+ };
108
+
109
+ function createLomProfileSchemas(config: { allowExtensions: boolean; values: LomVocabularySchemaConfig }) {
110
+ const object = config.allowExtensions ? looseObject : strictObject;
111
+
112
+ const LanguageStringSchema = object({
113
+ value: z.string(),
114
+ language: z.string().optional(),
115
+ });
116
+
117
+ const LangStringSchema = object({
118
+ string: z.array(LanguageStringSchema),
119
+ });
120
+
121
+ const vocabulary = (valueSchema: z.ZodTypeAny) =>
122
+ object({
123
+ source: z.string().optional(),
124
+ value: valueSchema.optional(),
125
+ });
126
+
127
+ const AggregationLevelSchema = vocabulary(config.values.aggregationLevel);
128
+ const ContextSchema = vocabulary(config.values.context);
129
+ const CopyrightAndOtherRestrictionsSchema = vocabulary(config.values.copyrightAndOtherRestrictions);
130
+ const CostSchema = vocabulary(config.values.cost);
131
+ const DifficultySchema = vocabulary(config.values.difficulty);
132
+ const IntendedEndUserRoleSchema = vocabulary(config.values.intendedEndUserRole);
133
+ const InteractivityLevelSchema = vocabulary(config.values.interactivityLevel);
134
+ const InteractivityTypeSchema = vocabulary(config.values.interactivityType);
135
+ const KindSchema = vocabulary(config.values.kind);
136
+ const LearningResourceTypeSchema = vocabulary(config.values.learningResourceType);
137
+ const NameSchema = vocabulary(config.values.name);
138
+ const PurposeSchema = vocabulary(config.values.purpose);
139
+ const RoleLifeCycleSchema = vocabulary(config.values.roleLifeCycle);
140
+ const RoleMetaMetadataSchema = vocabulary(config.values.roleMetaMetadata);
141
+ const SemanticDensitySchema = vocabulary(config.values.semanticDensity);
142
+ const StatusSchema = vocabulary(config.values.status);
143
+ const StructureSchema = vocabulary(config.values.structure);
144
+ const TypeSchema = vocabulary(config.values.type);
145
+
146
+ const IdentifierSchema = object({
147
+ catalog: z.string().optional(),
148
+ entry: z.string().optional(),
149
+ });
150
+
151
+ const DateTimeSchema = object({
152
+ dateTime: z.string().optional(),
153
+ description: LangStringSchema.optional(),
154
+ });
155
+
156
+ const ContributeLifeCycleSchema = object({
157
+ role: RoleLifeCycleSchema.optional(),
158
+ entity: z.array(z.string()).optional(),
159
+ date: DateTimeSchema.optional(),
160
+ });
161
+
162
+ const ContributeMetaMetadataSchema = object({
163
+ role: RoleMetaMetadataSchema.optional(),
164
+ entity: z.array(z.string()).optional(),
165
+ date: DateTimeSchema.optional(),
166
+ });
167
+
168
+ const DurationSchema = object({
169
+ duration: z.string().optional(),
170
+ description: LangStringSchema.optional(),
171
+ });
172
+
173
+ const ResourceSchema = object({
174
+ identifier: z.array(IdentifierSchema).optional(),
175
+ description: z.array(LangStringSchema).optional(),
176
+ });
177
+
178
+ const RelationSchema = object({
179
+ kind: KindSchema.optional(),
180
+ resource: ResourceSchema.optional(),
181
+ });
182
+
183
+ const OrCompositeSchema = object({
184
+ type: TypeSchema.optional(),
185
+ name: NameSchema.optional(),
186
+ minimumVersion: z.string().optional(),
187
+ maximumVersion: z.string().optional(),
188
+ });
189
+
190
+ const RequirementSchema = object({
191
+ orComposite: z.array(OrCompositeSchema).optional(),
192
+ });
193
+
194
+ const TechnicalSchema = object({
195
+ format: z.array(z.string()).optional(),
196
+ size: z.string().optional(),
197
+ location: z.array(z.string()).optional(),
198
+ requirement: z.array(RequirementSchema).optional(),
199
+ installationRemarks: LangStringSchema.optional(),
200
+ otherPlatformRequirements: LangStringSchema.optional(),
201
+ duration: DurationSchema.optional(),
202
+ });
203
+
204
+ const AnnotationSchema = object({
205
+ entity: z.string().optional(),
206
+ date: DateTimeSchema.optional(),
207
+ description: LangStringSchema.optional(),
208
+ });
209
+
210
+ const TaxonSchema = object({
211
+ id: z.string().optional(),
212
+ entry: LangStringSchema.optional(),
213
+ });
214
+
215
+ const TaxonPathSchema = object({
216
+ source: LangStringSchema.optional(),
217
+ taxon: z.array(TaxonSchema).optional(),
218
+ });
219
+
220
+ const ClassificationSchema = object({
221
+ purpose: PurposeSchema.optional(),
222
+ taxonPath: z.array(TaxonPathSchema).optional(),
223
+ description: LangStringSchema.optional(),
224
+ keyword: z.array(LangStringSchema).optional(),
225
+ });
226
+
227
+ const EducationalSchema = object({
228
+ interactivityType: InteractivityTypeSchema.optional(),
229
+ learningResourceType: z.array(LearningResourceTypeSchema).optional(),
230
+ interactivityLevel: InteractivityLevelSchema.optional(),
231
+ semanticDensity: SemanticDensitySchema.optional(),
232
+ intendedEndUserRole: z.array(IntendedEndUserRoleSchema).optional(),
233
+ context: z.array(ContextSchema).optional(),
234
+ typicalAgeRange: z.array(LangStringSchema).optional(),
235
+ difficulty: DifficultySchema.optional(),
236
+ typicalLearningTime: DurationSchema.optional(),
237
+ description: LangStringSchema.optional(),
238
+ language: z.array(z.string()).optional(),
239
+ });
240
+
241
+ const GeneralSchema = object({
242
+ identifier: z.array(IdentifierSchema).optional(),
243
+ title: LangStringSchema.optional(),
244
+ language: z.array(z.string()).optional(),
245
+ description: z.array(LangStringSchema).optional(),
246
+ keyword: z.array(LangStringSchema).optional(),
247
+ coverage: z.array(LangStringSchema).optional(),
248
+ structure: StructureSchema.optional(),
249
+ aggregationLevel: AggregationLevelSchema.optional(),
250
+ });
251
+
252
+ const LifeCycleSchema = object({
253
+ version: LangStringSchema.optional(),
254
+ status: StatusSchema.optional(),
255
+ contribute: z.array(ContributeLifeCycleSchema).optional(),
256
+ });
257
+
258
+ const MetaMetadataSchema = object({
259
+ identifier: z.array(IdentifierSchema).optional(),
260
+ contribute: z.array(ContributeMetaMetadataSchema).optional(),
261
+ metadataschema: z.array(z.string()).optional(),
262
+ language: z.string().optional(),
263
+ });
264
+
265
+ const RightsSchema = object({
266
+ cost: CostSchema.optional(),
267
+ copyrightAndOtherRestrictions: CopyrightAndOtherRestrictionsSchema.optional(),
268
+ description: LangStringSchema.optional(),
269
+ });
270
+
271
+ const LomSchema = object({
272
+ general: GeneralSchema.optional(),
273
+ lifeCycle: LifeCycleSchema.optional(),
274
+ metaMetadata: MetaMetadataSchema.optional(),
275
+ technical: TechnicalSchema.optional(),
276
+ educational: z.array(EducationalSchema).optional(),
277
+ rights: RightsSchema.optional(),
278
+ relation: z.array(RelationSchema).optional(),
279
+ annotation: z.array(AnnotationSchema).optional(),
280
+ classification: z.array(ClassificationSchema).optional(),
281
+ }).superRefine((lom, context) => {
282
+ const singletonChecks: Array<{ key: keyof typeof lom; label: string }> = [
283
+ { key: "general", label: "general" },
284
+ { key: "lifeCycle", label: "lifeCycle" },
285
+ { key: "metaMetadata", label: "metaMetadata" },
286
+ { key: "technical", label: "technical" },
287
+ { key: "rights", label: "rights" },
288
+ ];
289
+
290
+ for (const check of singletonChecks) {
291
+ const value = lom[check.key];
292
+ if (Array.isArray(value) && value.length > 1) {
293
+ addIssue(
294
+ context,
295
+ [check.key],
296
+ `LOM Schematron treats ${check.label} as 0..1 even though the XSD uses unordered repeated choices.`,
297
+ );
298
+ }
299
+ }
300
+ });
301
+
302
+ return {
303
+ LanguageStringSchema,
304
+ LangStringSchema,
305
+ AggregationLevelSchema,
306
+ ContextSchema,
307
+ CopyrightAndOtherRestrictionsSchema,
308
+ CostSchema,
309
+ DifficultySchema,
310
+ IntendedEndUserRoleSchema,
311
+ InteractivityLevelSchema,
312
+ InteractivityTypeSchema,
313
+ KindSchema,
314
+ LearningResourceTypeSchema,
315
+ NameSchema,
316
+ PurposeSchema,
317
+ RoleLifeCycleSchema,
318
+ RoleMetaMetadataSchema,
319
+ SemanticDensitySchema,
320
+ StatusSchema,
321
+ StructureSchema,
322
+ TypeSchema,
323
+ IdentifierSchema,
324
+ DateTimeSchema,
325
+ ContributeLifeCycleSchema,
326
+ ContributeMetaMetadataSchema,
327
+ DurationSchema,
328
+ ResourceSchema,
329
+ RelationSchema,
330
+ OrCompositeSchema,
331
+ RequirementSchema,
332
+ TechnicalSchema,
333
+ AnnotationSchema,
334
+ TaxonSchema,
335
+ TaxonPathSchema,
336
+ ClassificationSchema,
337
+ EducationalSchema,
338
+ GeneralSchema,
339
+ LifeCycleSchema,
340
+ MetaMetadataSchema,
341
+ RightsSchema,
342
+ LomSchema,
343
+ };
344
+ }
345
+
346
+ const looseLomValueSchema = z.string();
347
+
348
+ export const LomManifestProfileSchemas = createLomProfileSchemas({
349
+ allowExtensions: true,
350
+ values: {
351
+ aggregationLevel: looseLomValueSchema,
352
+ context: looseLomValueSchema,
353
+ copyrightAndOtherRestrictions: looseLomValueSchema,
354
+ cost: looseLomValueSchema,
355
+ difficulty: looseLomValueSchema,
356
+ intendedEndUserRole: looseLomValueSchema,
357
+ interactivityLevel: looseLomValueSchema,
358
+ interactivityType: looseLomValueSchema,
359
+ kind: looseLomValueSchema,
360
+ learningResourceType: looseLomValueSchema,
361
+ name: looseLomValueSchema,
362
+ purpose: looseLomValueSchema,
363
+ roleLifeCycle: looseLomValueSchema,
364
+ roleMetaMetadata: looseLomValueSchema,
365
+ semanticDensity: looseLomValueSchema,
366
+ status: looseLomValueSchema,
367
+ structure: looseLomValueSchema,
368
+ type: looseLomValueSchema,
369
+ },
370
+ });
371
+
372
+ export const LomResourceProfileSchemas = LomManifestProfileSchemas;
373
+
374
+ export const LomCcLtiLinkProfileSchemas = createLomProfileSchemas({
375
+ allowExtensions: false,
376
+ values: {
377
+ aggregationLevel: LomAggregationLevelValueSchema,
378
+ context: LomContextValueSchema,
379
+ copyrightAndOtherRestrictions: LowerYesNoSchema,
380
+ cost: LowerYesNoSchema,
381
+ difficulty: LomDifficultyValueSchema,
382
+ intendedEndUserRole: z.enum(["teacher", "author", "learner", "manager"]),
383
+ interactivityLevel: LomInteractivityLevelValueSchema,
384
+ interactivityType: LomInteractivityTypeValueSchema,
385
+ kind: LomKindValueSchema,
386
+ learningResourceType: LomLearningResourceTypeValueSchema,
387
+ name: LomNameValueSchema,
388
+ purpose: LomPurposeValueSchema,
389
+ roleLifeCycle: LomRoleLifeCycleValueSchema,
390
+ roleMetaMetadata: LomRoleMetaMetadataValueSchema,
391
+ semanticDensity: LomSemanticDensityValueSchema,
392
+ status: LomStatusValueSchema,
393
+ structure: LomStructureValueSchema,
394
+ type: LomTypeValueSchema,
395
+ },
396
+ });
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+
3
+ export const NonEmptyStringSchema = z.string().min(1);
4
+ export const UriReferenceSchema = z.string().min(1);
5
+ export const YesNoSchema = z.enum(["Yes", "No"]);
6
+ export const LowerYesNoSchema = z.enum(["yes", "no"]);
7
+ export const XmlSpaceSchema = z.enum(["default", "preserve"]);
8
+ export const XmlForeignAttributesSchema = z.record(z.string(), z.unknown());
9
+
10
+ export const XmlExtensionNodeSchema = z
11
+ .object({
12
+ namespace: NonEmptyStringSchema,
13
+ name: NonEmptyStringSchema,
14
+ value: z.unknown().optional(),
15
+ attributes: XmlForeignAttributesSchema.optional(),
16
+ children: z.array(z.unknown()).optional(),
17
+ })
18
+ .strict();
19
+
20
+ export const XmlExtensionNodeListSchema = z.array(XmlExtensionNodeSchema);
21
+
22
+ export function strictObject<T extends z.ZodRawShape>(shape: T) {
23
+ return z.object(shape).strict();
24
+ }
25
+
26
+ export function looseObject<T extends z.ZodRawShape>(shape: T) {
27
+ return strictObject({
28
+ ...shape,
29
+ extensions: XmlExtensionNodeListSchema.optional(),
30
+ foreignAttributes: XmlForeignAttributesSchema.optional(),
31
+ });
32
+ }
33
+
34
+ export function addIssue(context: z.RefinementCtx, path: Array<string | number>, message: string) {
35
+ context.addIssue({
36
+ code: z.ZodIssueCode.custom,
37
+ path,
38
+ message,
39
+ });
40
+ }
41
+
42
+ export function collectDuplicates(values: string[]): string[] {
43
+ const seen = new Set<string>();
44
+ const duplicates = new Set<string>();
45
+
46
+ for (const value of values) {
47
+ if (seen.has(value)) {
48
+ duplicates.add(value);
49
+ continue;
50
+ }
51
+ seen.add(value);
52
+ }
53
+
54
+ return [...duplicates];
55
+ }
56
+
57
+ export function asArray<T>(value: readonly T[] | T[] | undefined | null): T[] {
58
+ return Array.isArray(value) ? [...value] : [];
59
+ }
60
+ // Inferred types from exported Zod validators.
61
+ export type NonEmptyString = z.infer<typeof NonEmptyStringSchema>;
62
+ export type UriReference = z.infer<typeof UriReferenceSchema>;
63
+ export type YesNo = z.infer<typeof YesNoSchema>;
64
+ export type LowerYesNo = z.infer<typeof LowerYesNoSchema>;
65
+ export type XmlSpace = z.infer<typeof XmlSpaceSchema>;
66
+ export type XmlForeignAttributes = z.infer<typeof XmlForeignAttributesSchema>;
67
+ export type XmlExtensionNode = z.infer<typeof XmlExtensionNodeSchema>;
68
+ export type XmlExtensionNodeList = z.infer<typeof XmlExtensionNodeListSchema>;