@intellectif/lk-core 0.2.1 → 0.3.1
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/dist/activity-zdcAMtFB.d.cts +626 -0
- package/dist/activity-zdcAMtFB.d.ts +626 -0
- package/dist/chunk-3YAVDV5F.js +47 -0
- package/dist/chunk-3YAVDV5F.js.map +1 -0
- package/dist/chunk-55O4M45K.js +57 -0
- package/dist/chunk-55O4M45K.js.map +1 -0
- package/dist/chunk-5GJJHGY5.js +576 -0
- package/dist/chunk-5GJJHGY5.js.map +1 -0
- package/dist/{chunk-ZHOX6TO4.js → chunk-HS7BYCGE.js} +65 -7
- package/dist/chunk-HS7BYCGE.js.map +1 -0
- package/dist/chunk-PIMX4B4D.cjs +47 -0
- package/dist/chunk-PIMX4B4D.cjs.map +1 -0
- package/dist/chunk-QOAORTA4.cjs +576 -0
- package/dist/chunk-QOAORTA4.cjs.map +1 -0
- package/dist/chunk-QSVBYTNM.js +94 -0
- package/dist/chunk-QSVBYTNM.js.map +1 -0
- package/dist/{chunk-PJFDAP54.cjs → chunk-RUGIOQZY.cjs} +66 -8
- package/dist/chunk-RUGIOQZY.cjs.map +1 -0
- package/dist/chunk-THSZMZND.cjs +94 -0
- package/dist/chunk-THSZMZND.cjs.map +1 -0
- package/dist/chunk-YNTYWHZI.cjs +57 -0
- package/dist/chunk-YNTYWHZI.cjs.map +1 -0
- package/dist/index.cjs +185 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +253 -7
- package/dist/index.d.ts +253 -7
- package/dist/index.js +188 -9
- package/dist/index.js.map +1 -1
- package/dist/schemas.cjs +29 -2
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +310 -29
- package/dist/schemas.d.ts +310 -29
- package/dist/schemas.js +32 -5
- package/dist/scoring.cjs +13 -3
- package/dist/scoring.cjs.map +1 -1
- package/dist/scoring.d.cts +29 -5
- package/dist/scoring.d.ts +29 -5
- package/dist/scoring.js +12 -2
- package/dist/xapi.cjs +3 -3
- package/dist/xapi.d.cts +40 -2
- package/dist/xapi.d.ts +40 -2
- package/dist/xapi.js +2 -2
- package/package.json +7 -2
- package/dist/activity-D5tqgx8A.d.cts +0 -330
- package/dist/activity-D5tqgx8A.d.ts +0 -330
- package/dist/chunk-2T3IL7VL.js +0 -147
- package/dist/chunk-2T3IL7VL.js.map +0 -1
- package/dist/chunk-3JMLUUFS.cjs +0 -124
- package/dist/chunk-3JMLUUFS.cjs.map +0 -1
- package/dist/chunk-6VOCV4EX.js +0 -25
- package/dist/chunk-6VOCV4EX.js.map +0 -1
- package/dist/chunk-DCDOTQNH.cjs +0 -147
- package/dist/chunk-DCDOTQNH.cjs.map +0 -1
- package/dist/chunk-DV466SBJ.cjs +0 -25
- package/dist/chunk-DV466SBJ.cjs.map +0 -1
- package/dist/chunk-GZ73G2TS.js +0 -124
- package/dist/chunk-GZ73G2TS.js.map +0 -1
- package/dist/chunk-PJFDAP54.cjs.map +0 -1
- package/dist/chunk-ZHOX6TO4.js.map +0 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunkQOAORTA4cjs = require('./chunk-QOAORTA4.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _chunkPIMX4B4Dcjs = require('./chunk-PIMX4B4D.cjs');
|
|
10
|
+
|
|
11
|
+
// src/schemas/json-schema.ts
|
|
12
|
+
var _v4 = require('zod/v4');
|
|
13
|
+
var multipleChoiceJsonSchema = _v4.z.toJSONSchema(_chunkQOAORTA4cjs.MultipleChoiceDataSchema, {
|
|
14
|
+
target: "draft-7"
|
|
15
|
+
});
|
|
16
|
+
var fillInTheBlanksJsonSchema = _v4.z.toJSONSchema(_chunkQOAORTA4cjs.FillInTheBlanksDataSchema, {
|
|
17
|
+
target: "draft-7"
|
|
18
|
+
});
|
|
19
|
+
var writtenResponseJsonSchema = _v4.z.toJSONSchema(_chunkQOAORTA4cjs.WrittenResponseDataSchema, {
|
|
20
|
+
target: "draft-7"
|
|
21
|
+
});
|
|
22
|
+
function jsonSchemaFor(type) {
|
|
23
|
+
const descriptor = _chunkQOAORTA4cjs.getActivityTypeDescriptor.call(void 0, type);
|
|
24
|
+
if (descriptor === void 0) {
|
|
25
|
+
throw new (0, _chunkPIMX4B4Dcjs.UnknownActivityTypeError)(type);
|
|
26
|
+
}
|
|
27
|
+
return _v4.z.toJSONSchema(descriptor.schema, { target: "draft-7" });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/schemas/index.ts
|
|
31
|
+
function validateActivity(type, data) {
|
|
32
|
+
const descriptor = _chunkQOAORTA4cjs.getActivityTypeDescriptor.call(void 0, type);
|
|
33
|
+
if (descriptor === void 0) {
|
|
34
|
+
throw new (0, _chunkPIMX4B4Dcjs.UnknownActivityTypeError)(String(type));
|
|
35
|
+
}
|
|
36
|
+
const result = descriptor.schema.safeParse(data);
|
|
37
|
+
if (result.success) {
|
|
38
|
+
return { success: true, data: result.data };
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
errors: result.error.issues.map((issue) => ({
|
|
43
|
+
path: issue.path.map(String),
|
|
44
|
+
message: issue.message,
|
|
45
|
+
code: issue.code
|
|
46
|
+
}))
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
exports.multipleChoiceJsonSchema = multipleChoiceJsonSchema; exports.fillInTheBlanksJsonSchema = fillInTheBlanksJsonSchema; exports.writtenResponseJsonSchema = writtenResponseJsonSchema; exports.jsonSchemaFor = jsonSchemaFor; exports.validateActivity = validateActivity;
|
|
57
|
+
//# sourceMappingURL=chunk-YNTYWHZI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-YNTYWHZI.cjs","../src/schemas/json-schema.ts","../src/schemas/index.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACVA,4BAAkB;AAiBX,IAAM,yBAAA,EAA2B,KAAA,CAAE,YAAA,CAAa,0CAAA,EAA0B;AAAA,EAC/E,MAAA,EAAQ;AACV,CAAC,CAAA;AAOM,IAAM,0BAAA,EAA4B,KAAA,CAAE,YAAA,CAAa,2CAAA,EAA2B;AAAA,EACjF,MAAA,EAAQ;AACV,CAAC,CAAA;AAMM,IAAM,0BAAA,EAA4B,KAAA,CAAE,YAAA,CAAa,2CAAA,EAA2B;AAAA,EACjF,MAAA,EAAQ;AACV,CAAC,CAAA;AAUM,SAAS,aAAA,CAAc,IAAA,EAAuC;AACnE,EAAA,MAAM,WAAA,EAAa,yDAAA,IAA8B,CAAA;AACjD,EAAA,GAAA,CAAI,WAAA,IAAe,KAAA,CAAA,EAAW;AAC5B,IAAA,MAAM,IAAI,+CAAA,CAAyB,IAAI,CAAA;AAAA,EACzC;AACA,EAAA,OAAO,KAAA,CAAE,YAAA,CAAa,UAAA,CAAW,MAAA,EAAiB,EAAE,MAAA,EAAQ,UAAU,CAAC,CAAA;AAIzE;AD3BA;AACA;AEcO,SAAS,gBAAA,CACd,IAAA,EACA,IAAA,EACsC;AACtC,EAAA,MAAM,WAAA,EAAa,yDAAA,IAA8B,CAAA;AACjD,EAAA,GAAA,CAAI,WAAA,IAAe,KAAA,CAAA,EAAW;AAC5B,IAAA,MAAM,IAAI,+CAAA,CAAyB,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,OAAA,EAAS,UAAA,CAAW,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA;AAE/C,EAAA,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS;AAClB,IAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,KAA2B,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAA,GAAA,CAAW;AAAA,MAC1C,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAAA,MAC3B,OAAA,EAAS,KAAA,CAAM,OAAA;AAAA,MACf,IAAA,EAAM,KAAA,CAAM;AAAA,IACd,CAAA,CAAE;AAAA,EACJ,CAAA;AACF;AFlBA;AACA;AACE;AACA;AACA;AACA;AACA;AACF,8QAAC","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-YNTYWHZI.cjs","sourcesContent":[null,"import { z } from 'zod/v4';\nimport { UnknownActivityTypeError } from '../errors.js';\nimport { getActivityTypeDescriptor } from '../registry/index.js';\nimport { FillInTheBlanksDataSchema } from './fill-in-the-blanks.js';\nimport { MultipleChoiceDataSchema } from './multiple-choice.js';\nimport { WrittenResponseDataSchema } from './written-response.js';\n\n/**\n * JSON Schema (Draft 7) representation of the Multiple Choice activity data\n * contract, generated natively by Zod 4. Draft 7 is mandated by Requirement\n * 2.2 for the widest AI-prompt / OpenAPI tooling compatibility. The semantic\n * `.refine()` guards are not representable in JSON Schema and are\n * intentionally omitted — the export captures the *structural* contract only.\n * Since v0.3 the source schemas are loose, so these no longer emit\n * `additionalProperties: false` — the JSON Schema and `validateActivity` now\n * agree on unknown-key handling.\n */\nexport const multipleChoiceJsonSchema = z.toJSONSchema(MultipleChoiceDataSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) representation of the Fill-in-the-Blanks activity data\n * contract, generated natively by Zod 4. Structural contract only (semantic\n * `.refine()` guards are Zod-only and not representable in JSON Schema).\n */\nexport const fillInTheBlanksJsonSchema = z.toJSONSchema(FillInTheBlanksDataSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) representation of the Written Response activity data\n * contract. Structural contract only.\n */\nexport const writtenResponseJsonSchema = z.toJSONSchema(WrittenResponseDataSchema, {\n target: 'draft-7',\n});\n\n/**\n * Derives the JSON Schema (Draft 7) for any REGISTERED activity type — the\n * live, registry-backed replacement for the static per-type exports above,\n * and the building block for AI generation pipelines (R6.1): pass the result\n * as a structured-output schema so a model can only emit valid items.\n *\n * @throws UnknownActivityTypeError when `type` has no registered descriptor.\n */\nexport function jsonSchemaFor(type: string): Record<string, unknown> {\n const descriptor = getActivityTypeDescriptor(type);\n if (descriptor === undefined) {\n throw new UnknownActivityTypeError(type);\n }\n return z.toJSONSchema(descriptor.schema as never, { target: 'draft-7' }) as Record<\n string,\n unknown\n >;\n}\n","import { UnknownActivityTypeError } from '../errors.js';\nimport { getActivityTypeDescriptor } from '../registry/index.js';\nimport type { ActivityDataMap, ActivityType, ValidationResult } from '../types/activity.js';\n\nexport { FeedbackSchema } from './feedback.js';\nexport {\n BlankConfigSchema,\n FillInTheBlanksDataSchema,\n TextMatchPolicySchema,\n} from './fill-in-the-blanks.js';\nexport {\n fillInTheBlanksJsonSchema,\n jsonSchemaFor,\n multipleChoiceJsonSchema,\n writtenResponseJsonSchema,\n} from './json-schema.js';\nexport { MediaSchema, MediaUrlSchema } from './media.js';\nexport { MultipleChoiceDataSchema, MultipleChoiceOptionSchema } from './multiple-choice.js';\nexport {\n RedactedBlankConfigSchema,\n RedactedFillInTheBlanksDataSchema,\n RedactedMultipleChoiceDataSchema,\n RedactedMultipleChoiceOptionSchema,\n RedactedWrittenResponseDataSchema,\n} from './redacted.js';\nexport {\n WrittenResponseDataSchema,\n WrittenResponseRubricCriterionSchema,\n WrittenResponseRubricSchema,\n} from './written-response.js';\n\n/**\n * Validates raw activity data against the schema registered for the given\n * activity type (built-in or consumer-registered via `registerActivityType`).\n *\n * Unknown keys are PRESERVED, not stripped: every built-in schema is loose,\n * so consumer sidecar fields and forward-version fields survive validation\n * verbatim in the returned `data`.\n *\n * @returns `{ success: true, data }` with the typed, validated data, or\n * `{ success: false, errors }` with one entry per failed constraint.\n * @throws UnknownActivityTypeError when `type` has no registered descriptor.\n */\nexport function validateActivity<T extends ActivityType>(\n type: T,\n data: unknown,\n): ValidationResult<ActivityDataMap[T]> {\n const descriptor = getActivityTypeDescriptor(type);\n if (descriptor === undefined) {\n throw new UnknownActivityTypeError(String(type));\n }\n\n const result = descriptor.schema.safeParse(data);\n\n if (result.success) {\n return { success: true, data: result.data as ActivityDataMap[T] };\n }\n\n return {\n success: false,\n errors: result.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n })),\n };\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var _chunk3JMLUUFScjs = require('./chunk-3JMLUUFS.cjs');
|
|
5
4
|
|
|
6
5
|
|
|
6
|
+
var _chunkTHSZMZNDcjs = require('./chunk-THSZMZND.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var _chunkPJFDAP54cjs = require('./chunk-PJFDAP54.cjs');
|
|
11
10
|
|
|
12
11
|
|
|
12
|
+
var _chunkRUGIOQZYcjs = require('./chunk-RUGIOQZY.cjs');
|
|
13
13
|
|
|
14
|
-
var _chunkDV466SBJcjs = require('./chunk-DV466SBJ.cjs');
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
|
|
19
|
+
var _chunkYNTYWHZIcjs = require('./chunk-YNTYWHZI.cjs');
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
var _chunkDCDOTQNHcjs = require('./chunk-DCDOTQNH.cjs');
|
|
26
25
|
|
|
27
26
|
|
|
28
27
|
|
|
@@ -41,5 +40,185 @@ var _chunkDCDOTQNHcjs = require('./chunk-DCDOTQNH.cjs');
|
|
|
41
40
|
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
var _chunkQOAORTA4cjs = require('./chunk-QOAORTA4.cjs');
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
var _chunkPIMX4B4Dcjs = require('./chunk-PIMX4B4D.cjs');
|
|
54
|
+
|
|
55
|
+
// src/redact.ts
|
|
56
|
+
function mergePolicy(base, overrides) {
|
|
57
|
+
if (overrides === void 0) {
|
|
58
|
+
return base;
|
|
59
|
+
}
|
|
60
|
+
const merged = { ...base };
|
|
61
|
+
for (const [key, override] of Object.entries(overrides)) {
|
|
62
|
+
const current = merged[key];
|
|
63
|
+
merged[key] = typeof override === "object" && typeof current === "object" ? { ...current, ...override } : override;
|
|
64
|
+
}
|
|
65
|
+
return merged;
|
|
66
|
+
}
|
|
67
|
+
function isSensitivity(value) {
|
|
68
|
+
return typeof value === "string";
|
|
69
|
+
}
|
|
70
|
+
function keepField(sensitivity, reveal) {
|
|
71
|
+
if (sensitivity === "public") {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
return sensitivity === "answer-key" && reveal === "after-submit";
|
|
75
|
+
}
|
|
76
|
+
function redactValue(value, policy, reveal) {
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
return value.map((element) => redactValue(element, policy, reveal));
|
|
79
|
+
}
|
|
80
|
+
if (value === null || typeof value !== "object") {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
const source = value;
|
|
84
|
+
const output = {};
|
|
85
|
+
for (const [key, fieldValue] of Object.entries(source)) {
|
|
86
|
+
if (fieldValue === void 0) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const classification = policy[key];
|
|
90
|
+
if (classification === void 0) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (isSensitivity(classification)) {
|
|
94
|
+
if (keepField(classification, reveal)) {
|
|
95
|
+
output[key] = fieldValue;
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const nested = redactValue(fieldValue, classification, reveal);
|
|
100
|
+
if (nested !== void 0) {
|
|
101
|
+
output[key] = nested;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return output;
|
|
105
|
+
}
|
|
106
|
+
function redact(data, options = {}) {
|
|
107
|
+
const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
|
|
108
|
+
const descriptor = _chunkQOAORTA4cjs.getActivityTypeDescriptor.call(void 0, data.type);
|
|
109
|
+
if (descriptor === void 0) {
|
|
110
|
+
throw new (0, _chunkPIMX4B4Dcjs.UnknownActivityTypeError)(String(data.type));
|
|
111
|
+
}
|
|
112
|
+
if (descriptor.fieldPolicy === void 0) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Activity type "${descriptor.type}" has no fieldPolicy; redact() cannot run fail-closed redaction without one.`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
const effectivePolicy = mergePolicy(descriptor.fieldPolicy, options.policy);
|
|
118
|
+
const projected = redactValue(data, effectivePolicy, reveal);
|
|
119
|
+
const result = { ...projected, redacted: true };
|
|
120
|
+
if (reveal === "none" && descriptor.redactedSchema !== void 0) {
|
|
121
|
+
const parsed = descriptor.redactedSchema.safeParse(result);
|
|
122
|
+
if (!parsed.success) {
|
|
123
|
+
throw new (0, _chunkPIMX4B4Dcjs.ActivitySchemaError)(
|
|
124
|
+
descriptor.type,
|
|
125
|
+
parsed.error.issues.map((issue) => ({
|
|
126
|
+
path: issue.path.map(String),
|
|
127
|
+
message: issue.message,
|
|
128
|
+
code: issue.code
|
|
129
|
+
}))
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
function assertRedacted(data) {
|
|
136
|
+
if (typeof data !== "object" || data === null) {
|
|
137
|
+
throw new (0, _chunkPIMX4B4Dcjs.ActivitySchemaError)("unknown", [
|
|
138
|
+
{ path: [], message: "Redacted activity data must be an object.", code: "invalid_type" }
|
|
139
|
+
]);
|
|
140
|
+
}
|
|
141
|
+
const candidate = data;
|
|
142
|
+
if (candidate.redacted !== true) {
|
|
143
|
+
throw new (0, _chunkPIMX4B4Dcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
|
|
144
|
+
{
|
|
145
|
+
path: ["redacted"],
|
|
146
|
+
message: "Missing redacted marker \u2014 this payload is not a redact() projection.",
|
|
147
|
+
code: "custom"
|
|
148
|
+
}
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
const type = typeof candidate.type === "string" ? candidate.type : "";
|
|
152
|
+
const descriptor = _chunkQOAORTA4cjs.getActivityTypeDescriptor.call(void 0, type);
|
|
153
|
+
if (descriptor === void 0) {
|
|
154
|
+
throw new (0, _chunkPIMX4B4Dcjs.UnknownActivityTypeError)(type);
|
|
155
|
+
}
|
|
156
|
+
if (descriptor.redactedSchema === void 0) {
|
|
157
|
+
throw new (0, _chunkPIMX4B4Dcjs.ActivitySchemaError)(descriptor.type, [
|
|
158
|
+
{
|
|
159
|
+
path: [],
|
|
160
|
+
message: `Activity type "${descriptor.type}" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,
|
|
161
|
+
code: "custom"
|
|
162
|
+
}
|
|
163
|
+
]);
|
|
164
|
+
}
|
|
165
|
+
const parsed = descriptor.redactedSchema.safeParse(candidate);
|
|
166
|
+
if (!parsed.success) {
|
|
167
|
+
throw new (0, _chunkPIMX4B4Dcjs.ActivitySchemaError)(
|
|
168
|
+
descriptor.type,
|
|
169
|
+
parsed.error.issues.map((issue) => ({
|
|
170
|
+
path: issue.path.map(String),
|
|
171
|
+
message: issue.message,
|
|
172
|
+
code: issue.code
|
|
173
|
+
}))
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
exports.ActivitySchemaError = _chunkPIMX4B4Dcjs.ActivitySchemaError; exports.BlankConfigSchema = _chunkQOAORTA4cjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunkTHSZMZNDcjs.DEFAULT_PASS_THRESHOLD; exports.DeferredScoringError = _chunkPIMX4B4Dcjs.DeferredScoringError; exports.FeedbackSchema = _chunkQOAORTA4cjs.FeedbackSchema; exports.FillInTheBlanksDataSchema = _chunkQOAORTA4cjs.FillInTheBlanksDataSchema; exports.MediaSchema = _chunkQOAORTA4cjs.MediaSchema; exports.MediaUrlSchema = _chunkQOAORTA4cjs.MediaUrlSchema; exports.MultipleChoiceDataSchema = _chunkQOAORTA4cjs.MultipleChoiceDataSchema; exports.MultipleChoiceOptionSchema = _chunkQOAORTA4cjs.MultipleChoiceOptionSchema; exports.RedactedBlankConfigSchema = _chunkQOAORTA4cjs.RedactedBlankConfigSchema; exports.RedactedFillInTheBlanksDataSchema = _chunkQOAORTA4cjs.RedactedFillInTheBlanksDataSchema; exports.RedactedMultipleChoiceDataSchema = _chunkQOAORTA4cjs.RedactedMultipleChoiceDataSchema; exports.RedactedMultipleChoiceOptionSchema = _chunkQOAORTA4cjs.RedactedMultipleChoiceOptionSchema; exports.RedactedScoringError = _chunkPIMX4B4Dcjs.RedactedScoringError; exports.RedactedWrittenResponseDataSchema = _chunkQOAORTA4cjs.RedactedWrittenResponseDataSchema; exports.TextMatchPolicySchema = _chunkQOAORTA4cjs.TextMatchPolicySchema; exports.UnknownActivityTypeError = _chunkPIMX4B4Dcjs.UnknownActivityTypeError; exports.WrittenResponseDataSchema = _chunkQOAORTA4cjs.WrittenResponseDataSchema; exports.WrittenResponseRubricCriterionSchema = _chunkQOAORTA4cjs.WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = _chunkQOAORTA4cjs.WrittenResponseRubricSchema; exports.XAPIVerb = _chunkRUGIOQZYcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkRUGIOQZYcjs.XAPI_VERB_DISPLAY; exports.assertRedacted = assertRedacted; exports.computePassThreshold = _chunkTHSZMZNDcjs.computePassThreshold; exports.countWords = _chunkQOAORTA4cjs.countWords; exports.defineActivityType = _chunkQOAORTA4cjs.defineActivityType; exports.evaluate = _chunkTHSZMZNDcjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunkYNTYWHZIcjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunkQOAORTA4cjs.fillInTheBlanksType; exports.getActivityTypeDescriptor = _chunkQOAORTA4cjs.getActivityTypeDescriptor; exports.jsonSchemaFor = _chunkYNTYWHZIcjs.jsonSchemaFor; exports.levenshteinDistance = _chunkQOAORTA4cjs.levenshteinDistance; exports.matchText = _chunkQOAORTA4cjs.matchText; exports.multipleChoiceJsonSchema = _chunkYNTYWHZIcjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunkQOAORTA4cjs.multipleChoiceType; exports.redact = redact; exports.registerActivityType = _chunkQOAORTA4cjs.registerActivityType; exports.registeredActivityTypes = _chunkQOAORTA4cjs.registeredActivityTypes; exports.score = _chunkTHSZMZNDcjs.score; exports.validateActivity = _chunkYNTYWHZIcjs.validateActivity; exports.validateXAPIStatement = _chunkRUGIOQZYcjs.validateXAPIStatement; exports.writtenResponseJsonSchema = _chunkYNTYWHZIcjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunkQOAORTA4cjs.writtenResponseType; exports.xAPIBuilder = _chunkRUGIOQZYcjs.xAPIBuilder;
|
|
45
224
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,onCAAC","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/index.cjs"}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/index.cjs","../src/redact.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACA;ACAA,SAAS,WAAA,CAAY,IAAA,EAAmB,SAAA,EAAiD;AACvF,EAAA,GAAA,CAAI,UAAA,IAAc,KAAA,CAAA,EAAW;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAA,EAAoD,EAAE,GAAG,KAAK,CAAA;AACpE,EAAA,IAAA,CAAA,MAAW,CAAC,GAAA,EAAK,QAAQ,EAAA,GAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvD,IAAA,MAAM,QAAA,EAAU,MAAA,CAAO,GAAG,CAAA;AAC1B,IAAA,MAAA,CAAO,GAAG,EAAA,EACR,OAAO,SAAA,IAAa,SAAA,GAAY,OAAO,QAAA,IAAY,SAAA,EAC/C,EAAE,GAAG,OAAA,EAAS,GAAG,SAAS,EAAA,EAC1B,QAAA;AAAA,EACR;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,aAAA,CAAc,KAAA,EAAwD;AAC7E,EAAA,OAAO,OAAO,MAAA,IAAU,QAAA;AAC1B;AAEA,SAAS,SAAA,CAAU,WAAA,EAA0B,MAAA,EAA0C;AACrF,EAAA,GAAA,CAAI,YAAA,IAAgB,QAAA,EAAU;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,YAAA,IAAgB,aAAA,GAAgB,OAAA,IAAW,cAAA;AACpD;AAEA,SAAS,WAAA,CACP,KAAA,EACA,MAAA,EACA,MAAA,EACS;AACT,EAAA,GAAA,CAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,OAAA,EAAA,GAAY,WAAA,CAAY,OAAA,EAAS,MAAA,EAAQ,MAAM,CAAC,CAAA;AAAA,EACpE;AACA,EAAA,GAAA,CAAI,MAAA,IAAU,KAAA,GAAQ,OAAO,MAAA,IAAU,QAAA,EAAU;AAI/C,IAAA,OAAO,KAAA,CAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,EAAS,KAAA;AACf,EAAA,MAAM,OAAA,EAAkC,CAAC,CAAA;AACzC,EAAA,IAAA,CAAA,MAAW,CAAC,GAAA,EAAK,UAAU,EAAA,GAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACtD,IAAA,GAAA,CAAI,WAAA,IAAe,KAAA,CAAA,EAAW;AAC5B,MAAA,QAAA;AAAA,IACF;AACA,IAAA,MAAM,eAAA,EAAiB,MAAA,CAAO,GAAG,CAAA;AACjC,IAAA,GAAA,CAAI,eAAA,IAAmB,KAAA,CAAA,EAAW;AAGhC,MAAA,QAAA;AAAA,IACF;AACA,IAAA,GAAA,CAAI,aAAA,CAAc,cAAc,CAAA,EAAG;AACjC,MAAA,GAAA,CAAI,SAAA,CAAU,cAAA,EAAgB,MAAM,CAAA,EAAG;AACrC,QAAA,MAAA,CAAO,GAAG,EAAA,EAAI,UAAA;AAAA,MAChB;AACA,MAAA,QAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAA,EAAS,WAAA,CAAY,UAAA,EAAY,cAAA,EAAgB,MAAM,CAAA;AAC7D,IAAA,GAAA,CAAI,OAAA,IAAW,KAAA,CAAA,EAAW;AACxB,MAAA,MAAA,CAAO,GAAG,EAAA,EAAI,MAAA;AAAA,IAChB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAiBO,SAAS,MAAA,CACd,IAAA,EACA,QAAA,EAAyB,CAAC,CAAA,EACJ;AACtB,EAAA,MAAM,OAAA,mBAAS,OAAA,CAAQ,MAAA,UAAU,QAAA;AACjC,EAAA,MAAM,WAAA,EAAa,yDAAA,IAA0B,CAAK,IAAI,CAAA;AACtD,EAAA,GAAA,CAAI,WAAA,IAAe,KAAA,CAAA,EAAW;AAC5B,IAAA,MAAM,IAAI,+CAAA,CAAyB,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EACtD;AACA,EAAA,GAAA,CAAI,UAAA,CAAW,YAAA,IAAgB,KAAA,CAAA,EAAW;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,eAAA,EAAkB,UAAA,CAAW,IAAI,CAAA,4EAAA;AAAA,IACnC,CAAA;AAAA,EACF;AAEA,EAAA,MAAM,gBAAA,EAAkB,WAAA,CAAY,UAAA,CAAW,WAAA,EAAa,OAAA,CAAQ,MAAM,CAAA;AAC1E,EAAA,MAAM,UAAA,EAAY,WAAA,CAAY,IAAA,EAAM,eAAA,EAAiB,MAAM,CAAA;AAC3D,EAAA,MAAM,OAAA,EAAS,EAAE,GAAG,SAAA,EAAW,QAAA,EAAU,KAAc,CAAA;AAEvD,EAAA,GAAA,CAAI,OAAA,IAAW,OAAA,GAAU,UAAA,CAAW,eAAA,IAAmB,KAAA,CAAA,EAAW;AAChE,IAAA,MAAM,OAAA,EAAS,UAAA,CAAW,cAAA,CAAe,SAAA,CAAU,MAAM,CAAA;AACzD,IAAA,GAAA,CAAI,CAAC,MAAA,CAAO,OAAA,EAAS;AACnB,MAAA,MAAM,IAAI,0CAAA;AAAA,QACR,UAAA,CAAW,IAAA;AAAA,QACX,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAA,GAAA,CAAW;AAAA,UAClC,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAAA,UAC3B,OAAA,EAAS,KAAA,CAAM,OAAA;AAAA,UACf,IAAA,EAAM,KAAA,CAAM;AAAA,QACd,CAAA,CAAE;AAAA,MACJ,CAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AASO,SAAS,cAAA,CAAe,IAAA,EAAqD;AAClF,EAAA,GAAA,CAAI,OAAO,KAAA,IAAS,SAAA,GAAY,KAAA,IAAS,IAAA,EAAM;AAC7C,IAAA,MAAM,IAAI,0CAAA,CAAoB,SAAA,EAAW;AAAA,MACvC,EAAE,IAAA,EAAM,CAAC,CAAA,EAAG,OAAA,EAAS,2CAAA,EAA6C,IAAA,EAAM,eAAe;AAAA,IACzF,CAAC,CAAA;AAAA,EACH;AACA,EAAA,MAAM,UAAA,EAAY,IAAA;AAClB,EAAA,GAAA,CAAI,SAAA,CAAU,SAAA,IAAa,IAAA,EAAM;AAC/B,IAAA,MAAM,IAAI,0CAAA,CAAoB,MAAA,kBAAO,SAAA,CAAU,IAAA,UAAQ,WAAS,CAAA,EAAG;AAAA,MACjE;AAAA,QACE,IAAA,EAAM,CAAC,UAAU,CAAA;AAAA,QACjB,OAAA,EAAS,2EAAA;AAAA,QACT,IAAA,EAAM;AAAA,MACR;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACA,EAAA,MAAM,KAAA,EAAO,OAAO,SAAA,CAAU,KAAA,IAAS,SAAA,EAAW,SAAA,CAAU,KAAA,EAAO,EAAA;AACnE,EAAA,MAAM,WAAA,EAAa,yDAAA,IAA8B,CAAA;AACjD,EAAA,GAAA,CAAI,WAAA,IAAe,KAAA,CAAA,EAAW;AAC5B,IAAA,MAAM,IAAI,+CAAA,CAAyB,IAAI,CAAA;AAAA,EACzC;AACA,EAAA,GAAA,CAAI,UAAA,CAAW,eAAA,IAAmB,KAAA,CAAA,EAAW;AAI3C,IAAA,MAAM,IAAI,0CAAA,CAAoB,UAAA,CAAW,IAAA,EAAM;AAAA,MAC7C;AAAA,QACE,IAAA,EAAM,CAAC,CAAA;AAAA,QACP,OAAA,EAAS,CAAA,eAAA,EAAkB,UAAA,CAAW,IAAI,CAAA,wFAAA,CAAA;AAAA,QAC1C,IAAA,EAAM;AAAA,MACR;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACA,EAAA,MAAM,OAAA,EAAS,UAAA,CAAW,cAAA,CAAe,SAAA,CAAU,SAAS,CAAA;AAC5D,EAAA,GAAA,CAAI,CAAC,MAAA,CAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,0CAAA;AAAA,MACR,UAAA,CAAW,IAAA;AAAA,MACX,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAA,GAAA,CAAW;AAAA,QAClC,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAAA,QAC3B,OAAA,EAAS,KAAA,CAAM,OAAA;AAAA,QACf,IAAA,EAAM,KAAA,CAAM;AAAA,MACd,CAAA,CAAE;AAAA,IACJ,CAAA;AAAA,EACF;AACF;AD/CA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,4kGAAC","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/index.cjs","sourcesContent":[null,"import { ActivitySchemaError, UnknownActivityTypeError } from './errors.js';\nimport { getActivityTypeDescriptor } from './registry/index.js';\nimport type { FieldPolicy, Sensitivity } from './registry/registry.js';\n\n/**\n * A learner-safe projection of activity data produced by {@link redact}:\n * the activity's public fields plus the `redacted: true` marker. Renderable\n * and validatable (each built-in type registers a strict redacted schema),\n * but stripped of the answer key, scoring rules, authored feedback, and\n * author-only assets.\n */\nexport interface RedactedActivityData {\n redacted: true;\n schemaVersion: string;\n type: string;\n id: string;\n title: string;\n [key: string]: unknown;\n}\n\n/** Options for {@link redact}. */\nexport interface RedactOptions {\n /**\n * Which sensitivity tiers to keep beyond `public`:\n * - `'none'` (default) — public fields only; the output satisfies the\n * type's strict redacted schema and `assertRedacted`.\n * - `'after-submit'` — public + answer-key fields (for post-submission\n * review renders). `author-only` fields and unclassified fields are\n * STILL removed; the output will NOT pass `assertRedacted`.\n */\n reveal?: 'none' | 'after-submit';\n /**\n * Per-call sensitivity overrides, merged over the type's registered\n * `fieldPolicy` (top-level keys replace; nested objects merge one level).\n *\n * Sensitivity is partly a PEDAGOGICAL decision, not purely a security one —\n * whether a rubric or a hint is learner-visible differs legitimately between\n * deployments — and the SDK must not freeze that choice. Use this to tighten\n * a field the SDK ships as `public`:\n *\n * ```ts\n * redact(essay, { policy: { rubric: 'author-only' } });\n * ```\n *\n * Overrides can only be applied to fields; they cannot re-open a field the\n * caller has not classified, because unclassified still means removed.\n * Note that tightening below what the type's `redactedSchema` requires is\n * allowed — the schema check only rejects payloads that reveal MORE than\n * the learner-safe shape.\n */\n policy?: FieldPolicy;\n}\n\n/** Merges per-call overrides over a registered policy, one level deep. */\nfunction mergePolicy(base: FieldPolicy, overrides: FieldPolicy | undefined): FieldPolicy {\n if (overrides === undefined) {\n return base;\n }\n const merged: Record<string, Sensitivity | FieldPolicy> = { ...base };\n for (const [key, override] of Object.entries(overrides)) {\n const current = merged[key];\n merged[key] =\n typeof override === 'object' && typeof current === 'object'\n ? { ...current, ...override }\n : override;\n }\n return merged;\n}\n\nfunction isSensitivity(value: Sensitivity | FieldPolicy): value is Sensitivity {\n return typeof value === 'string';\n}\n\nfunction keepField(sensitivity: Sensitivity, reveal: 'none' | 'after-submit'): boolean {\n if (sensitivity === 'public') {\n return true;\n }\n return sensitivity === 'answer-key' && reveal === 'after-submit';\n}\n\nfunction redactValue(\n value: unknown,\n policy: FieldPolicy,\n reveal: 'none' | 'after-submit',\n): unknown {\n if (Array.isArray(value)) {\n return value.map((element) => redactValue(element, policy, reveal));\n }\n if (value === null || typeof value !== 'object') {\n // A nested FieldPolicy cannot classify a primitive's sub-fields; the\n // policy author classified an object shape that is not there. Fail\n // closed: drop it (handled by the caller returning undefined).\n return undefined;\n }\n\n const source = value as Record<string, unknown>;\n const output: Record<string, unknown> = {};\n for (const [key, fieldValue] of Object.entries(source)) {\n if (fieldValue === undefined) {\n continue;\n }\n const classification = policy[key];\n if (classification === undefined) {\n // Fail closed: unclassified fields are never emitted, at any reveal\n // level. Adding a field without classifying it hides it — never leaks it.\n continue;\n }\n if (isSensitivity(classification)) {\n if (keepField(classification, reveal)) {\n output[key] = fieldValue;\n }\n continue;\n }\n const nested = redactValue(fieldValue, classification, reveal);\n if (nested !== undefined) {\n output[key] = nested;\n }\n }\n return output;\n}\n\n/**\n * Produces the learner-safe projection of activity data (R7), driven by the\n * `fieldPolicy` registered for `data.type`. Fail-closed and exhaustive by\n * construction: a field the policy does not classify is removed — including\n * unknown passthrough fields — so a NEW field added by a future SDK or a\n * consumer sidecar can never leak through an out-of-date redactor.\n *\n * With the default `reveal: 'none'`, the output validates against the type's\n * strict redacted schema (verified here; an invalid projection throws\n * {@link ActivitySchemaError} rather than shipping an unproven payload).\n *\n * @throws UnknownActivityTypeError when `data.type` is not registered.\n * @throws Error when the registered descriptor declares no `fieldPolicy`\n * (redaction cannot guess sensitivities).\n */\nexport function redact<T extends { type: string }>(\n data: T,\n options: RedactOptions = {},\n): RedactedActivityData {\n const reveal = options.reveal ?? 'none';\n const descriptor = getActivityTypeDescriptor(data.type);\n if (descriptor === undefined) {\n throw new UnknownActivityTypeError(String(data.type));\n }\n if (descriptor.fieldPolicy === undefined) {\n throw new Error(\n `Activity type \"${descriptor.type}\" has no fieldPolicy; redact() cannot run fail-closed redaction without one.`,\n );\n }\n\n const effectivePolicy = mergePolicy(descriptor.fieldPolicy, options.policy);\n const projected = redactValue(data, effectivePolicy, reveal) as Record<string, unknown>;\n const result = { ...projected, redacted: true as const } as RedactedActivityData;\n\n if (reveal === 'none' && descriptor.redactedSchema !== undefined) {\n const parsed = descriptor.redactedSchema.safeParse(result);\n if (!parsed.success) {\n throw new ActivitySchemaError(\n descriptor.type,\n parsed.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n })),\n );\n }\n }\n\n return result;\n}\n\n/**\n * Asserts that `data` is a learner-safe redacted projection: it carries the\n * `redacted: true` marker and, when its type registers a strict redacted\n * schema, validates against it (proving the absence of answer-key fields).\n * Use this at the server boundary before sending activity data to a client\n * that must not hold the key.\n */\nexport function assertRedacted(data: unknown): asserts data is RedactedActivityData {\n if (typeof data !== 'object' || data === null) {\n throw new ActivitySchemaError('unknown', [\n { path: [], message: 'Redacted activity data must be an object.', code: 'invalid_type' },\n ]);\n }\n const candidate = data as Record<string, unknown>;\n if (candidate.redacted !== true) {\n throw new ActivitySchemaError(String(candidate.type ?? 'unknown'), [\n {\n path: ['redacted'],\n message: 'Missing redacted marker — this payload is not a redact() projection.',\n code: 'custom',\n },\n ]);\n }\n const type = typeof candidate.type === 'string' ? candidate.type : '';\n const descriptor = getActivityTypeDescriptor(type);\n if (descriptor === undefined) {\n throw new UnknownActivityTypeError(type);\n }\n if (descriptor.redactedSchema === undefined) {\n // Fail closed: without a registered redacted schema there is no way to\n // PROVE the absence of answer-key fields, and a marker alone proves\n // nothing (any object can carry `redacted: true`).\n throw new ActivitySchemaError(descriptor.type, [\n {\n path: [],\n message: `Activity type \"${descriptor.type}\" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,\n code: 'custom',\n },\n ]);\n }\n const parsed = descriptor.redactedSchema.safeParse(candidate);\n if (!parsed.success) {\n throw new ActivitySchemaError(\n descriptor.type,\n parsed.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n })),\n );\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { V as ValidationError } from './activity-
|
|
2
|
-
export { A as ActivityData, a as ActivityDataMap, b as ActivityFeedback, c as ActivityMedia, d as ActivityResult, e as ActivityType, B as BlankConfig,
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
|
|
1
|
+
import { V as ValidationError, m as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, j as MultipleChoiceLearnerResponse, W as WrittenResponseData, p as WrittenResponseLearnerResponse } from './activity-zdcAMtFB.cjs';
|
|
2
|
+
export { A as ActivityData, a as ActivityDataMap, b as ActivityFeedback, c as ActivityMedia, d as ActivityResult, e as ActivityType, B as BlankConfig, I as InteractionEvent, g as InteractionKind, h as ItemOutcome, L as LearnerResponse, i as LearnerResponseMap, k as MultipleChoiceOption, S as ScoringDetail, l as ScoringOutcome, T as TextMatchPolicy, n as TextMatchResult, o as ValidationResult, q as WrittenResponseRubric, r as WrittenResponseRubricCriterion, X as XAPIActor, s as XAPIConfig, t as XAPIContext, u as XAPIContextActivities, v as XAPIError, w as XAPIObject, x as XAPIResult, y as XAPIScore, z as XAPIStatement, C as XAPIVerbObject, E as levenshteinDistance, G as matchText } from './activity-zdcAMtFB.cjs';
|
|
3
|
+
import { z } from 'zod/v4';
|
|
4
|
+
export { BlankConfigSchema, FeedbackSchema, FillInTheBlanksDataSchema, MediaSchema, MediaUrlSchema, MultipleChoiceDataSchema, MultipleChoiceOptionSchema, RedactedBlankConfigSchema, RedactedFillInTheBlanksDataSchema, RedactedMultipleChoiceDataSchema, RedactedMultipleChoiceOptionSchema, RedactedWrittenResponseDataSchema, TextMatchPolicySchema, WrittenResponseDataSchema, WrittenResponseRubricCriterionSchema, WrittenResponseRubricSchema, fillInTheBlanksJsonSchema, jsonSchemaFor, multipleChoiceJsonSchema, validateActivity, writtenResponseJsonSchema } from './schemas.cjs';
|
|
5
|
+
export { DEFAULT_PASS_THRESHOLD, computePassThreshold, evaluate, score } from './scoring.cjs';
|
|
6
|
+
export { AnsweredStatementParams, CompletedStatementParams, SubmittedStatementParams, XAPIObjectParams, XAPIStatementParams, XAPIVerb, XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder } from './xapi.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Canonical word counter for written-response bounds (Req 22.9): tokens are
|
|
10
|
+
* maximal runs of non-whitespace (split on `\s+`), so hyphenated forms
|
|
11
|
+
* (`well-known`) count as one word. The empty / whitespace-only string counts
|
|
12
|
+
* 0. Consumers must use this helper rather than re-implementing the split so
|
|
13
|
+
* client previews, SDK scoring, and stored `wordCount` values always agree.
|
|
14
|
+
*/
|
|
15
|
+
declare function countWords(text: string): number;
|
|
7
16
|
|
|
8
17
|
/** Thrown when activity data fails schema validation at a component boundary. */
|
|
9
18
|
declare class ActivitySchemaError extends Error {
|
|
@@ -16,6 +25,243 @@ declare class UnknownActivityTypeError extends Error {
|
|
|
16
25
|
readonly activityType: string;
|
|
17
26
|
constructor(activityType: string);
|
|
18
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Thrown when `score()` is asked to grade a `redact()` projection (or any
|
|
30
|
+
* activity data whose answer key is missing, yielding a non-finite score).
|
|
31
|
+
* Redacted data is learner-safe precisely because the key was removed, so a
|
|
32
|
+
* score derived from it is meaningless — previously this produced a silent
|
|
33
|
+
* `NaN` that serialized to `null` in a grade column. `evaluate()` returns
|
|
34
|
+
* `{ status: 'unscorable' }` for the same input instead of throwing.
|
|
35
|
+
*/
|
|
36
|
+
declare class RedactedScoringError extends Error {
|
|
37
|
+
readonly activityType: string;
|
|
38
|
+
constructor(activityType: string);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Thrown when `score()` is called for an activity type whose grading is
|
|
42
|
+
* deferred (asynchronous AI/human grading, e.g. `written-response`). A
|
|
43
|
+
* deferred submission has no synchronous score — treating it as 0 would show
|
|
44
|
+
* a learner a failing grade for work that simply has not been graded yet.
|
|
45
|
+
* Call `evaluate()` instead, which returns `{ status: 'deferred', ... }`.
|
|
46
|
+
*/
|
|
47
|
+
declare class DeferredScoringError extends Error {
|
|
48
|
+
readonly activityType: string;
|
|
49
|
+
constructor(activityType: string);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** ScoringResult without `passed` — the public `score()` / `evaluate()` fill that in. */
|
|
53
|
+
type PartialScoringResult = Omit<ScoringResult, 'passed'>;
|
|
54
|
+
/**
|
|
55
|
+
* Sensitivity classification of a single activity-data field, driving
|
|
56
|
+
* `redact()`:
|
|
57
|
+
* - `public` — safe to send to a learner before they answer.
|
|
58
|
+
* - `answer-key` — reveals (or helps infer) the correct answer or the scoring
|
|
59
|
+
* rules; removed unless `reveal: 'after-submit'` is requested.
|
|
60
|
+
* - `author-only` — never leaves the authoring/grading context (e.g. rubrics).
|
|
61
|
+
*/
|
|
62
|
+
type Sensitivity = 'public' | 'answer-key' | 'author-only';
|
|
63
|
+
/**
|
|
64
|
+
* Per-field sensitivity map for an activity type. A `Sensitivity` value
|
|
65
|
+
* classifies the whole field (objects and arrays included); a nested
|
|
66
|
+
* `FieldPolicy` recurses into an object field — and, for an array field,
|
|
67
|
+
* applies to every element. Fail-closed: any field a policy does not mention
|
|
68
|
+
* is treated as `author-only` and removed by `redact()` — adding a field
|
|
69
|
+
* without classifying it hides it, never leaks it.
|
|
70
|
+
*/
|
|
71
|
+
interface FieldPolicy {
|
|
72
|
+
readonly [field: string]: Sensitivity | FieldPolicy;
|
|
73
|
+
}
|
|
74
|
+
/** xAPI interaction types defined by xAPI 1.0.3 (cmi.interaction vocabulary). */
|
|
75
|
+
type XAPIInteractionType = 'choice' | 'fill-in' | 'long-fill-in' | 'matching' | 'sequencing' | 'performance' | 'true-false' | 'other';
|
|
76
|
+
/** Interop facts a generic statement builder cannot infer from data alone. */
|
|
77
|
+
interface ActivityTypeInterop<TData> {
|
|
78
|
+
/** IRI for the xAPI Activity `definition.type`. */
|
|
79
|
+
readonly xapiActivityTypeIri?: string;
|
|
80
|
+
/** xAPI `definition.interactionType` for this activity type. */
|
|
81
|
+
readonly xapiInteractionType?: XAPIInteractionType;
|
|
82
|
+
/** Builds the xAPI `correctResponsesPattern` strings for an item. */
|
|
83
|
+
readonly correctResponsesPattern?: (data: TData) => string[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* How responses to an activity type are graded:
|
|
87
|
+
* - `sync` — a pure function produces the grade at submit time.
|
|
88
|
+
* - `deferred` — grading happens asynchronously (AI or human) after
|
|
89
|
+
* submission; `partial` reports the facts computable synchronously
|
|
90
|
+
* (e.g. word counts), surfaced in `ItemOutcome.partial`.
|
|
91
|
+
*/
|
|
92
|
+
type ActivityTypeScoring<TData, TResponse> = {
|
|
93
|
+
readonly kind: 'sync';
|
|
94
|
+
readonly score: (data: TData, response: TResponse) => PartialScoringResult;
|
|
95
|
+
} | {
|
|
96
|
+
readonly kind: 'deferred';
|
|
97
|
+
readonly reason: 'requires_async_grading';
|
|
98
|
+
readonly partial?: (data: TData, response: TResponse | undefined) => DeferredScoringPartial;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* A value-level description of an activity type: its contract (schema), its
|
|
102
|
+
* grading, its redaction policy, and its interop facts. Registering a
|
|
103
|
+
* descriptor makes `validateActivity`, `score`, `evaluate`, `redact`, and
|
|
104
|
+
* `jsonSchemaFor` work for the type — an activity type is a value, not a
|
|
105
|
+
* hardcoded union member (R1).
|
|
106
|
+
*/
|
|
107
|
+
interface ActivityTypeDescriptor<TData extends {
|
|
108
|
+
type: string;
|
|
109
|
+
}, TResponse> {
|
|
110
|
+
/** The `type` discriminator string (kebab-case by convention). */
|
|
111
|
+
readonly type: TData['type'];
|
|
112
|
+
/** Zod schema validating the activity's data contract. */
|
|
113
|
+
readonly schema: z.ZodType<TData>;
|
|
114
|
+
/** How responses are graded. */
|
|
115
|
+
readonly scoring: ActivityTypeScoring<TData, TResponse>;
|
|
116
|
+
/** Whether a response counts as an answer (vs. blank/untouched). */
|
|
117
|
+
readonly isAnswered?: (response: TResponse | undefined) => boolean;
|
|
118
|
+
/** Per-field sensitivity map driving `redact()`. Fail-closed. */
|
|
119
|
+
readonly fieldPolicy?: FieldPolicy;
|
|
120
|
+
/**
|
|
121
|
+
* Schema the output of `redact(data)` (with default `reveal: 'none'`) must
|
|
122
|
+
* satisfy. Strict by design: it proves the ABSENCE of answer-key fields,
|
|
123
|
+
* so `assertRedacted` can guarantee a payload is safe to send to a learner.
|
|
124
|
+
*/
|
|
125
|
+
readonly redactedSchema?: z.ZodType<unknown>;
|
|
126
|
+
/** Interop facts for xAPI (and later QTI) statement building. */
|
|
127
|
+
readonly interop?: ActivityTypeInterop<TData>;
|
|
128
|
+
/** The interaction-event kinds components for this type emit. */
|
|
129
|
+
readonly interactions?: readonly string[];
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Internal type-erased descriptor shape stored in the registry. Dispatch call
|
|
133
|
+
* sites cast payloads back; the public generic API preserves inference.
|
|
134
|
+
*/
|
|
135
|
+
interface RegisteredActivityTypeDescriptor {
|
|
136
|
+
readonly type: string;
|
|
137
|
+
readonly schema: z.ZodType<unknown>;
|
|
138
|
+
readonly scoring: {
|
|
139
|
+
readonly kind: 'sync';
|
|
140
|
+
readonly score: (data: unknown, response: unknown) => PartialScoringResult;
|
|
141
|
+
} | {
|
|
142
|
+
readonly kind: 'deferred';
|
|
143
|
+
readonly reason: 'requires_async_grading';
|
|
144
|
+
readonly partial?: (data: unknown, response: unknown) => DeferredScoringPartial;
|
|
145
|
+
};
|
|
146
|
+
readonly isAnswered?: (response: unknown) => boolean;
|
|
147
|
+
readonly fieldPolicy?: FieldPolicy;
|
|
148
|
+
readonly redactedSchema?: z.ZodType<unknown>;
|
|
149
|
+
readonly interop?: ActivityTypeInterop<unknown>;
|
|
150
|
+
readonly interactions?: readonly string[];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Identity helper that gives full type inference when authoring a descriptor:
|
|
154
|
+
*
|
|
155
|
+
* ```ts
|
|
156
|
+
* const myType = defineActivityType<MyTypeData, MyTypeLearnerResponse>({ ... });
|
|
157
|
+
* registerActivityType(myType);
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
declare function defineActivityType<TData extends {
|
|
161
|
+
type: string;
|
|
162
|
+
}, TResponse>(descriptor: ActivityTypeDescriptor<TData, TResponse>): ActivityTypeDescriptor<TData, TResponse>;
|
|
163
|
+
/**
|
|
164
|
+
* Registers an activity type on the default registry, making it live for
|
|
165
|
+
* `validateActivity`, `score`, `evaluate`, `redact`, and `jsonSchemaFor`.
|
|
166
|
+
* Re-registering the same descriptor object is a no-op; registering a
|
|
167
|
+
* DIFFERENT descriptor under an existing type throws — silently replacing a
|
|
168
|
+
* type's contract or scoring is exactly the class of accident a summative
|
|
169
|
+
* SDK must not allow.
|
|
170
|
+
*/
|
|
171
|
+
declare function registerActivityType<TData extends {
|
|
172
|
+
type: string;
|
|
173
|
+
}, TResponse>(descriptor: ActivityTypeDescriptor<TData, TResponse>): void;
|
|
174
|
+
/** Returns the registered descriptor for `type`, or `undefined`. */
|
|
175
|
+
declare function getActivityTypeDescriptor(type: string): RegisteredActivityTypeDescriptor | undefined;
|
|
176
|
+
/** The type strings currently registered (built-ins plus consumer-registered). */
|
|
177
|
+
declare function registeredActivityTypes(): string[];
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* A learner-safe projection of activity data produced by {@link redact}:
|
|
181
|
+
* the activity's public fields plus the `redacted: true` marker. Renderable
|
|
182
|
+
* and validatable (each built-in type registers a strict redacted schema),
|
|
183
|
+
* but stripped of the answer key, scoring rules, authored feedback, and
|
|
184
|
+
* author-only assets.
|
|
185
|
+
*/
|
|
186
|
+
interface RedactedActivityData {
|
|
187
|
+
redacted: true;
|
|
188
|
+
schemaVersion: string;
|
|
189
|
+
type: string;
|
|
190
|
+
id: string;
|
|
191
|
+
title: string;
|
|
192
|
+
[key: string]: unknown;
|
|
193
|
+
}
|
|
194
|
+
/** Options for {@link redact}. */
|
|
195
|
+
interface RedactOptions {
|
|
196
|
+
/**
|
|
197
|
+
* Which sensitivity tiers to keep beyond `public`:
|
|
198
|
+
* - `'none'` (default) — public fields only; the output satisfies the
|
|
199
|
+
* type's strict redacted schema and `assertRedacted`.
|
|
200
|
+
* - `'after-submit'` — public + answer-key fields (for post-submission
|
|
201
|
+
* review renders). `author-only` fields and unclassified fields are
|
|
202
|
+
* STILL removed; the output will NOT pass `assertRedacted`.
|
|
203
|
+
*/
|
|
204
|
+
reveal?: 'none' | 'after-submit';
|
|
205
|
+
/**
|
|
206
|
+
* Per-call sensitivity overrides, merged over the type's registered
|
|
207
|
+
* `fieldPolicy` (top-level keys replace; nested objects merge one level).
|
|
208
|
+
*
|
|
209
|
+
* Sensitivity is partly a PEDAGOGICAL decision, not purely a security one —
|
|
210
|
+
* whether a rubric or a hint is learner-visible differs legitimately between
|
|
211
|
+
* deployments — and the SDK must not freeze that choice. Use this to tighten
|
|
212
|
+
* a field the SDK ships as `public`:
|
|
213
|
+
*
|
|
214
|
+
* ```ts
|
|
215
|
+
* redact(essay, { policy: { rubric: 'author-only' } });
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* Overrides can only be applied to fields; they cannot re-open a field the
|
|
219
|
+
* caller has not classified, because unclassified still means removed.
|
|
220
|
+
* Note that tightening below what the type's `redactedSchema` requires is
|
|
221
|
+
* allowed — the schema check only rejects payloads that reveal MORE than
|
|
222
|
+
* the learner-safe shape.
|
|
223
|
+
*/
|
|
224
|
+
policy?: FieldPolicy;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Produces the learner-safe projection of activity data (R7), driven by the
|
|
228
|
+
* `fieldPolicy` registered for `data.type`. Fail-closed and exhaustive by
|
|
229
|
+
* construction: a field the policy does not classify is removed — including
|
|
230
|
+
* unknown passthrough fields — so a NEW field added by a future SDK or a
|
|
231
|
+
* consumer sidecar can never leak through an out-of-date redactor.
|
|
232
|
+
*
|
|
233
|
+
* With the default `reveal: 'none'`, the output validates against the type's
|
|
234
|
+
* strict redacted schema (verified here; an invalid projection throws
|
|
235
|
+
* {@link ActivitySchemaError} rather than shipping an unproven payload).
|
|
236
|
+
*
|
|
237
|
+
* @throws UnknownActivityTypeError when `data.type` is not registered.
|
|
238
|
+
* @throws Error when the registered descriptor declares no `fieldPolicy`
|
|
239
|
+
* (redaction cannot guess sensitivities).
|
|
240
|
+
*/
|
|
241
|
+
declare function redact<T extends {
|
|
242
|
+
type: string;
|
|
243
|
+
}>(data: T, options?: RedactOptions): RedactedActivityData;
|
|
244
|
+
/**
|
|
245
|
+
* Asserts that `data` is a learner-safe redacted projection: it carries the
|
|
246
|
+
* `redacted: true` marker and, when its type registers a strict redacted
|
|
247
|
+
* schema, validates against it (proving the absence of answer-key fields).
|
|
248
|
+
* Use this at the server boundary before sending activity data to a client
|
|
249
|
+
* that must not hold the key.
|
|
250
|
+
*/
|
|
251
|
+
declare function assertRedacted(data: unknown): asserts data is RedactedActivityData;
|
|
252
|
+
|
|
253
|
+
/** Built-in Multiple Choice descriptor. */
|
|
254
|
+
declare const multipleChoiceType: ActivityTypeDescriptor<MultipleChoiceData, MultipleChoiceLearnerResponse>;
|
|
255
|
+
/** Built-in Fill-in-the-Blanks descriptor. */
|
|
256
|
+
declare const fillInTheBlanksType: ActivityTypeDescriptor<FillInTheBlanksData, FillInTheBlanksLearnerResponse>;
|
|
257
|
+
/**
|
|
258
|
+
* Built-in Written Response descriptor. Grading is DEFERRED: submissions are
|
|
259
|
+
* graded asynchronously (AI or human) by the consumer; the synchronous
|
|
260
|
+
* outcome reports only word-count facts. `wordCount` is recomputed from the
|
|
261
|
+
* submitted text with the canonical `countWords()` — the client-supplied
|
|
262
|
+
* count is informational, never trusted.
|
|
263
|
+
*/
|
|
264
|
+
declare const writtenResponseType: ActivityTypeDescriptor<WrittenResponseData, WrittenResponseLearnerResponse>;
|
|
19
265
|
|
|
20
266
|
/**
|
|
21
267
|
* All CSS custom property tokens consumed by learning-kit components.
|
|
@@ -53,4 +299,4 @@ interface ThemeTokens {
|
|
|
53
299
|
'--lk-transition-base': string;
|
|
54
300
|
}
|
|
55
301
|
|
|
56
|
-
export { ActivitySchemaError, type ThemeTokens, UnknownActivityTypeError, ValidationError };
|
|
302
|
+
export { ActivitySchemaError, type ActivityTypeDescriptor, type ActivityTypeInterop, type ActivityTypeScoring, DeferredScoringError, DeferredScoringPartial, type FieldPolicy, FillInTheBlanksData, FillInTheBlanksLearnerResponse, MultipleChoiceData, MultipleChoiceLearnerResponse, type PartialScoringResult, type RedactOptions, type RedactedActivityData, RedactedScoringError, type RegisteredActivityTypeDescriptor, ScoringResult, type Sensitivity, type ThemeTokens, UnknownActivityTypeError, ValidationError, WrittenResponseData, WrittenResponseLearnerResponse, type XAPIInteractionType, assertRedacted, countWords, defineActivityType, fillInTheBlanksType, getActivityTypeDescriptor, multipleChoiceType, redact, registerActivityType, registeredActivityTypes, writtenResponseType };
|