@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.
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-format.log +6 -0
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-test.log +196 -0
- package/.turbo/turbo-typecheck.log +2 -0
- package/README.md +52 -0
- package/caliper-v1_2-zod-templates.md +123 -0
- package/case-v1_1-zod-templates.md +290 -0
- package/cat-v1_0-zod-templates.md +73 -0
- package/cc-v1_3-zod-templates.md +531 -0
- package/cc-v1_4-zod-templates.md +247 -0
- package/clr-v2_0-zod-templates.md +117 -0
- package/cmi5-v1_0-zod-templates.md +9 -0
- package/lti-zod-templates.md +11 -0
- package/oneroster-v1_2-zod-templates.md +76 -0
- package/open-badges-v3_0-zod-templates.md +66 -0
- package/package.json +42 -0
- package/qti-v2_1-zod-templates.md +45 -0
- package/qti-v2_2-zod-templates.md +32 -0
- package/qti-v3_0_1-zod-templates.md +421 -0
- package/src/adapter.ts +83 -0
- package/src/caliper/v1_2/caliper_v1p2_bootcamp_schema.ts +781 -0
- package/src/caliper/v1_2/index.ts +37 -0
- package/src/caliper/v1_2/shared.ts +122 -0
- package/src/caliper/v1_2/textual_requirements.ts +219 -0
- package/src/case/v1_1/case_v1p1_cfassociation_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfassociationgrouping_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfassociationset_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfconceptset_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfdocument_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfdocumentset_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfitem_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfitemtypeset_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cflicense_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfpackage_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfrubric_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_cfsubjectset_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_imsx_statusinfo_jsonschema1.ts +1 -0
- package/src/case/v1_1/case_v1p1_openapi3_restbinding_schema.ts +113 -0
- package/src/case/v1_1/index.ts +95 -0
- package/src/case/v1_1/shared.ts +384 -0
- package/src/cat/v1_0/cat_v1p0_restbinding_operations_schema.ts +75 -0
- package/src/cat/v1_0/index.ts +124 -0
- package/src/cat/v1_0/shared.ts +345 -0
- package/src/clr/v2_0/clr_v2p0_achievementcredential_schema.ts +16 -0
- package/src/clr/v2_0/clr_v2p0_clrcredential_schema.ts +9 -0
- package/src/clr/v2_0/clr_v2p0_endorsementcredential_schema.ts +11 -0
- package/src/clr/v2_0/clr_v2p0_getclrcredentialsresponse_schema.ts +1 -0
- package/src/clr/v2_0/clr_v2p0_imsx_statusinfo_schema.ts +8 -0
- package/src/clr/v2_0/clr_v2p0_profile_schema.ts +9 -0
- package/src/clr/v2_0/index.ts +22 -0
- package/src/clr/v2_0/shared.ts +206 -0
- package/src/cmi5/index.ts +3 -0
- package/src/cmi5/v1_0/index.ts +134 -0
- package/src/common-cartridge/v1_3/ccv1p3_imsccauth_v1p3.ts +26 -0
- package/src/common-cartridge/v1_3/ccv1p3_imscp_v1p2_v1p0.ts +352 -0
- package/src/common-cartridge/v1_3/ccv1p3_imscsmd_v1p0.ts +35 -0
- package/src/common-cartridge/v1_3/ccv1p3_imsdt_v1p3.ts +33 -0
- package/src/common-cartridge/v1_3/ccv1p3_imswl_v1p3.ts +23 -0
- package/src/common-cartridge/v1_3/ccv1p3_lomccltilink_v1p0.ts +14 -0
- package/src/common-cartridge/v1_3/ccv1p3_lommanifest_v1p0.ts +14 -0
- package/src/common-cartridge/v1_3/ccv1p3_lomresource_v1p0.ts +14 -0
- package/src/common-cartridge/v1_3/ccv1p3_qtiasiv1p2p1_v1p0.ts +964 -0
- package/src/common-cartridge/v1_3/index.ts +41 -0
- package/src/common-cartridge/v1_3/lom-internal.ts +396 -0
- package/src/common-cartridge/v1_3/shared.ts +68 -0
- package/src/common-cartridge/v1_4/core/ccv1p4_imscp_v1p2_v1p0.ts +360 -0
- package/src/common-cartridge/v1_4/core/ccv1p4_lommanifest_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/core/ccv1p4_lomresource_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/extension/cc_extresource_assignmentv1p0_v1p0.ts +61 -0
- package/src/common-cartridge/v1_4/extension/ccv1p4_cpextensionv1p2_v1p0.ts +20 -0
- package/src/common-cartridge/v1_4/extension/ims_openvideov1p0_v1p0.ts +325 -0
- package/src/common-cartridge/v1_4/index.ts +104 -0
- package/src/common-cartridge/v1_4/k12/ccv1p4_imscp_v1p2_v1p0.ts +19 -0
- package/src/common-cartridge/v1_4/k12/ccv1p4_imscp_v1p2_v1p0_thin.ts +17 -0
- package/src/common-cartridge/v1_4/k12/ccv1p4_lommanifest_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/k12/ccv1p4_lomresource_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/lom-internal.ts +476 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_imsccauth_v1p4.ts +26 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_imscsmd_v1p1.ts +36 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_imsdt_v1p4.ts +33 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_imslticc_v1p4.ts +45 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_imswl_v1p4.ts +23 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_lomccltilink_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/shared/ccv1p4_qtiasiv1p2p1_v1p0.ts +964 -0
- package/src/common-cartridge/v1_4/shared/imsbasiclti_v1p0p1.ts +24 -0
- package/src/common-cartridge/v1_4/shared/imslticm_v1p0.ts +23 -0
- package/src/common-cartridge/v1_4/shared/imslticp_v1p0.ts +57 -0
- package/src/common-cartridge/v1_4/shared/lineitem_v1p0.ts +35 -0
- package/src/common-cartridge/v1_4/shared/resourcea11ymetadata-20210915.ts +110 -0
- package/src/common-cartridge/v1_4/shared.ts +68 -0
- package/src/common-cartridge/v1_4/thin/ccv1p4_imscp_v1p2_v1p0.ts +243 -0
- package/src/common-cartridge/v1_4/thin/ccv1p4_lommanifest_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/thin/ccv1p4_lomresource_v1p0.ts +14 -0
- package/src/common-cartridge/v1_4/vdex/imsmd_loose_v1p3p2.ts +13 -0
- package/src/common-cartridge/v1_4/vdex/imsvdex_v1p0.ts +124 -0
- package/src/config.ts +121 -0
- package/src/index.ts +32 -0
- package/src/lti/ags/v2_0/index.ts +97 -0
- package/src/lti/deep-linking/v2_0/index.ts +100 -0
- package/src/lti/index.ts +26 -0
- package/src/lti/nrps/v2_0/index.ts +69 -0
- package/src/lti/proctoring/v1_0/index.ts +131 -0
- package/src/lti/shared.ts +66 -0
- package/src/lti/v1_3/index.ts +84 -0
- package/src/oneroster/v1_2/index.ts +156 -0
- package/src/oneroster/v1_2/or_v1p2_csv_binding_schema.ts +427 -0
- package/src/oneroster/v1_2/or_v1p2_gradebook_restbinding_schema.ts +120 -0
- package/src/oneroster/v1_2/or_v1p2_gradebook_service_schema.ts +243 -0
- package/src/oneroster/v1_2/or_v1p2_resource_restbinding_schema.ts +24 -0
- package/src/oneroster/v1_2/or_v1p2_resource_service_schema.ts +47 -0
- package/src/oneroster/v1_2/or_v1p2_rostering_restbinding_schema.ts +84 -0
- package/src/oneroster/v1_2/or_v1p2_rostering_service_schema.ts +288 -0
- package/src/oneroster/v1_2/shared.ts +90 -0
- package/src/open-badges/v3_0/index.ts +20 -0
- package/src/open-badges/v3_0/ob_v3p0_achievementcredential_schema.ts +17 -0
- package/src/open-badges/v3_0/ob_v3p0_endorsementcredential_schema.ts +11 -0
- package/src/open-badges/v3_0/ob_v3p0_getopenbadgecredentialsresponse_schema.ts +1 -0
- package/src/open-badges/v3_0/ob_v3p0_imsx_statusinfo_schema.ts +8 -0
- package/src/open-badges/v3_0/ob_v3p0_profile_schema.ts +9 -0
- package/src/open-badges/v3_0/shared.ts +458 -0
- package/src/qti/v2-internal.ts +1683 -0
- package/src/qti/v2_1/apipv1p0_qtiextv2p1_v1p0.ts +3 -0
- package/src/qti/v2_1/imsqti_metadata_v2p1.ts +3 -0
- package/src/qti/v2_1/imsqti_result_v2p1.ts +3 -0
- package/src/qti/v2_1/imsqti_usagedata_v2p1.ts +3 -0
- package/src/qti/v2_1/imsqti_v2p1p2.ts +71 -0
- package/src/qti/v2_1/index.ts +53 -0
- package/src/qti/v2_1/qtiv2p1_imscpv1p2_v1p0.ts +3 -0
- package/src/qti/v2_1/schemas.ts +15 -0
- package/src/qti/v2_1/shared.ts +3 -0
- package/src/qti/v2_2/apipv1p0_qtiextv2p2_v1p0p1.ts +3 -0
- package/src/qti/v2_2/imsqti_metadata_v2p2.ts +3 -0
- package/src/qti/v2_2/imsqti_result_v2p2.ts +3 -0
- package/src/qti/v2_2/imsqti_usagedata_v2p2.ts +3 -0
- package/src/qti/v2_2/imsqti_v2p2p4.ts +76 -0
- package/src/qti/v2_2/imsqtiv2p2p4_html5_v1p0.ts +8 -0
- package/src/qti/v2_2/index.ts +59 -0
- package/src/qti/v2_2/qtiv2p2_csm_v2p2.ts +4 -0
- package/src/qti/v2_2/qtiv2p2_imscpv1p2_v1p0.ts +3 -0
- package/src/qti/v2_2/schemas.ts +19 -0
- package/src/qti/v2_2/shared.ts +3 -0
- package/src/qti/v3_0_1/assessment-internal.ts +1509 -0
- package/src/qti/v3_0_1/imsqti_asiv3p0p1_v1p0.ts +57 -0
- package/src/qti/v3_0_1/imsqti_itemv3p0p1_v1p0.ts +60 -0
- package/src/qti/v3_0_1/imsqti_metadatav3p0_v1p0.ts +73 -0
- package/src/qti/v3_0_1/imsqti_outcomev3p0p1_v1p0.ts +11 -0
- package/src/qti/v3_0_1/imsqti_responseprocessingv3p0p1_v1p0.ts +17 -0
- package/src/qti/v3_0_1/imsqti_resultv3p0_v1p0.ts +222 -0
- package/src/qti/v3_0_1/imsqti_sectionv3p0p1_v1p0.ts +15 -0
- package/src/qti/v3_0_1/imsqti_stimulusv3p0p1_v1p0.ts +15 -0
- package/src/qti/v3_0_1/imsqti_testv3p0p1_v1p0.ts +49 -0
- package/src/qti/v3_0_1/imsqti_usagedatav3p0_v1p0.ts +77 -0
- package/src/qti/v3_0_1/imsqtiv3p0_afa3p0pnp_v1p0.ts +269 -0
- package/src/qti/v3_0_1/index.ts +50 -0
- package/src/qti/v3_0_1/processing-internal.ts +667 -0
- package/src/qti/v3_0_1/shared.ts +146 -0
- package/src/qti/v3_0_1/variables-internal.ts +274 -0
- package/src/shared/imsx-status.ts +49 -0
- package/src/summary.ts +70 -0
- package/src/vc-data-model/v2_0/index.ts +27 -0
- package/src/vc-data-model/v2_0/shared.ts +206 -0
- package/src/xapi/index.ts +12 -0
- package/src/xapi/shared.ts +444 -0
- package/src/xapi/v1_0_3/index.ts +169 -0
- package/src/xapi/v2_0/index.ts +256 -0
- package/test/caliper-v1_2.test.ts +270 -0
- package/test/case-v1_1.test.ts +147 -0
- package/test/cat-v1_0.test.ts +338 -0
- package/test/cc-v1_4.test.ts +239 -0
- package/test/clr-v2_0.test.ts +225 -0
- package/test/cmi5-v1_0.test.ts +196 -0
- package/test/contracts.test.ts +125 -0
- package/test/fixtures/cmi5/extended-cmi5.xml +72 -0
- package/test/fixtures/cmi5/simple-cmi5.xml +26 -0
- package/test/lti.test.ts +146 -0
- package/test/oneroster-v1_2.test.ts +234 -0
- package/test/open-badges-v3_0.test.ts +144 -0
- package/test/qti-v2_1.test.ts +146 -0
- package/test/qti-v2_2.test.ts +154 -0
- package/test/qti-v3_0_1.test.ts +576 -0
- package/test/schema-examples.test.ts +101 -0
- package/test/vc-data-model-v2_0.test.ts +63 -0
- package/test/xapi.test.ts +384 -0
- package/tsconfig.json +7 -0
- package/vc-data-model-v2_0-zod-templates.md +43 -0
- package/xapi-zod-templates.md +95 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# CASE v1.1 Zod Implementation
|
|
2
|
+
|
|
3
|
+
This document describes the Zod schema implementation for [CASE v1.1](https://www.imsglobal.org/spec/case/v1p1) (Competency and Academic Standards Exchange).
|
|
4
|
+
|
|
5
|
+
## Specification Links
|
|
6
|
+
|
|
7
|
+
- **CASE v1.1 Base**: https://www.imsglobal.org/spec/case/v1p1
|
|
8
|
+
- **JSON Schema Definitions**: https://purl.imsglobal.org/spec/case/v1p1/schema/json/
|
|
9
|
+
- **OpenAPI3 Definitions**: https://purl.imsglobal.org/spec/case/v1p1/schema/openapi/
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
CASE v1.1 defines a comprehensive data model for representing competency and academic standards frameworks. The specification includes:
|
|
14
|
+
|
|
15
|
+
- **Core Entities**: CFPackage, CFItem (competency/standard), CFAssociation (relationships), CFRubric, CFLicense
|
|
16
|
+
- **Collections**: CFAssociationSet, CFConceptSet, CFItemTypeSet, CFSubjectSet, CFDocumentSet
|
|
17
|
+
- **Integration**: IMSX Status models for API/integration scenarios
|
|
18
|
+
- **API Bindings**: OpenAPI3 REST operations for CRUD and retrieval
|
|
19
|
+
|
|
20
|
+
## Schema Organization
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
packages/contracts/src/case/v1_1/
|
|
24
|
+
├── shared.ts # Core entity and shared validators
|
|
25
|
+
├── case_v1p1_cfassociation_jsonschema1.ts # CFAssociation export
|
|
26
|
+
├── case_v1p1_cfassociationset_jsonschema1.ts # CFAssociationSet export
|
|
27
|
+
├── case_v1p1_cfconceptset_jsonschema1.ts # CFConceptSet export
|
|
28
|
+
├── case_v1p1_cfdocument_jsonschema1.ts # CFDocument export
|
|
29
|
+
├── case_v1p1_cfdocumentset_jsonschema1.ts # CFDocumentSet export
|
|
30
|
+
├── case_v1p1_cfitem_jsonschema1.ts # CFItem export
|
|
31
|
+
├── case_v1p1_cfitemtypeset_jsonschema1.ts # CFItemTypeSet export
|
|
32
|
+
├── case_v1p1_cflicense_jsonschema1.ts # CFLicense export
|
|
33
|
+
├── case_v1p1_cfpackage_jsonschema1.ts # CFPackage export
|
|
34
|
+
├── case_v1p1_cfrubric_jsonschema1.ts # CFRubric export
|
|
35
|
+
├── case_v1p1_cfsubjectset_jsonschema1.ts # CFSubjectSet export
|
|
36
|
+
├── case_v1p1_imsx_statusinfo_jsonschema1.ts # IMSX Status export
|
|
37
|
+
├── case_v1p1_openapi3_restbinding_schema.ts # REST operation bindings
|
|
38
|
+
└── index.ts # Barrel and namespace exports
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Core Schemas
|
|
42
|
+
|
|
43
|
+
### CFPackage
|
|
44
|
+
|
|
45
|
+
Root container for a competency/standards framework.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { CaseV1_1 } from "@conform-ed/contracts/case/v1_1";
|
|
49
|
+
|
|
50
|
+
const pkg = {
|
|
51
|
+
id: "6g1568e7-0i5f-7e1g-2h4d-5f8i6e9g0d1h",
|
|
52
|
+
uri: "http://example.org/cf/packages/1",
|
|
53
|
+
title: "Core Competencies",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const result = CaseV1_1.Schemas.CFPackage.safeParse(pkg);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### CFItem
|
|
60
|
+
|
|
61
|
+
Represents a competency or academic standard.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const item = {
|
|
65
|
+
id: "7h2679f8-1j6g-8f2h-3i5e-6g9j7f0h1e2i",
|
|
66
|
+
uri: "http://example.org/cf/items/1",
|
|
67
|
+
fullStatement: "Students can analyze data",
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const result = CaseV1_1.Schemas.CFItem.safeParse(item);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### CFAssociation
|
|
74
|
+
|
|
75
|
+
Represents relationships between competencies (e.g., prerequisites, composition).
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const association = {
|
|
79
|
+
id: "3d8235b4-7f2c-4b8d-9e1a-2c5f3b6d7a8e",
|
|
80
|
+
uri: "http://example.org/cf/associations/1",
|
|
81
|
+
originNodeIdentifier: "4e9346c5-8g3d-5c9e-0f2b-3d6g4c7e8b9f",
|
|
82
|
+
destinationNodeIdentifier: "5f0457d6-9h4e-6d0f-1g3c-4e7h5d8f9c0g",
|
|
83
|
+
associationType: "isChildOf",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const result = CaseV1_1.Schemas.CFAssociation.safeParse(association);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### CFRubric
|
|
90
|
+
|
|
91
|
+
Scoring guide or assessment rubric.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const rubric = {
|
|
95
|
+
id: "8i378a0g-2k7h-9g3i-4j6f-7h0k8g1i2f3j",
|
|
96
|
+
uri: "http://example.org/cf/rubrics/1",
|
|
97
|
+
title: "Assessment Rubric",
|
|
98
|
+
description: "Scoring guide for competency evaluation",
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const result = CaseV1_1.Schemas.CFRubric.safeParse(rubric);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Collections
|
|
105
|
+
|
|
106
|
+
Use collection schemas for bulk data transfer:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// CFAssociationSet
|
|
110
|
+
const assocSet = {
|
|
111
|
+
association: [
|
|
112
|
+
{
|
|
113
|
+
/* CFAssociation 1 */
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
/* CFAssociation 2 */
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const result = CaseV1_1.Schemas.CFAssociationSet.safeParse(assocSet);
|
|
122
|
+
|
|
123
|
+
// CFConceptSet
|
|
124
|
+
const conceptSet = {
|
|
125
|
+
conceptSet: [
|
|
126
|
+
{
|
|
127
|
+
/* CFConcept 1 */
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const result = CaseV1_1.Schemas.CFConceptSet.safeParse(conceptSet);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## REST API Bindings
|
|
136
|
+
|
|
137
|
+
OpenAPI3 operation signatures are exposed for API client generation and introspection:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Get single resource
|
|
141
|
+
const op = CaseV1_1.RestBinding.Operations.getCFAssociation;
|
|
142
|
+
console.log(op.method); // "GET"
|
|
143
|
+
console.log(op.path); // "/cfAssociations/{id}"
|
|
144
|
+
|
|
145
|
+
// List resources
|
|
146
|
+
const listOp = CaseV1_1.RestBinding.Operations.listCFAssociations;
|
|
147
|
+
console.log(listOp.method); // "GET"
|
|
148
|
+
console.log(listOp.path); // "/cfAssociations"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Available operations:
|
|
152
|
+
|
|
153
|
+
- `getCFAssociation` / `listCFAssociations`
|
|
154
|
+
- `getCFConcept` / `listCFConcepts`
|
|
155
|
+
- `getCFItem` / `listCFItems`
|
|
156
|
+
- `getCFItemType` / `listCFItemTypes`
|
|
157
|
+
- `getCFLicense` (single only)
|
|
158
|
+
- `getCFPackage` (single only)
|
|
159
|
+
- `getCFRubric` (single only)
|
|
160
|
+
- `listCFSubjects`
|
|
161
|
+
|
|
162
|
+
## Validators and Shared Types
|
|
163
|
+
|
|
164
|
+
### UUID
|
|
165
|
+
|
|
166
|
+
RFC4122 compliant identifier:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const uuid = "3d8235b4-7f2c-4b8d-9e1a-2c5f3b6d7a8e";
|
|
170
|
+
const result = CaseV1_1.Shared.Uuid.safeParse(uuid);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### DateTime
|
|
174
|
+
|
|
175
|
+
ISO8601 timestamp:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const dt = "2024-01-15T10:30:00Z";
|
|
179
|
+
const result = CaseV1_1.Shared.DateTime.safeParse(dt);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Link URIs
|
|
183
|
+
|
|
184
|
+
HTTP URIs for resource references:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const uri = "http://example.org/cf/items/1";
|
|
188
|
+
const result = CaseV1_1.Shared.LinkUri.safeParse(uri);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Extensible Vocabularies
|
|
192
|
+
|
|
193
|
+
Support standard and vendor-specific (ext:\*) extensions:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const typeEnum = CaseV1_1.Shared.ExtensionEnum(["isChildOf", "isPartOf"]);
|
|
197
|
+
|
|
198
|
+
// Standard value
|
|
199
|
+
typeEnum.safeParse("isChildOf"); // ✓
|
|
200
|
+
|
|
201
|
+
// Vendor extension
|
|
202
|
+
typeEnum.safeParse("ext:custom-association-type"); // ✓
|
|
203
|
+
|
|
204
|
+
// Invalid
|
|
205
|
+
typeEnum.safeParse("unknownType"); // ✗
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Import Patterns
|
|
209
|
+
|
|
210
|
+
### Full namespace
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { CaseV1_1 } from "@conform-ed/contracts/case/v1_1";
|
|
214
|
+
|
|
215
|
+
const pkg = CaseV1_1.Schemas.CFPackage;
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Individual schemas
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { CFPackageSchema, CFItemSchema } from "@conform-ed/contracts/case/v1_1";
|
|
222
|
+
|
|
223
|
+
const pkg = CFPackageSchema;
|
|
224
|
+
const item = CFItemSchema;
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Subpath export
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { CaseV1_1 } from "@conform-ed/contracts/case/v1_1";
|
|
231
|
+
|
|
232
|
+
const RestOps = CaseV1_1.RestBinding.Operations;
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Design Notes
|
|
236
|
+
|
|
237
|
+
### Strict validation
|
|
238
|
+
|
|
239
|
+
All entity schemas use `.strict()` to reject additional properties not defined in the spec. This ensures compatibility with strict JSON Schema validation.
|
|
240
|
+
|
|
241
|
+
### Extensibility
|
|
242
|
+
|
|
243
|
+
- Vendor-specific properties use `z.record(z.string(), z.unknown())` passthrough pattern
|
|
244
|
+
- Vocabulary fields use `z.union([z.enum([...]), z.string().regex(/^ext:.../)])` pattern
|
|
245
|
+
- This allows both strict standard conformance and flexible vendor extensions
|
|
246
|
+
|
|
247
|
+
### Shared IMSX Models
|
|
248
|
+
|
|
249
|
+
IMSX Status information is shared across multiple standards (CLR, OB, OneRoster, CASE):
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
import { ImsxStatusInfoSchema } from "@conform-ed/contracts/case/v1_1";
|
|
253
|
+
// Same schema available in CLR v2_0, OpenBadges v3_0, OneRoster v1_2
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Testing
|
|
257
|
+
|
|
258
|
+
Run CASE v1.1 tests:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
bun test packages/contracts/test/case-v1_1.test.ts
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Tests cover:
|
|
265
|
+
|
|
266
|
+
- Core entity schema validation
|
|
267
|
+
- UUID and datetime validators
|
|
268
|
+
- REST binding operation structure
|
|
269
|
+
- Extensible vocabulary support
|
|
270
|
+
- Derived template exports
|
|
271
|
+
|
|
272
|
+
## Compliance
|
|
273
|
+
|
|
274
|
+
- **Specification**: CASE v1.1 JSON Schema and OpenAPI3
|
|
275
|
+
- **Validation Mode**: strict (additionalProperties rejected)
|
|
276
|
+
- **Date Format**: ISO8601 with optional timezone
|
|
277
|
+
- **Identifier Format**: RFC4122 UUID v4/v5
|
|
278
|
+
- **Extensibility**: ext:\* vendor extensions supported per spec
|
|
279
|
+
|
|
280
|
+
## Known Limitations
|
|
281
|
+
|
|
282
|
+
1. **OpenAPI2 variants**: Not implemented; OpenAPI3 only
|
|
283
|
+
2. **Profile/extension variants**: No profile-specific sub-schemas in this initial release
|
|
284
|
+
3. **Computed collections**: Collection schemas model explicit array payloads, not server-generated paging
|
|
285
|
+
|
|
286
|
+
## Future Enhancements
|
|
287
|
+
|
|
288
|
+
- Profile-specific sub-schemas (e.g., CASE-OSTP)
|
|
289
|
+
- Paging/filtering operation bindings from OpenAPI3
|
|
290
|
+
- Domain-specific vocabulary registries for extensible types
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# CAT v1.0 implementation -> Zod template notes
|
|
2
|
+
|
|
3
|
+
## Published specification
|
|
4
|
+
|
|
5
|
+
- Main specification: `https://www.imsglobal.org/spec/cat/v1p0/impl/`
|
|
6
|
+
- Latest specification permalink: `https://www.imsglobal.org/spec/cat/latest/impl/`
|
|
7
|
+
- Errata: `https://www.imsglobal.org/spec/cat/v1p0/errata/`
|
|
8
|
+
|
|
9
|
+
This note accompanies `packages/contracts/src/cat/v1_0/`.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. What was implemented
|
|
14
|
+
|
|
15
|
+
This port models the CAT v1.0 core REST service contract and shared payload types:
|
|
16
|
+
|
|
17
|
+
- section configuration (`SectionData`)
|
|
18
|
+
- item staging (`ItemStage`)
|
|
19
|
+
- candidate submission payloads (`AssessmentResult`)
|
|
20
|
+
- CAT engine return payloads (`CatEngineResultReport`)
|
|
21
|
+
- operation request/response envelopes for:
|
|
22
|
+
- `createSection`
|
|
23
|
+
- `getSection`
|
|
24
|
+
- `createSession`
|
|
25
|
+
- `submitResults`
|
|
26
|
+
- `endSession`
|
|
27
|
+
- `endSection`
|
|
28
|
+
|
|
29
|
+
Public package surface:
|
|
30
|
+
|
|
31
|
+
- root namespace: `CatV1_0`
|
|
32
|
+
- subpath export: `@conform-ed/contracts/cat/v1_0`
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. Structural choices
|
|
37
|
+
|
|
38
|
+
The implementation is split into:
|
|
39
|
+
|
|
40
|
+
- `shared.ts` for core CAT data types, shared primitives, and request/response schemas
|
|
41
|
+
- `cat_v1p0_restbinding_operations_schema.ts` for endpoint-level operation contracts
|
|
42
|
+
- `index.ts` for namespaced exports and derived template metadata
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 3. Validation choices
|
|
47
|
+
|
|
48
|
+
- strict objects are used across payloads (`.strict()`) to avoid silent property drift
|
|
49
|
+
- UUID fields use RFC4122 regex validation
|
|
50
|
+
- date-time fields allow both `Z` and numeric UTC offset forms
|
|
51
|
+
- enumerated values use explicit vocabularies where practical, with optional `ext:*` extension tokens for extensibility
|
|
52
|
+
- error payloads are normalized into a predictable `{ error, message, statusCode, details? }` shape
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 4. REST binding operation shape
|
|
57
|
+
|
|
58
|
+
Each operation entry exposes:
|
|
59
|
+
|
|
60
|
+
- `method`
|
|
61
|
+
- `path`
|
|
62
|
+
- `requestPayload`
|
|
63
|
+
- `successResponsePayload`
|
|
64
|
+
- `errorResponsePayload`
|
|
65
|
+
|
|
66
|
+
This mirrors the operation-catalog pattern used in other contracts packages (e.g., OneRoster REST bindings) and keeps API-client generation/introspection straightforward.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 5. Known limitations
|
|
71
|
+
|
|
72
|
+
- CAT engine-specific custom payload fragments are intentionally open (`z.record(z.string(), z.unknown())`) where the published specification does not tightly standardize vendor-specific structures.
|
|
73
|
+
- This version focuses on the core CAT service API contracts and does not attempt to fully model every adjacent referenced standard artifact (QTI Metadata, Usage Data vocabularies, etc.) inline.
|