@intellectif/lk-core 0.8.2 → 0.10.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +5 -4
  3. package/dist/{activity-CPtJUBek.d.cts → activity-B0zbvu18.d.cts} +177 -2
  4. package/dist/{activity-CPtJUBek.d.ts → activity-B0zbvu18.d.ts} +177 -2
  5. package/dist/{chunk-FVLKIL6W.cjs → chunk-3FEAEO3D.cjs} +18 -13
  6. package/dist/chunk-3FEAEO3D.cjs.map +1 -0
  7. package/dist/chunk-7ODQRNR4.cjs +2009 -0
  8. package/dist/chunk-7ODQRNR4.cjs.map +1 -0
  9. package/dist/chunk-FIS5KBCE.js +2009 -0
  10. package/dist/chunk-FIS5KBCE.js.map +1 -0
  11. package/dist/{chunk-NHGXOOZ2.js → chunk-IXXMYJI7.js} +2 -2
  12. package/dist/{chunk-YJZY5TPY.cjs → chunk-VBM5H6P5.cjs} +8 -8
  13. package/dist/{chunk-YJZY5TPY.cjs.map → chunk-VBM5H6P5.cjs.map} +1 -1
  14. package/dist/{chunk-7ACNBDSF.cjs → chunk-VTTRXGDD.cjs} +4 -4
  15. package/dist/{chunk-7ACNBDSF.cjs.map → chunk-VTTRXGDD.cjs.map} +1 -1
  16. package/dist/{chunk-2M76F32Y.js → chunk-XGCTAQSS.js} +7 -2
  17. package/dist/chunk-XGCTAQSS.js.map +1 -0
  18. package/dist/{chunk-LNA33IK7.js → chunk-ZTY4UIUD.js} +2 -2
  19. package/dist/{index-BvrA8nIV.d.ts → index-DSfETm4b.d.ts} +321 -3
  20. package/dist/{index-gIN564mV.d.cts → index-u_rBLkuc.d.cts} +321 -3
  21. package/dist/index.cjs +156 -42
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +159 -8
  24. package/dist/index.d.ts +159 -8
  25. package/dist/index.js +137 -23
  26. package/dist/index.js.map +1 -1
  27. package/dist/schemas.cjs +25 -3
  28. package/dist/schemas.cjs.map +1 -1
  29. package/dist/schemas.d.cts +2 -2
  30. package/dist/schemas.d.ts +2 -2
  31. package/dist/schemas.js +24 -2
  32. package/dist/scoring.cjs +3 -3
  33. package/dist/scoring.d.cts +2 -2
  34. package/dist/scoring.d.ts +2 -2
  35. package/dist/scoring.js +2 -2
  36. package/dist/xapi.cjs +3 -3
  37. package/dist/xapi.d.cts +1 -1
  38. package/dist/xapi.d.ts +1 -1
  39. package/dist/xapi.js +2 -2
  40. package/package.json +1 -1
  41. package/dist/chunk-2M76F32Y.js.map +0 -1
  42. package/dist/chunk-FKH4YT5X.cjs +0 -748
  43. package/dist/chunk-FKH4YT5X.cjs.map +0 -1
  44. package/dist/chunk-FVLKIL6W.cjs.map +0 -1
  45. package/dist/chunk-HCOWSGEZ.js +0 -748
  46. package/dist/chunk-HCOWSGEZ.js.map +0 -1
  47. /package/dist/{chunk-NHGXOOZ2.js.map → chunk-IXXMYJI7.js.map} +0 -0
  48. /package/dist/{chunk-LNA33IK7.js.map → chunk-ZTY4UIUD.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ScoredItem } from './scoring.js';
2
2
  export { AssessmentScore, AssessmentSectionInput, Band, CompositionPolicy, DEFAULT_PASS_THRESHOLD, PassFailureReason, RoundingMode, RoundingPolicy, SectionScore, classifyBand, composeAssessmentScore, computePassThreshold, evaluate, gte, roundGrade, score } from './scoring.js';
