@intellectif/lk-core 0.3.0 → 0.4.0
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 → activity-wkzRemHx.d.cts} +113 -1
- package/dist/{activity-zdcAMtFB.d.ts → activity-wkzRemHx.d.ts} +113 -1
- package/dist/chunk-5ZAW76F3.cjs +334 -0
- package/dist/chunk-5ZAW76F3.cjs.map +1 -0
- package/dist/chunk-A6JXV5GP.js +334 -0
- package/dist/chunk-A6JXV5GP.js.map +1 -0
- package/dist/{chunk-HS7BYCGE.js → chunk-APDLWLYD.js} +11 -3
- package/dist/chunk-APDLWLYD.js.map +1 -0
- package/dist/{chunk-RUGIOQZY.cjs → chunk-RUZ52Q7A.cjs} +11 -3
- package/dist/chunk-RUZ52Q7A.cjs.map +1 -0
- package/dist/index.cjs +17 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -4
- package/dist/index.d.ts +50 -4
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.cts +3 -3
- package/dist/schemas.d.ts +3 -3
- package/dist/scoring.cjs +10 -2
- package/dist/scoring.cjs.map +1 -1
- package/dist/scoring.d.cts +190 -3
- package/dist/scoring.d.ts +190 -3
- package/dist/scoring.js +9 -1
- package/dist/xapi.cjs +2 -2
- package/dist/xapi.d.cts +8 -1
- package/dist/xapi.d.ts +8 -1
- package/dist/xapi.js +1 -1
- package/package.json +37 -15
- package/dist/chunk-HS7BYCGE.js.map +0 -1
- package/dist/chunk-QSVBYTNM.js +0 -94
- package/dist/chunk-QSVBYTNM.js.map +0 -1
- package/dist/chunk-RUGIOQZY.cjs.map +0 -1
- package/dist/chunk-THSZMZND.cjs +0 -94
- package/dist/chunk-THSZMZND.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-RUZ52Q7A.cjs","../src/xapi/validators.ts","../src/xapi/verbs.ts","../src/xapi/builder.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;ACJA,4BAAkB;AAKlB,IAAM,QAAA,EAAU,wEAAA;AAEhB,IAAM,IAAA,EAAM,sBAAA;AAEZ,IAAM,QAAA,EAAU,KAAA,CAAE,MAAA,CAAO,KAAA,CAAE,MAAA,CAAO,CAAA,EAAG,KAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAC/C,IAAM,WAAA,EAAa,KAAA,CAAE,MAAA,CAAO,KAAA,CAAE,MAAA,CAAO,CAAA,EAAG,KAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAEnD,IAAM,YAAA,EAAc,KAAA,CACjB,MAAA,CAAO;AAAA,EACN,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,EAC7B,IAAA,EAAM,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,EAC1B,IAAA,EAAM,KAAA,CACH,MAAA,CAAO,CAAA,CACP,KAAA,CAAM,UAAA,EAAY,2BAA2B,CAAA,CAC7C,QAAA,CAAS,CAAA;AAAA,EACZ,OAAA,EAAS,KAAA,CAAE,MAAA,CAAO,EAAE,QAAA,EAAU,KAAA,CAAE,MAAA,CAAO,CAAA,EAAG,IAAA,EAAM,KAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAA,CAAE,QAAA,CAAS;AACzE,CAAC,CAAA,CACA,MAAA,CAAO,CAAC,KAAA,EAAA,GAAU,KAAA,CAAM,KAAA,IAAS,KAAA,EAAA,GAAa,KAAA,CAAM,QAAA,IAAY,KAAA,CAAA,EAAW;AAAA,EAC1E,KAAA,EAAO;AACT,CAAC,CAAA;AAEH,IAAM,gBAAA,EAAkB,KAAA,CAAE,MAAA,CAAO;AAAA,EAC/B,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,KAAA,CAAM,OAAA,EAAS,sBAAsB,CAAA;AAAA,EACpD,KAAA,EAAO,WAAA;AAAA,EACP,IAAA,EAAM,KAAA,CAAE,MAAA,CAAO;AAAA,IACb,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,KAAA,CAAM,GAAA,EAAK,wBAAwB,CAAA;AAAA,IAClD,OAAA,EAAS;AAAA,EACX,CAAC,CAAA;AAAA,EACD,MAAA,EAAQ,KAAA,CAAE,MAAA,CAAO;AAAA,IACf,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,UAAU,CAAA;AAAA,IAChC,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,KAAA,CAAM,GAAA,EAAK,0BAA0B,CAAA;AAAA,IACpD,UAAA,EAAY,KAAA,CACT,MAAA,CAAO;AAAA,MACN,IAAA,EAAM,OAAA,CAAQ,QAAA,CAAS,CAAA;AAAA,MACvB,WAAA,EAAa,OAAA,CAAQ,QAAA,CAAS,CAAA;AAAA,MAC9B,IAAA,EAAM,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,MAC1B,eAAA,EAAiB,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,MACrC,uBAAA,EAAyB,KAAA,CAAE,KAAA,CAAM,KAAA,CAAE,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,MACtD,OAAA,EAAS,KAAA,CAAE,KAAA,CAAM,KAAA,CAAE,MAAA,CAAO,EAAE,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,CAAA,EAAG,WAAA,EAAa,OAAA,CAAQ,QAAA,CAAS,EAAE,CAAC,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,MACzF,UAAA,EAAY,UAAA,CAAW,QAAA,CAAS;AAAA,IAClC,CAAC,CAAA,CACA,QAAA,CAAS;AAAA,EACd,CAAC,CAAA;AAAA,EACD,MAAA,EAAQ,KAAA,CACL,MAAA,CAAO;AAAA;AAAA,IAEN,KAAA,EAAO,KAAA,CACJ,MAAA,CAAO;AAAA,MACN,MAAA,EAAQ,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,GAAA,CAAI,CAAA,CAAE,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA;AAAA,MAChC,GAAA,EAAK,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,MACzB,GAAA,EAAK,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,MACzB,GAAA,EAAK,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS;AAAA,IAC3B,CAAC,CAAA,CACA,QAAA,CAAS,CAAA;AAAA,IACZ,OAAA,EAAS,KAAA,CAAE,OAAA,CAAQ,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,IAC9B,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,IACjC,QAAA,EAAU,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,KAAA,CAAM,IAAA,EAAM,uCAAuC,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,IACnF,QAAA,EAAU,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,IAC9B,UAAA,EAAY,UAAA,CAAW,QAAA,CAAS;AAAA,EAClC,CAAC,CAAA,CACA,QAAA,CAAS,CAAA;AAAA,EACZ,OAAA,EAAS,KAAA,CACN,MAAA,CAAO;AAAA,IACN,QAAA,EAAU,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,IAC9B,QAAA,EAAU,KAAA,CAAE,MAAA,CAAO,CAAA,CAAE,QAAA,CAAS,CAAA;AAAA,IAC9B,iBAAA,EAAmB,KAAA,CAChB,MAAA,CAAO;AAAA,MACN,MAAA,EAAQ,KAAA,CACL,KAAA,CAAM,KAAA,CAAE,MAAA,CAAO,EAAE,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,UAAU,CAAA,EAAG,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA,CACrE,QAAA,CAAS,CAAA;AAAA,MACZ,QAAA,EAAU,KAAA,CACP,KAAA,CAAM,KAAA,CAAE,MAAA,CAAO,EAAE,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,UAAU,CAAA,EAAG,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA,CACrE,QAAA,CAAS,CAAA;AAAA,MACZ,QAAA,EAAU,KAAA,CACP,KAAA,CAAM,KAAA,CAAE,MAAA,CAAO,EAAE,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,UAAU,CAAA,EAAG,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA,CACrE,QAAA,CAAS,CAAA;AAAA,MACZ,KAAA,EAAO,KAAA,CACJ,KAAA,CAAM,KAAA,CAAE,MAAA,CAAO,EAAE,UAAA,EAAY,KAAA,CAAE,OAAA,CAAQ,UAAU,CAAA,EAAG,EAAA,EAAI,KAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAC,CAAA,CACrE,QAAA,CAAS;AAAA,IACd,CAAC,CAAA,CACA,QAAA,CAAS,CAAA;AAAA,IACZ,UAAA,EAAY,UAAA,CAAW,QAAA,CAAS;AAAA,EAClC,CAAC,CAAA,CACA,QAAA,CAAS,CAAA;AAAA,EACZ,SAAA,EAAW,KAAA,CACR,MAAA,CAAO,CAAA,CACP,MAAA,CAAO,CAAC,KAAA,EAAA,GAAU,CAAC,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA,EAAG,4BAA4B,CAAA;AAAA,EACnF,OAAA,EAAS,KAAA,CAAE,OAAA,CAAQ,OAAO;AAC5B,CAAC,CAAA;AAGD,SAAS,YAAA,CAAA,EAAwB;AAC/B,EAAA,MAAM,EAAA,EAAI,UAAA;AACV,EAAA,uBAAO,CAAA,mBAAE,OAAA,6BAAS,GAAA,6BAAK,WAAA,IAAa,YAAA;AACtC;AAeO,SAAS,qBAAA,CAAsB,SAAA,EAAgC;AACpE,EAAA,MAAM,OAAA,EAAS,eAAA,CAAgB,SAAA,CAAU,SAAS,CAAA;AAClD,EAAA,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS;AAClB,IAAA,MAAA;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,EAA4B,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAA,GAAA,CAAW;AAAA,IACpE,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAAA,IAC3B,OAAA,EAAS,KAAA,CAAM,OAAA;AAAA,IACf,IAAA,EAAM,KAAA,CAAM;AAAA,EACd,CAAA,CAAE,CAAA;AAEF,EAAA,GAAA,CAAI,YAAA,CAAa,CAAA,EAAG;AAClB,IAAA,OAAA,CAAQ,IAAA,CAAK,sDAAA,EAAwD,MAAM,CAAA;AAC3E,IAAA,MAAA;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,0CAAA,CAAoB,eAAA,EAAiB,MAAM,CAAA;AACvD;AD9CA;AACA;AEnFO,IAAM,SAAA,EAAW;AAAA,EACtB,QAAA,EAAU,yCAAA;AAAA,EACV,SAAA,EAAW,0CAAA;AAAA,EACX,WAAA,EAAa,4CAAA;AAAA,EACb,UAAA,EAAY,2CAAA;AAAA,EACZ,SAAA,EAAW,0CAAA;AAAA,EACX,MAAA,EAAQ,uCAAA;AAAA,EACR,MAAA,EAAQ,uCAAA;AAAA,EACR,OAAA,EAAS,2CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,SAAA,EAAW,2CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOX,MAAA,EAAQ;AACV,CAAA;AASO,IAAM,kBAAA,EAAiE;AAAA,EAC5E,QAAA,EAAU,EAAE,OAAA,EAAS,WAAW,CAAA;AAAA,EAChC,SAAA,EAAW,EAAE,OAAA,EAAS,YAAY,CAAA;AAAA,EAClC,WAAA,EAAa,EAAE,OAAA,EAAS,cAAc,CAAA;AAAA,EACtC,UAAA,EAAY,EAAE,OAAA,EAAS,aAAa,CAAA;AAAA,EACpC,SAAA,EAAW,EAAE,OAAA,EAAS,YAAY,CAAA;AAAA,EAClC,MAAA,EAAQ,EAAE,OAAA,EAAS,SAAS,CAAA;AAAA,EAC5B,MAAA,EAAQ,EAAE,OAAA,EAAS,SAAS,CAAA;AAAA,EAC5B,OAAA,EAAS,EAAE,OAAA,EAAS,UAAU,CAAA;AAAA,EAC9B,SAAA,EAAW,EAAE,OAAA,EAAS,YAAY,CAAA;AAAA,EAClC,MAAA,EAAQ,EAAE,OAAA,EAAS,SAAS;AAC9B,CAAA;AF6EA;AACA;AG9CA,SAAS,eAAA,CAAgB,EAAA,EAAoB;AAC3C,EAAA,OAAO,CAAA,EAAA,EAAA,CAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAE,EAAA,EAAI,EAAE,EAAA,EAAI,GAAA,CAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACjE;AASA,SAAS,MAAA,CAAA,EAAiB;AACxB,EAAA,MAAM,EAAA,EACJ,UAAA,CAGA,MAAA;AACF,EAAA,GAAA,iBAAI,CAAA,6BAAG,YAAA,EAAY;AACjB,IAAA,OAAO,CAAA,CAAE,UAAA,CAAW,CAAA;AAAA,EACtB;AACA,EAAA,MAAM,MAAA,EAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,GAAA,iBAAI,CAAA,6BAAG,iBAAA,EAAiB;AACtB,IAAA,CAAA,CAAE,eAAA,CAAgB,KAAK,CAAA;AAAA,EACzB,EAAA,KAAO;AACL,IAAA,IAAA,CAAA,IAAS,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,EAAA,EAAI,EAAA,GAAK,CAAA,EAAG;AAC9B,MAAA,KAAA,CAAM,CAAC,EAAA,EAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,EAAA,EAAI,GAAG,CAAA;AAAA,IAC3C;AAAA,EACF;AACA,EAAA,KAAA,CAAM,CAAC,EAAA,EAAM,KAAA,CAAM,CAAC,EAAA,EAAe,GAAA,EAAQ,EAAA;AAC3C,EAAA,KAAA,CAAM,CAAC,EAAA,EAAM,KAAA,CAAM,CAAC,EAAA,EAAe,GAAA,EAAQ,GAAA;AAC3C,EAAA,MAAM,IAAA,EAAM,CAAC,GAAG,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC1E,EAAA,OAAO,CAAA,EAAA;AACT;AAGS;AACD,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAGA,IAAA;AACN,EAAA;AACO,EAAA;AACL,IAAA;AACI,IAAA;AACA,IAAA;AACN,EAAA;AACF;AAMS;AAMA,EAAA;AACL,IAAA;AACA,IAAA;AACI,IAAA;AAEE,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AAED,IAAA;AACD,IAAA;AACA,IAAA;AACN,EAAA;AACF;AAOa;AACX,EAAA;AACQ,IAAA;AACA,MAAA;AACJ,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACI,MAAA;AACA,MAAA;AACJ,MAAA;AACA,MAAA;AACF,IAAA;AAGA,IAAA;AACA,IAAA;AACF,EAAA;AAEA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AAEA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AACF;AHSU;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-RUZ52Q7A.cjs","sourcesContent":[null,"import { z } from 'zod/v4';\nimport { ActivitySchemaError } from '../errors.js';\nimport type { ValidationError } from '../types/activity.js';\nimport type { XAPIStatement } from '../types/xapi.js';\n\nconst UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n// Minimal IRI/URI check: a scheme followed by ':'.\nconst IRI = /^[a-z][a-z0-9+.-]*:/i;\n\nconst langMap = z.record(z.string(), z.string());\nconst extensions = z.record(z.string(), z.unknown());\n\nconst actorSchema = z\n .object({\n objectType: z.literal('Agent'),\n name: z.string().optional(),\n mbox: z\n .string()\n .regex(/^mailto:/, 'mbox must be a mailto IRI')\n .optional(),\n account: z.object({ homePage: z.string(), name: z.string() }).optional(),\n })\n .refine((actor) => actor.mbox !== undefined || actor.account !== undefined, {\n error: 'actor must be identified by an mbox or an account',\n });\n\nconst statementSchema = z.object({\n id: z.string().regex(UUID_V4, 'id must be a UUID v4'),\n actor: actorSchema,\n verb: z.object({\n id: z.string().regex(IRI, 'verb.id must be an IRI'),\n display: langMap,\n }),\n object: z.object({\n objectType: z.literal('Activity'),\n id: z.string().regex(IRI, 'object.id must be an IRI'),\n definition: z\n .object({\n name: langMap.optional(),\n description: langMap.optional(),\n type: z.string().optional(),\n interactionType: z.string().optional(),\n correctResponsesPattern: z.array(z.string()).optional(),\n choices: z.array(z.object({ id: z.string(), description: langMap.optional() })).optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n }),\n result: z\n .object({\n // xAPI 1.0.3 permits scaled in [-1, 1]; the SDK only emits [0, 1].\n score: z\n .object({\n scaled: z.number().min(-1).max(1),\n raw: z.number().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .optional(),\n success: z.boolean().optional(),\n completion: z.boolean().optional(),\n duration: z.string().regex(/^P/, 'duration must be an ISO 8601 duration').optional(),\n response: z.string().optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n context: z\n .object({\n platform: z.string().optional(),\n language: z.string().optional(),\n contextActivities: z\n .object({\n parent: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n grouping: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n category: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n other: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n })\n .optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n timestamp: z\n .string()\n .refine((value) => !Number.isNaN(Date.parse(value)), 'timestamp must be ISO 8601'),\n version: z.literal('1.0.3'),\n});\n\n/** True when running under `NODE_ENV=production`, safe in any environment. */\nfunction isProduction(): boolean {\n const g = globalThis as { process?: { env?: Record<string, string | undefined> } };\n return g.process?.env?.NODE_ENV === 'production';\n}\n\n/**\n * Validates a constructed {@link XAPIStatement} against the xAPI 1.0.3\n * structural contract.\n *\n * In development a structural failure throws (caught early); in production it\n * logs a warning and returns (the statement is still sent — see the design's\n * Error Handling table). Uses a `zod/v4` schema rather than `ajv` + an\n * external JSON Schema to keep `lk-core` dependency-free.\n *\n * NOTE: `ActivitySchemaError` is reused here per the task spec; its\n * `activityType` field carries the sentinel `'xAPIStatement'`. A dedicated\n * `XAPIValidationError` would be semantically cleaner — flagged for review.\n */\nexport function validateXAPIStatement(statement: XAPIStatement): void {\n const result = statementSchema.safeParse(statement);\n if (result.success) {\n return;\n }\n\n const errors: ValidationError[] = result.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n }));\n\n if (isProduction()) {\n console.warn('[learning-kit] Invalid xAPI statement (sent anyway):', errors);\n return;\n }\n\n throw new ActivitySchemaError('xAPIStatement', errors);\n}\n","/**\n * The set of xAPI verbs emitted by SDK activities, keyed by a stable\n * identifier mapped to its canonical xAPI verb IRI (xAPI 1.0.3 / ADL registry).\n */\nexport const XAPIVerb = {\n ANSWERED: 'http://adlnet.gov/expapi/verbs/answered',\n COMPLETED: 'http://adlnet.gov/expapi/verbs/completed',\n EXPERIENCED: 'http://adlnet.gov/expapi/verbs/experienced',\n INTERACTED: 'http://adlnet.gov/expapi/verbs/interacted',\n ATTEMPTED: 'http://adlnet.gov/expapi/verbs/attempted',\n PASSED: 'http://adlnet.gov/expapi/verbs/passed',\n FAILED: 'http://adlnet.gov/expapi/verbs/failed',\n WATCHED: 'https://w3id.org/xapi/video/verbs/watched',\n /**\n * Emitted for deferred-grading submissions (e.g. written-response): the\n * learner has submitted work whose grade does not exist yet, so `answered`\n * (which implies a scored response) would be wrong. xAPI 1.0.3 defines no\n * canonical \"submit\" verb; the Activity Streams 1.0 IRI is the established\n * community choice (design decision recorded per Task 25.4).\n */\n SUBMITTED: 'http://activitystrea.ms/schema/1.0/submit',\n /**\n * Emitted when an asynchronous grader produces a grade for work that was\n * previously only SUBMITTED. Distinct from `answered`, which asserts the\n * grade existed at submission time — here the learner acted earlier and the\n * grade arrived later, often from a different actor (an AI or a teacher).\n */\n SCORED: 'http://adlnet.gov/expapi/verbs/scored',\n} as const;\n\n/** Union of the valid `XAPIVerb` keys. */\nexport type XAPIVerbKey = keyof typeof XAPIVerb;\n\n/**\n * Default `en-US` display label for each verb, used to populate\n * `XAPIVerbObject.display` when the builder resolves a verb key.\n */\nexport const XAPI_VERB_DISPLAY: Record<XAPIVerbKey, Record<string, string>> = {\n ANSWERED: { 'en-US': 'answered' },\n COMPLETED: { 'en-US': 'completed' },\n EXPERIENCED: { 'en-US': 'experienced' },\n INTERACTED: { 'en-US': 'interacted' },\n ATTEMPTED: { 'en-US': 'attempted' },\n PASSED: { 'en-US': 'passed' },\n FAILED: { 'en-US': 'failed' },\n WATCHED: { 'en-US': 'watched' },\n SUBMITTED: { 'en-US': 'submitted' },\n SCORED: { 'en-US': 'scored' },\n};\n","import type { ScoringResult } from '../types/activity.js';\nimport type {\n XAPIActor,\n XAPIContext,\n XAPIObject,\n XAPIResult,\n XAPIStatement,\n} from '../types/xapi.js';\nimport { validateXAPIStatement } from './validators.js';\nimport { XAPI_VERB_DISPLAY, XAPIVerb, type XAPIVerbKey } from './verbs.js';\n\n/** Caller-supplied activity object descriptor (mapped to an xAPI Activity). */\nexport interface XAPIObjectParams {\n /** Activity IRI. */\n id: string;\n name?: Record<string, string>;\n description?: Record<string, string>;\n /** Activity type IRI. */\n type?: string;\n /** xAPI cmi.interaction type (e.g. `choice`, `fill-in`, `long-fill-in`). */\n interactionType?: string;\n /** Correct-responses patterns, per the xAPI CRP format. */\n correctResponsesPattern?: string[];\n /** For choice-family interactions: the available components. */\n choices?: Array<{ id: string; description?: Record<string, string> }>;\n}\n\n/** Parameters for the generic {@link xAPIBuilder.buildStatement}. */\nexport interface XAPIStatementParams {\n actor: XAPIActor;\n verb: XAPIVerbKey;\n object: XAPIObjectParams;\n result?: XAPIResult;\n context?: XAPIContext;\n}\n\n/** Parameters for {@link xAPIBuilder.buildAnsweredStatement} (verb = ANSWERED). */\nexport interface AnsweredStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n scoringResult: ScoringResult;\n timeSpentMs: number;\n /** Serialized learner response string. */\n response?: string;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/**\n * Parameters for {@link xAPIBuilder.buildSubmittedStatement} (verb =\n * SUBMITTED — deferred-grading submissions). Carries NO score, success, or\n * completion: the grade does not exist yet (Req 22.7).\n */\nexport interface SubmittedStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n timeSpentMs: number;\n /** Serialized learner response string (e.g. the submitted text). */\n response?: string;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/** Parameters for {@link xAPIBuilder.buildCompletedStatement} (verb = COMPLETED). */\nexport interface CompletedStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n scoringResult?: ScoringResult;\n timeSpentMs: number;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/**\n * Converts a millisecond duration to an ISO 8601 seconds string with\n * centisecond precision (`PT1.23S`), per the xAPI 1.0.3 recommendation of\n * 0.01-second accuracy. Sub-second durations are preserved (previously any\n * duration under 500 ms collapsed to `PT0S`). Negative inputs (clock skew)\n * clamp to zero — a negative ISO duration is invalid.\n */\nfunction msToIsoDuration(ms: number): string {\n return `PT${(Math.round(Math.max(0, ms) / 10) / 100).toFixed(2)}S`;\n}\n\n/**\n * UUID v4 that works outside secure contexts. `crypto.randomUUID` is\n * SecureContext-gated (undefined on plain-http LAN/staging origins), and a\n * statement is built at SUBMIT time — throwing here would lose the learner's\n * answer. `crypto.getRandomValues` is NOT gated, so the fallback still emits\n * a spec-valid v4 UUID (the statement validator enforces the v4 format).\n */\nfunction uuidv4(): string {\n const c = (\n globalThis as {\n crypto?: { randomUUID?: () => string; getRandomValues?: (a: Uint8Array) => Uint8Array };\n }\n ).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (c?.getRandomValues) {\n c.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i += 1) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = ((bytes[6] as number) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] as number) & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/** Builds the xAPI Activity object, including `definition` only when populated. */\nfunction buildObject(params: XAPIObjectParams): XAPIObject {\n const definition: NonNullable<XAPIObject['definition']> = {\n ...(params.name !== undefined ? { name: params.name } : {}),\n ...(params.description !== undefined ? { description: params.description } : {}),\n ...(params.type !== undefined ? { type: params.type } : {}),\n ...(params.interactionType !== undefined ? { interactionType: params.interactionType } : {}),\n ...(params.correctResponsesPattern !== undefined\n ? { correctResponsesPattern: params.correctResponsesPattern }\n : {}),\n ...(params.choices !== undefined ? { choices: params.choices } : {}),\n };\n return {\n objectType: 'Activity',\n id: params.id,\n ...(Object.keys(definition).length > 0 ? { definition } : {}),\n };\n}\n\n/**\n * Maps a {@link ScoringResult} + timing to an {@link XAPIResult} per the\n * normative mapping in the design document.\n */\nfunction buildResult(\n timeSpentMs: number,\n scoringResult: ScoringResult | undefined,\n resultExtensions: Record<string, unknown> | undefined,\n response: string | undefined,\n): XAPIResult {\n return {\n completion: true,\n duration: msToIsoDuration(timeSpentMs),\n ...(scoringResult !== undefined\n ? {\n score: {\n scaled: scoringResult.score,\n raw: scoringResult.score,\n min: 0,\n max: scoringResult.maxScore,\n },\n success: scoringResult.passed,\n }\n : {}),\n ...(response !== undefined ? { response } : {}),\n ...(resultExtensions !== undefined ? { extensions: resultExtensions } : {}),\n };\n}\n\n/**\n * Constructs xAPI 1.0.3 Statements. Every call stamps a fresh UUID v4 `id`,\n * an ISO 8601 `timestamp`, and `version: '1.0.3'`. Not pure by design —\n * statements are unique events.\n */\nexport const xAPIBuilder = {\n buildStatement(params: XAPIStatementParams): XAPIStatement {\n const statement: XAPIStatement = {\n id: uuidv4(),\n actor: params.actor,\n verb: {\n id: XAPIVerb[params.verb],\n display: XAPI_VERB_DISPLAY[params.verb],\n },\n object: buildObject(params.object),\n ...(params.result !== undefined ? { result: params.result } : {}),\n ...(params.context !== undefined ? { context: params.context } : {}),\n timestamp: new Date().toISOString(),\n version: '1.0.3',\n };\n // Design xAPIBuilder step 4: validate every statement (throws in dev,\n // warns in prod). All build*Statement helpers route through here.\n validateXAPIStatement(statement);\n return statement;\n },\n\n buildAnsweredStatement(params: AnsweredStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'ANSWERED',\n object: params.object,\n result: buildResult(\n params.timeSpentMs,\n params.scoringResult,\n params.resultExtensions,\n params.response,\n ),\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n\n /**\n * Builds a statement for a deferred-grading submission (e.g. a written\n * response). Verb is SUBMITTED and the result deliberately omits `score`,\n * `success`, and `completion` — none of them exist until the asynchronous\n * grader runs; only `duration`, `response`, and extensions are recorded.\n */\n buildSubmittedStatement(params: SubmittedStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'SUBMITTED',\n object: params.object,\n result: {\n duration: msToIsoDuration(params.timeSpentMs),\n ...(params.response !== undefined ? { response: params.response } : {}),\n ...(params.resultExtensions !== undefined ? { extensions: params.resultExtensions } : {}),\n },\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n\n buildCompletedStatement(params: CompletedStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'COMPLETED',\n object: params.object,\n result: buildResult(\n params.timeSpentMs,\n params.scoringResult,\n params.resultExtensions,\n undefined,\n ),\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n};\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var _chunkTHSZMZNDcjs = require('./chunk-THSZMZND.cjs');
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
var _chunk5ZAW76F3cjs = require('./chunk-5ZAW76F3.cjs');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
var _chunkRUZ52Q7Acjs = require('./chunk-RUZ52Q7A.cjs');
|
|
13
20
|
|
|
14
21
|
|
|
15
22
|
|
|
@@ -220,5 +227,12 @@ function assertRedacted(data) {
|
|
|
220
227
|
|
|
221
228
|
|
|
222
229
|
|
|
223
|
-
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
exports.ActivitySchemaError = _chunkPIMX4B4Dcjs.ActivitySchemaError; exports.BlankConfigSchema = _chunkQOAORTA4cjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunk5ZAW76F3cjs.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 = _chunkRUZ52Q7Acjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkRUZ52Q7Acjs.XAPI_VERB_DISPLAY; exports.assertRedacted = assertRedacted; exports.classifyBand = _chunk5ZAW76F3cjs.classifyBand; exports.composeAssessmentScore = _chunk5ZAW76F3cjs.composeAssessmentScore; exports.computePassThreshold = _chunk5ZAW76F3cjs.computePassThreshold; exports.countWords = _chunkQOAORTA4cjs.countWords; exports.defineActivityType = _chunkQOAORTA4cjs.defineActivityType; exports.evaluate = _chunk5ZAW76F3cjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunkYNTYWHZIcjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunkQOAORTA4cjs.fillInTheBlanksType; exports.getActivityTypeDescriptor = _chunkQOAORTA4cjs.getActivityTypeDescriptor; exports.gradeFromRubric = _chunk5ZAW76F3cjs.gradeFromRubric; exports.gte = _chunk5ZAW76F3cjs.gte; exports.hasGrade = _chunk5ZAW76F3cjs.hasGrade; exports.jsonSchemaFor = _chunkYNTYWHZIcjs.jsonSchemaFor; exports.levenshteinDistance = _chunkQOAORTA4cjs.levenshteinDistance; exports.matchText = _chunkQOAORTA4cjs.matchText; exports.multipleChoiceJsonSchema = _chunkYNTYWHZIcjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunkQOAORTA4cjs.multipleChoiceType; exports.outcomeFromGrade = _chunk5ZAW76F3cjs.outcomeFromGrade; exports.redact = redact; exports.registerActivityType = _chunkQOAORTA4cjs.registerActivityType; exports.registeredActivityTypes = _chunkQOAORTA4cjs.registeredActivityTypes; exports.roundGrade = _chunk5ZAW76F3cjs.roundGrade; exports.score = _chunk5ZAW76F3cjs.score; exports.validateActivity = _chunkYNTYWHZIcjs.validateActivity; exports.validateXAPIStatement = _chunkRUZ52Q7Acjs.validateXAPIStatement; exports.writtenResponseJsonSchema = _chunkYNTYWHZIcjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunkQOAORTA4cjs.writtenResponseType; exports.xAPIBuilder = _chunkRUZ52Q7Acjs.xAPIBuilder;
|
|
224
238
|
//# 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","../src/redact.ts"],"names":[],"mappings":"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","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"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/index.cjs","../src/redact.ts"],"names":[],"mappings":"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","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,8 +1,8 @@
|
|
|
1
|
-
import { V as ValidationError, m as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData,
|
|
2
|
-
export {
|
|
1
|
+
import { V as ValidationError, C as CriterionScore, A as ActivityData, G as GradeRecord, m as ItemOutcome, r as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, o as MultipleChoiceLearnerResponse, W as WrittenResponseData, u as WrittenResponseLearnerResponse } from './activity-wkzRemHx.cjs';
|
|
2
|
+
export { a as ActivityDataMap, b as ActivityFeedback, c as ActivityMedia, d as ActivityResult, e as ActivityType, B as BlankConfig, g as Grader, h as GraderKind, i as GraderUsage, j as GradingState, I as InlineCorrection, k as InteractionEvent, l as InteractionKind, L as LearnerResponse, n as LearnerResponseMap, p as MultipleChoiceOption, S as ScoringDetail, q as ScoringOutcome, T as TextMatchPolicy, s as TextMatchResult, t as ValidationResult, v as WrittenResponseRubric, w as WrittenResponseRubricCriterion, X as XAPIActor, x as XAPIConfig, y as XAPIContext, z as XAPIContextActivities, E as XAPIError, H as XAPIObject, J as XAPIResult, K as XAPIScore, N as XAPIStatement, O as XAPIVerbObject, P as levenshteinDistance, Q as matchText } from './activity-wkzRemHx.cjs';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
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';
|
|
5
|
+
export { AssessmentScore, AssessmentSectionInput, Band, CompositionPolicy, DEFAULT_PASS_THRESHOLD, PassFailureReason, RoundingMode, RoundingPolicy, ScoredItem, SectionScore, classifyBand, composeAssessmentScore, computePassThreshold, evaluate, gte, roundGrade, score } from './scoring.cjs';
|
|
6
6
|
export { AnsweredStatementParams, CompletedStatementParams, SubmittedStatementParams, XAPIObjectParams, XAPIStatementParams, XAPIVerb, XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder } from './xapi.cjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -49,6 +49,52 @@ declare class DeferredScoringError extends Error {
|
|
|
49
49
|
constructor(activityType: string);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/** Options for {@link gradeFromRubric}. */
|
|
53
|
+
interface GradeFromRubricOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Scaled score [0,1] required to pass. Defaults to the activity's
|
|
56
|
+
* `passThreshold`, or {@link DEFAULT_PASS_THRESHOLD} when absent.
|
|
57
|
+
*/
|
|
58
|
+
passThreshold?: number;
|
|
59
|
+
/** Narrative feedback for the learner, carried onto the record verbatim. */
|
|
60
|
+
feedback?: string | null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Computes the weighted total from per-criterion scores — the arithmetic that
|
|
64
|
+
* must NOT be delegated to a language model.
|
|
65
|
+
*
|
|
66
|
+
* A grader is asked for judgement (how good is this criterion?), not for
|
|
67
|
+
* mental arithmetic. Asking a model to also produce the weighted total makes
|
|
68
|
+
* the final grade unverifiable and unreproducible: two runs can return
|
|
69
|
+
* different totals for identical criterion scores. This function makes the
|
|
70
|
+
* total a pure function of the judgements, so a grade can be recomputed and
|
|
71
|
+
* audited years later.
|
|
72
|
+
*
|
|
73
|
+
* Weights are normalised by their sum, so they need not add to 1. Criteria
|
|
74
|
+
* marked `notApplicable`, and those carrying no numeric `score` (a purely
|
|
75
|
+
* banded judgement), are excluded from both numerator and denominator. When
|
|
76
|
+
* nothing scoreable remains the result is `unscorable`, never a zero.
|
|
77
|
+
*/
|
|
78
|
+
declare function gradeFromRubric(criteria: readonly CriterionScore[], activityData?: ActivityData, options?: GradeFromRubricOptions): GradeRecord | {
|
|
79
|
+
unscorable: true;
|
|
80
|
+
reason: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Lifts a {@link GradeRecord} into the `graded` arm of {@link ItemOutcome}, so
|
|
84
|
+
* a grade that arrived asynchronously renders through the same path as a
|
|
85
|
+
* synchronously scored item. The score/passed/feedback fields are mirrored
|
|
86
|
+
* onto the outcome for uniform reads; `grade` carries the full record.
|
|
87
|
+
*/
|
|
88
|
+
declare function outcomeFromGrade(grade: GradeRecord): ItemOutcome;
|
|
89
|
+
/**
|
|
90
|
+
* True when an outcome carries a real grade — either the SDK scored it
|
|
91
|
+
* synchronously or a grader returned one. Use this instead of testing
|
|
92
|
+
* `status === 'scored'`, which silently misses asynchronously graded work.
|
|
93
|
+
*/
|
|
94
|
+
declare function hasGrade(outcome: ItemOutcome): outcome is Extract<ItemOutcome, {
|
|
95
|
+
status: 'scored' | 'graded';
|
|
96
|
+
}>;
|
|
97
|
+
|
|
52
98
|
/** ScoringResult without `passed` — the public `score()` / `evaluate()` fill that in. */
|
|
53
99
|
type PartialScoringResult = Omit<ScoringResult, 'passed'>;
|
|
54
100
|
/**
|
|
@@ -299,4 +345,4 @@ interface ThemeTokens {
|
|
|
299
345
|
'--lk-transition-base': string;
|
|
300
346
|
}
|
|
301
347
|
|
|
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 };
|
|
348
|
+
export { ActivityData, ActivitySchemaError, type ActivityTypeDescriptor, type ActivityTypeInterop, type ActivityTypeScoring, CriterionScore, DeferredScoringError, DeferredScoringPartial, type FieldPolicy, FillInTheBlanksData, FillInTheBlanksLearnerResponse, type GradeFromRubricOptions, GradeRecord, ItemOutcome, 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, gradeFromRubric, hasGrade, multipleChoiceType, outcomeFromGrade, redact, registerActivityType, registeredActivityTypes, writtenResponseType };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { V as ValidationError, m as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData,
|
|
2
|
-
export {
|
|
1
|
+
import { V as ValidationError, C as CriterionScore, A as ActivityData, G as GradeRecord, m as ItemOutcome, r as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, o as MultipleChoiceLearnerResponse, W as WrittenResponseData, u as WrittenResponseLearnerResponse } from './activity-wkzRemHx.js';
|
|
2
|
+
export { a as ActivityDataMap, b as ActivityFeedback, c as ActivityMedia, d as ActivityResult, e as ActivityType, B as BlankConfig, g as Grader, h as GraderKind, i as GraderUsage, j as GradingState, I as InlineCorrection, k as InteractionEvent, l as InteractionKind, L as LearnerResponse, n as LearnerResponseMap, p as MultipleChoiceOption, S as ScoringDetail, q as ScoringOutcome, T as TextMatchPolicy, s as TextMatchResult, t as ValidationResult, v as WrittenResponseRubric, w as WrittenResponseRubricCriterion, X as XAPIActor, x as XAPIConfig, y as XAPIContext, z as XAPIContextActivities, E as XAPIError, H as XAPIObject, J as XAPIResult, K as XAPIScore, N as XAPIStatement, O as XAPIVerbObject, P as levenshteinDistance, Q as matchText } from './activity-wkzRemHx.js';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
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.js';
|
|
5
|
-
export { DEFAULT_PASS_THRESHOLD, computePassThreshold, evaluate, score } from './scoring.js';
|
|
5
|
+
export { AssessmentScore, AssessmentSectionInput, Band, CompositionPolicy, DEFAULT_PASS_THRESHOLD, PassFailureReason, RoundingMode, RoundingPolicy, ScoredItem, SectionScore, classifyBand, composeAssessmentScore, computePassThreshold, evaluate, gte, roundGrade, score } from './scoring.js';
|
|
6
6
|
export { AnsweredStatementParams, CompletedStatementParams, SubmittedStatementParams, XAPIObjectParams, XAPIStatementParams, XAPIVerb, XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder } from './xapi.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -49,6 +49,52 @@ declare class DeferredScoringError extends Error {
|
|
|
49
49
|
constructor(activityType: string);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/** Options for {@link gradeFromRubric}. */
|
|
53
|
+
interface GradeFromRubricOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Scaled score [0,1] required to pass. Defaults to the activity's
|
|
56
|
+
* `passThreshold`, or {@link DEFAULT_PASS_THRESHOLD} when absent.
|
|
57
|
+
*/
|
|
58
|
+
passThreshold?: number;
|
|
59
|
+
/** Narrative feedback for the learner, carried onto the record verbatim. */
|
|
60
|
+
feedback?: string | null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Computes the weighted total from per-criterion scores — the arithmetic that
|
|
64
|
+
* must NOT be delegated to a language model.
|
|
65
|
+
*
|
|
66
|
+
* A grader is asked for judgement (how good is this criterion?), not for
|
|
67
|
+
* mental arithmetic. Asking a model to also produce the weighted total makes
|
|
68
|
+
* the final grade unverifiable and unreproducible: two runs can return
|
|
69
|
+
* different totals for identical criterion scores. This function makes the
|
|
70
|
+
* total a pure function of the judgements, so a grade can be recomputed and
|
|
71
|
+
* audited years later.
|
|
72
|
+
*
|
|
73
|
+
* Weights are normalised by their sum, so they need not add to 1. Criteria
|
|
74
|
+
* marked `notApplicable`, and those carrying no numeric `score` (a purely
|
|
75
|
+
* banded judgement), are excluded from both numerator and denominator. When
|
|
76
|
+
* nothing scoreable remains the result is `unscorable`, never a zero.
|
|
77
|
+
*/
|
|
78
|
+
declare function gradeFromRubric(criteria: readonly CriterionScore[], activityData?: ActivityData, options?: GradeFromRubricOptions): GradeRecord | {
|
|
79
|
+
unscorable: true;
|
|
80
|
+
reason: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Lifts a {@link GradeRecord} into the `graded` arm of {@link ItemOutcome}, so
|
|
84
|
+
* a grade that arrived asynchronously renders through the same path as a
|
|
85
|
+
* synchronously scored item. The score/passed/feedback fields are mirrored
|
|
86
|
+
* onto the outcome for uniform reads; `grade` carries the full record.
|
|
87
|
+
*/
|
|
88
|
+
declare function outcomeFromGrade(grade: GradeRecord): ItemOutcome;
|
|
89
|
+
/**
|
|
90
|
+
* True when an outcome carries a real grade — either the SDK scored it
|
|
91
|
+
* synchronously or a grader returned one. Use this instead of testing
|
|
92
|
+
* `status === 'scored'`, which silently misses asynchronously graded work.
|
|
93
|
+
*/
|
|
94
|
+
declare function hasGrade(outcome: ItemOutcome): outcome is Extract<ItemOutcome, {
|
|
95
|
+
status: 'scored' | 'graded';
|
|
96
|
+
}>;
|
|
97
|
+
|
|
52
98
|
/** ScoringResult without `passed` — the public `score()` / `evaluate()` fill that in. */
|
|
53
99
|
type PartialScoringResult = Omit<ScoringResult, 'passed'>;
|
|
54
100
|
/**
|
|
@@ -299,4 +345,4 @@ interface ThemeTokens {
|
|
|
299
345
|
'--lk-transition-base': string;
|
|
300
346
|
}
|
|
301
347
|
|
|
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 };
|
|
348
|
+
export { ActivityData, ActivitySchemaError, type ActivityTypeDescriptor, type ActivityTypeInterop, type ActivityTypeScoring, CriterionScore, DeferredScoringError, DeferredScoringPartial, type FieldPolicy, FillInTheBlanksData, FillInTheBlanksLearnerResponse, type GradeFromRubricOptions, GradeRecord, ItemOutcome, 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, gradeFromRubric, hasGrade, multipleChoiceType, outcomeFromGrade, redact, registerActivityType, registeredActivityTypes, writtenResponseType };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_PASS_THRESHOLD,
|
|
3
|
+
classifyBand,
|
|
4
|
+
composeAssessmentScore,
|
|
3
5
|
computePassThreshold,
|
|
4
6
|
evaluate,
|
|
7
|
+
gradeFromRubric,
|
|
8
|
+
gte,
|
|
9
|
+
hasGrade,
|
|
10
|
+
outcomeFromGrade,
|
|
11
|
+
roundGrade,
|
|
5
12
|
score
|
|
6
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-A6JXV5GP.js";
|
|
7
14
|
import {
|
|
8
15
|
XAPIVerb,
|
|
9
16
|
XAPI_VERB_DISPLAY,
|
|
10
17
|
validateXAPIStatement,
|
|
11
18
|
xAPIBuilder
|
|
12
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-APDLWLYD.js";
|
|
13
20
|
import {
|
|
14
21
|
fillInTheBlanksJsonSchema,
|
|
15
22
|
jsonSchemaFor,
|
|
@@ -199,6 +206,8 @@ export {
|
|
|
199
206
|
XAPIVerb,
|
|
200
207
|
XAPI_VERB_DISPLAY,
|
|
201
208
|
assertRedacted,
|
|
209
|
+
classifyBand,
|
|
210
|
+
composeAssessmentScore,
|
|
202
211
|
computePassThreshold,
|
|
203
212
|
countWords,
|
|
204
213
|
defineActivityType,
|
|
@@ -206,14 +215,19 @@ export {
|
|
|
206
215
|
fillInTheBlanksJsonSchema,
|
|
207
216
|
fillInTheBlanksType,
|
|
208
217
|
getActivityTypeDescriptor,
|
|
218
|
+
gradeFromRubric,
|
|
219
|
+
gte,
|
|
220
|
+
hasGrade,
|
|
209
221
|
jsonSchemaFor,
|
|
210
222
|
levenshteinDistance,
|
|
211
223
|
matchText,
|
|
212
224
|
multipleChoiceJsonSchema,
|
|
213
225
|
multipleChoiceType,
|
|
226
|
+
outcomeFromGrade,
|
|
214
227
|
redact,
|
|
215
228
|
registerActivityType,
|
|
216
229
|
registeredActivityTypes,
|
|
230
|
+
roundGrade,
|
|
217
231
|
score,
|
|
218
232
|
validateActivity,
|
|
219
233
|
validateXAPIStatement,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/redact.ts"],"sourcesContent":["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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/redact.ts"],"sourcesContent":["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"],"mappings":"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","names":[]}
|
package/dist/schemas.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as ActivityType,
|
|
1
|
+
import { e as ActivityType, t as ValidationResult, a as ActivityDataMap } from './activity-wkzRemHx.cjs';
|
|
2
2
|
import { z } from 'zod/v4';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -97,8 +97,8 @@ declare const FillInTheBlanksDataSchema: z.ZodObject<{
|
|
|
97
97
|
feedback: z.ZodOptional<z.ZodString>;
|
|
98
98
|
}, z.core.$loose>>;
|
|
99
99
|
scoringStrategy: z.ZodEnum<{
|
|
100
|
-
partial: "partial";
|
|
101
100
|
"all-or-nothing": "all-or-nothing";
|
|
101
|
+
partial: "partial";
|
|
102
102
|
}>;
|
|
103
103
|
media: z.ZodOptional<z.ZodObject<{
|
|
104
104
|
type: z.ZodEnum<{
|
|
@@ -233,8 +233,8 @@ declare const MultipleChoiceDataSchema: z.ZodObject<{
|
|
|
233
233
|
feedback: z.ZodOptional<z.ZodString>;
|
|
234
234
|
}, z.core.$loose>>;
|
|
235
235
|
scoringStrategy: z.ZodEnum<{
|
|
236
|
-
partial: "partial";
|
|
237
236
|
"all-or-nothing": "all-or-nothing";
|
|
237
|
+
partial: "partial";
|
|
238
238
|
}>;
|
|
239
239
|
media: z.ZodOptional<z.ZodObject<{
|
|
240
240
|
type: z.ZodEnum<{
|
package/dist/schemas.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as ActivityType,
|
|
1
|
+
import { e as ActivityType, t as ValidationResult, a as ActivityDataMap } from './activity-wkzRemHx.js';
|
|
2
2
|
import { z } from 'zod/v4';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -97,8 +97,8 @@ declare const FillInTheBlanksDataSchema: z.ZodObject<{
|
|
|
97
97
|
feedback: z.ZodOptional<z.ZodString>;
|
|
98
98
|
}, z.core.$loose>>;
|
|
99
99
|
scoringStrategy: z.ZodEnum<{
|
|
100
|
-
partial: "partial";
|
|
101
100
|
"all-or-nothing": "all-or-nothing";
|
|
101
|
+
partial: "partial";
|
|
102
102
|
}>;
|
|
103
103
|
media: z.ZodOptional<z.ZodObject<{
|
|
104
104
|
type: z.ZodEnum<{
|
|
@@ -233,8 +233,8 @@ declare const MultipleChoiceDataSchema: z.ZodObject<{
|
|
|
233
233
|
feedback: z.ZodOptional<z.ZodString>;
|
|
234
234
|
}, z.core.$loose>>;
|
|
235
235
|
scoringStrategy: z.ZodEnum<{
|
|
236
|
-
partial: "partial";
|
|
237
236
|
"all-or-nothing": "all-or-nothing";
|
|
237
|
+
partial: "partial";
|
|
238
238
|
}>;
|
|
239
239
|
media: z.ZodOptional<z.ZodObject<{
|
|
240
240
|
type: z.ZodEnum<{
|
package/dist/scoring.cjs
CHANGED
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunk5ZAW76F3cjs = require('./chunk-5ZAW76F3.cjs');
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
|
|
@@ -16,5 +20,9 @@ require('./chunk-PIMX4B4D.cjs');
|
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
exports.DEFAULT_PASS_THRESHOLD = _chunk5ZAW76F3cjs.DEFAULT_PASS_THRESHOLD; exports.classifyBand = _chunk5ZAW76F3cjs.classifyBand; exports.composeAssessmentScore = _chunk5ZAW76F3cjs.composeAssessmentScore; exports.computePassThreshold = _chunk5ZAW76F3cjs.computePassThreshold; exports.evaluate = _chunk5ZAW76F3cjs.evaluate; exports.gte = _chunk5ZAW76F3cjs.gte; exports.levenshteinDistance = _chunkQOAORTA4cjs.levenshteinDistance; exports.matchText = _chunkQOAORTA4cjs.matchText; exports.roundGrade = _chunk5ZAW76F3cjs.roundGrade; exports.score = _chunk5ZAW76F3cjs.score;
|
|
20
28
|
//# sourceMappingURL=scoring.cjs.map
|
package/dist/scoring.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/scoring.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACF
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/scoring.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yjBAAC","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/scoring.cjs"}
|