3
- import { m as ItemOutcome, A as ActivityData, L as LearnerResponse, V as ValidationError, C as CriterionScore, G as GradeRecord, N as NativeControlHint, c as ActivityMedia, 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-CPtJUBek.js';
4
- export { a as ActivityDataMap, b as ActivityFeedback, 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, 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, O as XAPIStatement, P as XAPIVerbObject, Q as levenshteinDistance, R as matchText } from './activity-CPtJUBek.js';
5
- import { u as SequenceSlot, S as SequenceEntry, I as ItemGroup } from './index-BvrA8nIV.js';
6
- export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, b as ItemGroupSchema, M as MediaPlaybackSchema, c as MediaSchema, d as MediaUrlSchema, e as MultipleChoiceDataSchema, f as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, g as RedactedBlankConfig, h as RedactedBlankConfigSchema, i as RedactedFillInTheBlanksData, j as RedactedFillInTheBlanksDataSchema, k as RedactedItemGroupSchema, l as RedactedMediaSchema, m as RedactedMultipleChoiceData, n as RedactedMultipleChoiceDataSchema, o as RedactedMultipleChoiceOption, p as RedactedMultipleChoiceOptionSchema, q as RedactedStimulus, r as RedactedStimulusSchema, s as RedactedWrittenResponseData, t as RedactedWrittenResponseDataSchema, v as SequenceSlotGroup, w as Stimulus, x as StimulusKind, y as StimulusSchema, T as TextMatchPolicySchema, W as WrittenResponseDataSchema, z as WrittenResponseRubricCriterionSchema, A as WrittenResponseRubricSchema, C as fillInTheBlanksJsonSchema, D as itemGroupJsonSchema, E as jsonSchemaFor, G as multipleChoiceJsonSchema, H as stimulusJsonSchema, J as validateActivity, K as validateItemGroup, L as writtenResponseJsonSchema } from './index-BvrA8nIV.js';
3
+ import { m as ItemOutcome, A as ActivityData, L as LearnerResponse, V as ValidationError, e as ActivityType, a as ActivityDataMap, C as CriterionScore, G as GradeRecord, N as NativeControlHint, c as ActivityMedia, s as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, o as MultipleChoiceLearnerResponse, W as WrittenResponseData, v as WrittenResponseLearnerResponse } from './activity-B0zbvu18.js';
4
+ export { b as ActivityFeedback, d as ActivityResult, B as BlankConfig, g as Grader, h as GraderKind, i as GraderUsage, j as GradingState, I as InlineCorrection, k as InteractionEvent, l as InteractionKind, n as LearnerResponseMap, p as MultipleChoiceOption, q as MultipleChoiceOptionMedia, S as ScoringDetail, r as ScoringOutcome, T as TextMatchPolicy, t as TextMatchResult, u as ValidationResult, w as WrittenResponseRubric, x as WrittenResponseRubricCriterion, X as XAPIActor, y as XAPIConfig, z as XAPIContext, E as XAPIContextActivities, H as XAPIError, J as XAPIObject, K as XAPIResult, O as XAPIScore, P as XAPIStatement, Q as XAPIVerbObject, R as levenshteinDistance, U as matchText } from './activity-B0zbvu18.js';
5
+ import { O as SequenceSlot, S as SequenceEntry, I as ItemGroup } from './index-DSfETm4b.js';
6
+ export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, P as SequenceSlotGroup, Q as Stimulus, T as StimulusKind, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-DSfETm4b.js';
7
7
  import { z } from 'zod/v4';
8
8
  export { AnsweredStatementParams, CompletedStatementParams, SubmittedStatementParams, XAPIObjectParams, XAPIStatementParams, XAPIVerb, XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder, xapiDefinitionFor } from './xapi.js';
9
9
 
@@ -327,6 +327,118 @@ declare function restoreAttemptState(plan: AttemptPlan, state: AttemptState): At
327
327
  */
328
328
  declare function diffResponses(before: Pick<AttemptState, 'responses'>, after: Pick<AttemptState, 'responses'>): ResponseDiffEntry[];
329
329
 
330
+ /**
331
+ * Why a draft is not an activity yet.
332
+ *
333
+ * - `incomplete` — something the author has not written yet: an empty title, an
334
+ * option with no text, no option marked correct. The fix is to add it.
335
+ * - `invalid` — something is wrong in a way that writing more cannot fix: two
336
+ * correct options on a single-selection question, a maximum word count below
337
+ * the minimum, a media address with a scheme the SDK refuses, a `null` in an
338
+ * optional field that accepts none. The fix is to change it.
339
+ */
340
+ type DraftSeverity = 'incomplete' | 'invalid';
341
+ /**
342
+ * One problem with a draft. A {@link ValidationError} with a severity, so code
343
+ * that already lists `validateActivity` errors can list these unchanged.
344
+ */
345
+ interface DraftIssue extends ValidationError {
346
+ severity: DraftSeverity;
347
+ }
348
+ /** A draft that is a valid activity and has nothing left to write. */
349
+ interface DraftComplete<T> {
350
+ status: 'complete';
351
+ /** The validated activity, exactly as `validateActivity` returns it. */
352
+ data: T;
353
+ /** Always empty. Present so that every result can be read the same way. */
354
+ issues: DraftIssue[];
355
+ }
356
+ /**
357
+ * A draft that is not an activity yet: `invalid` when any issue is invalid,
358
+ * otherwise `incomplete`. It carries no `data`, because nothing here may be
359
+ * stored or rendered as an activity.
360
+ */
361
+ interface DraftNotComplete {
362
+ status: 'incomplete' | 'invalid';
363
+ issues: DraftIssue[];
364
+ }
365
+ /**
366
+ * The result of `validateDraft`.
367
+ *
368
+ * There is deliberately no `success` boolean. A boolean has to call an
369
+ * incomplete draft either a success, which lets a half-written answer key
370
+ * through anything that checks it, or a failure, which is the conflation this
371
+ * result exists to remove. Branch on `status`.
372
+ */
373
+ type DraftValidationResult<T> = DraftComplete<T> | DraftNotComplete;
374
+ /** What `createDraft` hands an activity type's `authoring.createDraft`. */
375
+ interface DraftContext {
376
+ /**
377
+ * Returns a new id on every call. The SDK invents none: an id made here would
378
+ * need `crypto`, which plain-http origins do not have, or would be positional —
379
+ * and option ids reach the learner, so ids like `"a"` and `"b"` would tell them
380
+ * which option was written first.
381
+ */
382
+ newId: () => string;
383
+ }
384
+
385
+ /**
386
+ * Tells a draft that is not finished from a draft that is wrong.
387
+ *
388
+ * `validateActivity` answers "may this be stored?", and to that question an
389
+ * empty new question and a broken one are the same answer: no. An editor needs
390
+ * the difference — "Add a title" is a to-do, "Only one option can be marked
391
+ * correct" is an error — so a freshly added question does not read as a
392
+ * failure, disable a whole form, or blank a preview.
393
+ *
394
+ * - `complete` — the draft is a valid activity with nothing left to write.
395
+ * `data` is exactly what `validateActivity` returns for it.
396
+ * - `incomplete` — every problem is something not yet written.
397
+ * - `invalid` — at least one problem is wrong in a way writing more cannot fix.
398
+ *
399
+ * It is stricter than `validateActivity`, never looser: `complete` requires the
400
+ * activity's schema to pass, and a draft can fail here that the schema accepts
401
+ * (a title that is only whitespace). Content stored by an older build can
402
+ * therefore be valid and still not `complete`. `validateActivity` stays the
403
+ * check at your write boundary.
404
+ *
405
+ * Issues come from the type's `authoring.checkDraft`, plus every schema failure
406
+ * it did not already report at that path or inside it. (A failure at the root of
407
+ * the draft counts as reported only by an issue at the root, since every path is
408
+ * inside the root.) Such a failure is added as `invalid`: under the code
409
+ * `null_not_allowed` when the schema refused a `null` there, or an `undefined`
410
+ * entry in a list, and otherwise under the schema's own code and message. A type
411
+ * with no `checkDraft` therefore reports every schema failure as `invalid`.
412
+ *
413
+ * The codes documented in `docs/authoring.md` are a contract, and each is
414
+ * reported with its documented severity, whichever check reports it. A code
415
+ * passed through from the schema is not a contract: the code and its English
416
+ * message belong to the schema library, so give a code you do not recognise a
417
+ * generic message of your own.
418
+ *
419
+ * @throws UnknownActivityTypeError when `type` has no registered descriptor —
420
+ * including `'item-group'`, which is a container, not an activity type.
421
+ */
422
+ declare function validateDraft<T extends ActivityType>(type: T, draft: unknown): DraftValidationResult<ActivityDataMap[T]>;
423
+ /**
424
+ * A new, empty draft of an activity type, for an editor to start from.
425
+ *
426
+ * Every required field is present and nothing is authored, so the draft comes
427
+ * back from {@link validateDraft} as `incomplete`, and `validateActivity`
428
+ * rejects it until someone writes it. The SDK invents no ids: `newId` is called
429
+ * once per id the draft needs, and must return a different non-empty string each
430
+ * time.
431
+ *
432
+ * ```ts
433
+ * const draft = createDraft('multiple-choice', { newId: () => crypto.randomUUID() });
434
+ * ```
435
+ *
436
+ * @throws UnknownActivityTypeError when `type` has no registered descriptor.
437
+ * @throws Error when the type declares no `authoring.createDraft`, or when
438
+ * `newId` returns an empty or repeated id.
439
+ */
440
+ declare function createDraft<T extends ActivityType>(type: T, context: DraftContext): ActivityDataMap[T];
441
+
330
442
  /**
331
443
  * Content fingerprinting — "is this the same content the learner was served?"
332
444
  *
@@ -706,12 +818,48 @@ type ActivityTypeScoring<TData, TResponse> = {
706
818
  readonly reason: 'requires_async_grading';
707
819
  readonly partial?: (data: TData, response: TResponse | undefined) => DeferredScoringPartial;
708
820
  };
821
+ /**
822
+ * Authoring support for an activity type: the empty draft an editor starts
823
+ * from, and the rules that tell a draft that is unfinished from one that is
824
+ * wrong. Both are optional. Without `checkDraft`, `validateDraft` still works
825
+ * and reports every schema failure as `invalid`; without `createDraft`,
826
+ * `createDraft()` throws for the type.
827
+ */
828
+ interface ActivityTypeAuthoring<TData> {
829
+ /**
830
+ * A new draft: every required field present, nothing authored yet. It must
831
+ * come back from `validateDraft` as `incomplete` — never `invalid`, and never
832
+ * `complete` — so a freshly added question is not reported as an error, and
833
+ * cannot pass validation before anyone has written it.
834
+ */
835
+ readonly createDraft?: (context: DraftContext) => TData;
836
+ /**
837
+ * Reports what is missing (`incomplete`) and what is wrong (`invalid`) in a
838
+ * draft. Receives any plain object and must not throw on one.
839
+ *
840
+ * Report each problem at the path the schema reports it. `validateDraft` adds
841
+ * every schema failure as `invalid` unless an issue returned here sits at that
842
+ * path or inside it — so an issue at the wrong path leaves the schema's
843
+ * message standing beside yours, and makes an unfinished draft read as wrong.
844
+ * An issue inside a path accounts for every failure at that path, a list's
845
+ * length included, so report a rule about a whole list at the list's own path.
846
+ * A failure at the root of the draft is accounted for only by an issue at the
847
+ * root. A `null` the schema refuses, where nothing here reports it, comes back
848
+ * as `null_not_allowed` — except inside a plain `z.union`, which reports a
849
+ * failure once, at the union's own path, under its own code.
850
+ *
851
+ * A code documented in `docs/authoring.md` is reported with its documented
852
+ * severity. For a code of your own, a severity other than `'incomplete'` is
853
+ * reported as `invalid`.
854
+ */
855
+ readonly checkDraft?: (draft: Readonly<Record<string, unknown>>) => DraftIssue[];
856
+ }
709
857
  /**
710
858
  * A value-level description of an activity type: its contract (schema), its
711
859
  * grading, its redaction policy, and its interop facts. Registering a
712
- * descriptor makes `validateActivity`, `score`, `evaluate`, `redact`, and
713
- * `jsonSchemaFor` work for the type — an activity type is a value, not a
714
- * hardcoded union member (R1).
860
+ * descriptor makes `validateActivity`, `validateDraft`, `score`, `evaluate`,
861
+ * `redact`, and `jsonSchemaFor` work for the type — an activity type is a value,
862
+ * not a hardcoded union member (R1).
715
863
  */
716
864
  interface ActivityTypeDescriptor<TData extends {
717
865
  type: string;
@@ -736,6 +884,8 @@ interface ActivityTypeDescriptor<TData extends {
736
884
  readonly interop?: ActivityTypeInterop<TData>;
737
885
  /** The interaction-event kinds components for this type emit. */
738
886
  readonly interactions?: readonly string[];
887
+ /** Draft support for authoring tools. See {@link ActivityTypeAuthoring}. */
888
+ readonly authoring?: ActivityTypeAuthoring<TData>;
739
889
  }
740
890
  /**
741
891
  * Internal type-erased descriptor shape stored in the registry. Dispatch call
@@ -757,6 +907,7 @@ interface RegisteredActivityTypeDescriptor {
757
907
  readonly redactedSchema?: z.ZodType<unknown>;
758
908
  readonly interop?: ActivityTypeInterop<unknown>;
759
909
  readonly interactions?: readonly string[];
910
+ readonly authoring?: ActivityTypeAuthoring<unknown>;
760
911
  }
761
912
  /**
762
913
  * Identity helper that gives full type inference when authoring a descriptor:
@@ -997,4 +1148,4 @@ interface ThemeTokens {
997
1148
  '--lk-transition-base': string;
998
1149
  }
999
1150
 
1000
- export { ActivityData, ActivityMedia, ActivitySchemaError, type ActivityTypeDescriptor, type ActivityTypeInterop, type ActivityTypeScoring, type AttemptPlan, type AttemptPlanDrift, type AttemptPlanSlot, type AttemptProgress, type AttemptState, CriterionScore, DeferredScoringError, DeferredScoringPartial, type FieldPolicy, FillInTheBlanksData, FillInTheBlanksLearnerResponse, type FlattenSequenceOptions, type GradeFromRubricOptions, GradeRecord, ItemGroup, ItemOutcome, LearnerResponse, type MediaBudgetRef, type MediaPlayClaim, type MediaPlayGrant, type MediaPlayLedger, type MediaPlayLedgerEntry, type MissingOutcomePolicy, MultipleChoiceData, MultipleChoiceLearnerResponse, type PartialScoringResult, type PlanAttemptOptions, type PlannableEntry, type RedactOptions, type RedactedActivityData, type RedactedItemGroup, RedactedScoringError, type RegisteredActivityTypeDescriptor, type ResolvedPlaybackPolicy, type ResponseDiffEntry, ScoredItem, ScoringResult, type SeededShuffleOptions, type Sensitivity, SequenceEntry, SequenceSlot, type ShuffleVersion, type ThemeTokens, UnknownActivityTypeError, ValidationError, WrittenResponseData, WrittenResponseLearnerResponse, type XAPIInteractionType, assertRedacted, assertRedactedItemGroup, canonicalJson, contentHash, countWords, defineActivityType, diffResponses, entryKeyOf, fillInTheBlanksType, fingerprint, flattenSequence, getActivityTypeDescriptor, gradeFromRubric, hasGrade, hashSeed, isItemGroup, multipleChoiceType, outcomeFromGrade, planAttempt, planMediaBudgets, redact, redactItemGroup, registerActivityType, registeredActivityTypes, resolvePlaybackPolicy, restoreAttemptState, restoreMediaPlayLedger, scoredItemsFromPlan, seededShuffle, serializeAttemptState, serializeMediaPlayLedger, slotMediaKey, stimulusMediaKey, verifyAttemptPlan, writtenResponseType };
1151
+ export { ActivityData, ActivityDataMap, ActivityMedia, ActivitySchemaError, ActivityType, type ActivityTypeAuthoring, type ActivityTypeDescriptor, type ActivityTypeInterop, type ActivityTypeScoring, type AttemptPlan, type AttemptPlanDrift, type AttemptPlanSlot, type AttemptProgress, type AttemptState, CriterionScore, DeferredScoringError, DeferredScoringPartial, type DraftComplete, type DraftContext, type DraftIssue, type DraftNotComplete, type DraftSeverity, type DraftValidationResult, type FieldPolicy, FillInTheBlanksData, FillInTheBlanksLearnerResponse, type FlattenSequenceOptions, type GradeFromRubricOptions, GradeRecord, ItemGroup, ItemOutcome, LearnerResponse, type MediaBudgetRef, type MediaPlayClaim, type MediaPlayGrant, type MediaPlayLedger, type MediaPlayLedgerEntry, type MissingOutcomePolicy, MultipleChoiceData, MultipleChoiceLearnerResponse, type PartialScoringResult, type PlanAttemptOptions, type PlannableEntry, type RedactOptions, type RedactedActivityData, type RedactedItemGroup, RedactedScoringError, type RegisteredActivityTypeDescriptor, type ResolvedPlaybackPolicy, type ResponseDiffEntry, ScoredItem, ScoringResult, type SeededShuffleOptions, type Sensitivity, SequenceEntry, SequenceSlot, type ShuffleVersion, type ThemeTokens, UnknownActivityTypeError, ValidationError, WrittenResponseData, WrittenResponseLearnerResponse, type XAPIInteractionType, assertRedacted, assertRedactedItemGroup, canonicalJson, contentHash, countWords, createDraft, defineActivityType, diffResponses, entryKeyOf, fillInTheBlanksType, fingerprint, flattenSequence, getActivityTypeDescriptor, gradeFromRubric, hasGrade, hashSeed, isItemGroup, multipleChoiceType, outcomeFromGrade, planAttempt, planMediaBudgets, redact, redactItemGroup, registerActivityType, registeredActivityTypes, resolvePlaybackPolicy, restoreAttemptState, restoreMediaPlayLedger, scoredItemsFromPlan, seededShuffle, serializeAttemptState, serializeMediaPlayLedger, slotMediaKey, stimulusMediaKey, validateDraft, verifyAttemptPlan, writtenResponseType };
package/dist/index.js CHANGED
@@ -10,20 +10,21 @@ import {
10
10
  outcomeFromGrade,
11
11
  roundGrade,
12
12
  score
13
- } from "./chunk-LNA33IK7.js";
13
+ } from "./chunk-ZTY4UIUD.js";
14
14
  import {
15
15
  XAPIVerb,
16
16
  XAPI_VERB_DISPLAY,
17
17
  validateXAPIStatement,
18
18
  xAPIBuilder,
19
19
  xapiDefinitionFor
20
- } from "./chunk-NHGXOOZ2.js";
20
+ } from "./chunk-IXXMYJI7.js";
21
21
  import {
22
22
  ItemGroupSchema,
23
23
  RedactedItemGroupSchema,
24
24
  RedactedStimulusSchema,
25
25
  StimulusSchema,
26
26
  fillInTheBlanksJsonSchema,
27
+ gapSelectJsonSchema,
27
28
  itemGroupJsonSchema,
28
29
  jsonSchemaFor,
29
30
  multipleChoiceJsonSchema,
@@ -31,24 +32,35 @@ import {
31
32
  validateActivity,
32
33
  validateItemGroup,
33
34
  writtenResponseJsonSchema
34
- } from "./chunk-2M76F32Y.js";
35
+ } from "./chunk-XGCTAQSS.js";
35
36
  import {
36
37
  ActivitySchemaError,
37
38
  BlankConfigSchema,
39
+ DRAFT_ISSUE_SEVERITY,
38
40
  DeferredScoringError,
39
41
  FeedbackSchema,
40
42
  FillInTheBlanksDataSchema,
43
+ GapSelectBankSchema,
44
+ GapSelectChoiceSchema,
45
+ GapSelectDataSchema,
46
+ GapSelectGapSchema,
41
47
  MEDIA_FIELD_POLICY,
42
48
  MediaPlaybackSchema,
43
49
  MediaSchema,
44
50
  MediaUrlSchema,
45
51
  MultipleChoiceDataSchema,
52
+ MultipleChoiceOptionMediaSchema,
46
53
  MultipleChoiceOptionSchema,
47
54
  NativeControlHintSchema,
48
55
  RedactedBlankConfigSchema,
49
56
  RedactedFillInTheBlanksDataSchema,
57
+ RedactedGapSelectBankSchema,
58
+ RedactedGapSelectChoiceSchema,
59
+ RedactedGapSelectDataSchema,
60
+ RedactedGapSelectGapSchema,
50
61
  RedactedMediaSchema,
51
62
  RedactedMultipleChoiceDataSchema,
63
+ RedactedMultipleChoiceOptionMediaSchema,
52
64
  RedactedMultipleChoiceOptionSchema,
53
65
  RedactedScoringError,
54
66
  RedactedWrittenResponseDataSchema,
@@ -61,13 +73,16 @@ import {
61
73
  defineActivityType,
62
74
  fillInTheBlanksType,
63
75
  getActivityTypeDescriptor,
76
+ isRecord,
77
+ issue,
64
78
  levenshteinDistance,
65
79
  matchText,
66
80
  multipleChoiceType,
81
+ refusesEmpty,
67
82
  registerActivityType,
68
83
  registeredActivityTypes,
69
84
  writtenResponseType
70
- } from "./chunk-HCOWSGEZ.js";
85
+ } from "./chunk-FIS5KBCE.js";
71
86
 
72
87
  // src/content-hash.ts
73
88
  function canonicalJson(value, seen = /* @__PURE__ */ new Set()) {
@@ -571,6 +586,92 @@ function diffResponses(before, after) {
571
586
  return entries;
572
587
  }
573
588
 
589
+ // src/authoring/index.ts
590
+ function validateDraft(type, draft) {
591
+ const descriptor = getActivityTypeDescriptor(type);
592
+ if (descriptor === void 0) {
593
+ throw new UnknownActivityTypeError(String(type));
594
+ }
595
+ const reported = isRecord(draft) && descriptor.authoring?.checkDraft !== void 0 ? descriptor.authoring.checkDraft(draft).map(normalise) : [];
596
+ const issues = [...reported];
597
+ const parsed = descriptor.schema.safeParse(draft, { reportInput: true });
598
+ if (!parsed.success) {
599
+ const reportedEmpty = /* @__PURE__ */ new Set();
600
+ for (const schemaIssue of parsed.error.issues) {
601
+ const path = schemaIssue.path.map(String);
602
+ if (reported.some((known) => covers(known.path, path))) {
603
+ continue;
604
+ }
605
+ if (path.length > 0 && refusesEmpty(draft, schemaIssue)) {
606
+ const key = JSON.stringify(path);
607
+ if (!reportedEmpty.has(key)) {
608
+ reportedEmpty.add(key);
609
+ issues.push(
610
+ issue(
611
+ "null_not_allowed",
612
+ path,
613
+ typeof schemaIssue.path.at(-1) === "number" ? "This entry has no value. Remove it, or fill it in." : "This field cannot be null. Leave it out if it is optional, or give it a value."
614
+ )
615
+ );
616
+ }
617
+ continue;
618
+ }
619
+ issues.push({
620
+ path,
621
+ message: schemaIssue.message,
622
+ code: schemaIssue.code,
623
+ severity: "invalid"
624
+ });
625
+ }
626
+ }
627
+ if (parsed.success && issues.length === 0) {
628
+ return { status: "complete", data: parsed.data, issues };
629
+ }
630
+ const invalid = issues.some((found) => found.severity !== "incomplete");
631
+ return { status: invalid ? "invalid" : "incomplete", issues };
632
+ }
633
+ function createDraft(type, context) {
634
+ const descriptor = getActivityTypeDescriptor(type);
635
+ if (descriptor === void 0) {
636
+ throw new UnknownActivityTypeError(String(type));
637
+ }
638
+ const create = descriptor.authoring?.createDraft;
639
+ if (create === void 0) {
640
+ throw new Error(
641
+ `Activity type "${String(type)}" declares no authoring.createDraft, so there is no empty draft to create. Build the draft yourself; validateDraft works for every registered type.`
642
+ );
643
+ }
644
+ const issued = /* @__PURE__ */ new Set();
645
+ const newId = () => {
646
+ const id = context.newId();
647
+ if (typeof id !== "string" || id === "") {
648
+ throw new Error("createDraft: newId() must return a non-empty string.");
649
+ }
650
+ if (issued.has(id)) {
651
+ throw new Error(
652
+ `createDraft: newId() returned "${id}" twice. Ids within one draft must differ \u2014 two options sharing an id cannot be scored apart.`
653
+ );
654
+ }
655
+ issued.add(id);
656
+ return id;
657
+ };
658
+ return create({ newId });
659
+ }
660
+ function normalise(found) {
661
+ const documented = Object.hasOwn(DRAFT_ISSUE_SEVERITY, found.code) ? DRAFT_ISSUE_SEVERITY[found.code] : void 0;
662
+ return {
663
+ ...found,
664
+ path: found.path.map(String),
665
+ severity: documented ?? (found.severity === "incomplete" ? "incomplete" : "invalid")
666
+ };
667
+ }
668
+ function covers(reported, failed) {
669
+ if (failed.length === 0) {
670
+ return reported.length === 0;
671
+ }
672
+ return failed.every((segment, index) => reported[index] === segment);
673
+ }
674
+
574
675
  // src/redact.ts
575
676
  function mergePolicy(base, overrides) {
576
677
  if (overrides === void 0) {
@@ -644,10 +745,10 @@ function redact(data, options = {}) {
644
745
  if (!parsed.success) {
645
746
  throw new ActivitySchemaError(
646
747
  descriptor.type,
647
- parsed.error.issues.map((issue) => ({
648
- path: issue.path.map(String),
649
- message: issue.message,
650
- code: issue.code
748
+ parsed.error.issues.map((issue2) => ({
749
+ path: issue2.path.map(String),
750
+ message: issue2.message,
751
+ code: issue2.code
651
752
  }))
652
753
  );
653
754
  }
@@ -688,10 +789,10 @@ function assertRedacted(data) {
688
789
  if (!parsed.success) {
689
790
  throw new ActivitySchemaError(
690
791
  descriptor.type,
691
- parsed.error.issues.map((issue) => ({
692
- path: issue.path.map(String),
693
- message: issue.message,
694
- code: issue.code
792
+ parsed.error.issues.map((issue2) => ({
793
+ path: issue2.path.map(String),
794
+ message: issue2.message,
795
+ code: issue2.code
695
796
  }))
696
797
  );
697
798
  }
@@ -732,10 +833,10 @@ function redactItemGroup(group, options = {}) {
732
833
  if (!parsed.success) {
733
834
  throw new ActivitySchemaError(
734
835
  "item-group",
735
- parsed.error.issues.map((issue) => ({
736
- path: issue.path.map(String),
737
- message: issue.message,
738
- code: issue.code
836
+ parsed.error.issues.map((issue2) => ({
837
+ path: issue2.path.map(String),
838
+ message: issue2.message,
839
+ code: issue2.code
739
840
  }))
740
841
  );
741
842
  }
@@ -762,10 +863,10 @@ function assertRedactedItemGroup(data) {
762
863
  if (!parsed.success) {
763
864
  throw new ActivitySchemaError(
764
865
  "item-group",
765
- parsed.error.issues.map((issue) => ({
766
- path: issue.path.map(String),
767
- message: issue.message,
768
- code: issue.code
866
+ parsed.error.issues.map((issue2) => ({
867
+ path: issue2.path.map(String),
868
+ message: issue2.message,
869
+ code: issue2.code
769
870
  }))
770
871
  );
771
872
  }
@@ -776,9 +877,9 @@ function assertRedactedItemGroup(data) {
776
877
  if (error instanceof ActivitySchemaError) {
777
878
  throw new ActivitySchemaError(
778
879
  "item-group",
779
- error.errors.map((issue) => ({
780
- ...issue,
781
- path: ["items", String(index), ...issue.path]
880
+ error.errors.map((issue2) => ({
881
+ ...issue2,
882
+ path: ["items", String(index), ...issue2.path]
782
883
  }))
783
884
  );
784
885
  }
@@ -793,18 +894,28 @@ export {
793
894
  DeferredScoringError,
794
895
  FeedbackSchema,
795
896
  FillInTheBlanksDataSchema,
897
+ GapSelectBankSchema,
898
+ GapSelectChoiceSchema,
899
+ GapSelectDataSchema,
900
+ GapSelectGapSchema,
796
901
  ItemGroupSchema,
797
902
  MediaPlaybackSchema,
798
903
  MediaSchema,
799
904
  MediaUrlSchema,
800
905
  MultipleChoiceDataSchema,
906
+ MultipleChoiceOptionMediaSchema,
801
907
  MultipleChoiceOptionSchema,
802
908
  NativeControlHintSchema,
803
909
  RedactedBlankConfigSchema,
804
910
  RedactedFillInTheBlanksDataSchema,
911
+ RedactedGapSelectBankSchema,
912
+ RedactedGapSelectChoiceSchema,
913
+ RedactedGapSelectDataSchema,
914
+ RedactedGapSelectGapSchema,
805
915
  RedactedItemGroupSchema,
806
916
  RedactedMediaSchema,
807
917
  RedactedMultipleChoiceDataSchema,
918
+ RedactedMultipleChoiceOptionMediaSchema,
808
919
  RedactedMultipleChoiceOptionSchema,
809
920
  RedactedScoringError,
810
921
  RedactedStimulusSchema,
@@ -825,6 +936,7 @@ export {
825
936
  computePassThreshold,
826
937
  contentHash,
827
938
  countWords,
939
+ createDraft,
828
940
  defineActivityType,
829
941
  diffResponses,
830
942
  entryKeyOf,
@@ -833,6 +945,7 @@ export {
833
945
  fillInTheBlanksType,
834
946
  fingerprint,
835
947
  flattenSequence,
948
+ gapSelectJsonSchema,
836
949
  getActivityTypeDescriptor,
837
950
  gradeFromRubric,
838
951
  gte,
@@ -865,6 +978,7 @@ export {
865
978
  stimulusJsonSchema,
866
979
  stimulusMediaKey,
867
980
  validateActivity,
981
+ validateDraft,
868
982
  validateItemGroup,
869
983
  validateXAPIStatement,
870
984
  verifyAttemptPlan,