@superbuilders/primer-tives 1.2.0 → 2.0.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/README.md +15 -6
- package/dist/client/choice-state.d.ts +2 -1
- package/dist/client/choice-state.d.ts.map +1 -1
- package/dist/client/create.d.ts +1 -1
- package/dist/client/create.d.ts.map +1 -1
- package/dist/client/extended-text-state.d.ts +2 -1
- package/dist/client/extended-text-state.d.ts.map +1 -1
- package/dist/client/feedback-state.d.ts +2 -2
- package/dist/client/feedback-state.d.ts.map +1 -1
- package/dist/client/index.js +140 -61
- package/dist/client/index.js.map +16 -15
- package/dist/client/match-state.d.ts +2 -1
- package/dist/client/match-state.d.ts.map +1 -1
- package/dist/client/observation-state.d.ts +2 -1
- package/dist/client/observation-state.d.ts.map +1 -1
- package/dist/client/order-state.d.ts +2 -1
- package/dist/client/order-state.d.ts.map +1 -1
- package/dist/client/pci-state.d.ts +2 -1
- package/dist/client/pci-state.d.ts.map +1 -1
- package/dist/client/session-context.d.ts +1 -1
- package/dist/client/session-context.d.ts.map +1 -1
- package/dist/client/session.d.ts +1 -1
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/text-entry-state.d.ts +2 -1
- package/dist/client/text-entry-state.d.ts.map +1 -1
- package/dist/client/transport.d.ts +9 -6
- package/dist/client/transport.d.ts.map +1 -1
- package/dist/client/types.d.ts +10 -1
- package/dist/client/types.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/types.d.ts +5 -9
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/errors.d.ts +2 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -1
- package/dist/errors.js.map +3 -3
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +3 -3
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var ErrStudentNotFound = errors.new("student not found");
|
|
|
22
22
|
var ErrUnsupportedGrade = errors.new("unsupported grade");
|
|
23
23
|
var ErrTimebackUnavailable = errors.new("timeback unavailable");
|
|
24
24
|
var ErrNeedsHints = errors.new("student needs hints set before /advance");
|
|
25
|
+
var ErrSdkUpgradeRequired = errors.new("sdk upgrade required");
|
|
25
26
|
// src/contracts/content.ts
|
|
26
27
|
function inlinesToPlainText(nodes) {
|
|
27
28
|
const parts = [];
|
|
@@ -336,18 +337,22 @@ import * as errors10 from "@superbuilders/errors";
|
|
|
336
337
|
|
|
337
338
|
// src/client/transport.ts
|
|
338
339
|
import * as errors2 from "@superbuilders/errors";
|
|
340
|
+
|
|
341
|
+
// src/version.ts
|
|
342
|
+
var SDK_VERSION = "2.0.0";
|
|
343
|
+
var NPM_PACKAGE_URL = "https://www.npmjs.com/package/@superbuilders/primer-tives";
|
|
344
|
+
|
|
345
|
+
// src/client/transport.ts
|
|
339
346
|
var ADVANCE_PATH = "/api/v0/advance";
|
|
340
|
-
function
|
|
341
|
-
if (
|
|
342
|
-
return
|
|
343
|
-
}
|
|
344
|
-
if ("error" in value && value.error !== undefined && typeof value.error !== "string") {
|
|
345
|
-
return false;
|
|
347
|
+
function readStringField(value, key) {
|
|
348
|
+
if (!(key in value)) {
|
|
349
|
+
return;
|
|
346
350
|
}
|
|
347
|
-
|
|
348
|
-
|
|
351
|
+
const v = Reflect.get(value, key);
|
|
352
|
+
if (typeof v !== "string") {
|
|
353
|
+
return;
|
|
349
354
|
}
|
|
350
|
-
return
|
|
355
|
+
return v;
|
|
351
356
|
}
|
|
352
357
|
function parseAdvanceErrorBody(body) {
|
|
353
358
|
if (body.length === 0) {
|
|
@@ -359,13 +364,39 @@ function parseAdvanceErrorBody(body) {
|
|
|
359
364
|
if (parsed.error) {
|
|
360
365
|
return null;
|
|
361
366
|
}
|
|
362
|
-
|
|
367
|
+
const raw = parsed.data;
|
|
368
|
+
if (typeof raw !== "object" || raw === null) {
|
|
363
369
|
return null;
|
|
364
370
|
}
|
|
365
|
-
|
|
371
|
+
const result = {};
|
|
372
|
+
const error = readStringField(raw, "error");
|
|
373
|
+
if (error !== undefined) {
|
|
374
|
+
result.error = error;
|
|
375
|
+
}
|
|
376
|
+
const detail = readStringField(raw, "detail");
|
|
377
|
+
if (detail !== undefined) {
|
|
378
|
+
result.detail = detail;
|
|
379
|
+
}
|
|
380
|
+
const minimumSdkVersion = readStringField(raw, "minimumSdkVersion");
|
|
381
|
+
if (minimumSdkVersion !== undefined) {
|
|
382
|
+
result.minimumSdkVersion = minimumSdkVersion;
|
|
383
|
+
}
|
|
384
|
+
const receivedSdkVersion = readStringField(raw, "receivedSdkVersion");
|
|
385
|
+
if (receivedSdkVersion !== undefined) {
|
|
386
|
+
result.receivedSdkVersion = receivedSdkVersion;
|
|
387
|
+
}
|
|
388
|
+
const upgradeUrl = readStringField(raw, "upgradeUrl");
|
|
389
|
+
if (upgradeUrl !== undefined) {
|
|
390
|
+
result.upgradeUrl = upgradeUrl;
|
|
391
|
+
}
|
|
392
|
+
return result;
|
|
366
393
|
}
|
|
367
394
|
function httpSentinel(status, body) {
|
|
368
395
|
if (status === 400) {
|
|
396
|
+
const parsed = parseAdvanceErrorBody(body);
|
|
397
|
+
if (parsed?.error === "sdk_upgrade_required") {
|
|
398
|
+
return ErrSdkUpgradeRequired;
|
|
399
|
+
}
|
|
369
400
|
return ErrBadRequest;
|
|
370
401
|
}
|
|
371
402
|
if (status === 401) {
|
|
@@ -395,6 +426,29 @@ function httpSentinel(status, body) {
|
|
|
395
426
|
}
|
|
396
427
|
return ErrServerError;
|
|
397
428
|
}
|
|
429
|
+
function buildSdkUpgradeRequiredError(sentinel, text, logger) {
|
|
430
|
+
const parsed = parseAdvanceErrorBody(text);
|
|
431
|
+
if (parsed === null) {
|
|
432
|
+
logger.error("sdk upgrade required", {
|
|
433
|
+
receivedSdkVersion: null,
|
|
434
|
+
minimumSdkVersion: "<unknown>",
|
|
435
|
+
upgradeUrl: NPM_PACKAGE_URL
|
|
436
|
+
});
|
|
437
|
+
const message2 = `<missing> < <unknown>; bump @superbuilders/primer-tives at ${NPM_PACKAGE_URL}`;
|
|
438
|
+
return errors2.wrap(sentinel, message2);
|
|
439
|
+
}
|
|
440
|
+
const minimumSdkVersion = parsed.minimumSdkVersion === undefined ? "<unknown>" : parsed.minimumSdkVersion;
|
|
441
|
+
const receivedSdkVersion = parsed.receivedSdkVersion === undefined ? null : parsed.receivedSdkVersion;
|
|
442
|
+
const receivedDisplay = receivedSdkVersion === null ? "<missing>" : receivedSdkVersion;
|
|
443
|
+
const upgradeUrl = parsed.upgradeUrl === undefined ? NPM_PACKAGE_URL : parsed.upgradeUrl;
|
|
444
|
+
logger.error("sdk upgrade required", {
|
|
445
|
+
receivedSdkVersion,
|
|
446
|
+
minimumSdkVersion,
|
|
447
|
+
upgradeUrl
|
|
448
|
+
});
|
|
449
|
+
const message = `${receivedDisplay} < ${minimumSdkVersion}; bump @superbuilders/primer-tives at ${upgradeUrl}`;
|
|
450
|
+
return errors2.wrap(sentinel, message);
|
|
451
|
+
}
|
|
398
452
|
function isAbortError(err) {
|
|
399
453
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
400
454
|
return true;
|
|
@@ -406,7 +460,7 @@ function isAbortError(err) {
|
|
|
406
460
|
}
|
|
407
461
|
function createTransport(tc) {
|
|
408
462
|
const fetchFn = tc.fetch ? tc.fetch : globalThis.fetch;
|
|
409
|
-
const
|
|
463
|
+
const logger = tc.logger;
|
|
410
464
|
function transportSignal() {
|
|
411
465
|
if (tc.abort) {
|
|
412
466
|
return tc.abort.signal;
|
|
@@ -414,7 +468,7 @@ function createTransport(tc) {
|
|
|
414
468
|
return;
|
|
415
469
|
}
|
|
416
470
|
async function transport(body) {
|
|
417
|
-
|
|
471
|
+
logger.debug("transport request", {
|
|
418
472
|
intentKind: body.intent.kind,
|
|
419
473
|
subject: body.subject
|
|
420
474
|
});
|
|
@@ -423,7 +477,8 @@ function createTransport(tc) {
|
|
|
423
477
|
method: "POST",
|
|
424
478
|
headers: {
|
|
425
479
|
"Content-Type": "application/json",
|
|
426
|
-
Authorization: `Bearer ${tc.accessToken}
|
|
480
|
+
Authorization: `Bearer ${tc.accessToken}`,
|
|
481
|
+
"X-Primer-SDK-Version": SDK_VERSION
|
|
427
482
|
},
|
|
428
483
|
body: JSON.stringify(body),
|
|
429
484
|
signal: transportSignal()
|
|
@@ -434,12 +489,12 @@ function createTransport(tc) {
|
|
|
434
489
|
});
|
|
435
490
|
if (!fetchResult.ok) {
|
|
436
491
|
if (isAbortError(fetchResult.error)) {
|
|
437
|
-
|
|
492
|
+
logger.error("transport timeout", {
|
|
438
493
|
intentKind: body.intent.kind
|
|
439
494
|
});
|
|
440
495
|
return { ok: false, error: errors2.wrap(ErrTimeout, fetchResult.error.message) };
|
|
441
496
|
}
|
|
442
|
-
|
|
497
|
+
logger.error("transport network error", {
|
|
443
498
|
error: fetchResult.error
|
|
444
499
|
});
|
|
445
500
|
return { ok: false, error: errors2.wrap(ErrNetwork, fetchResult.error.message) };
|
|
@@ -450,7 +505,10 @@ function createTransport(tc) {
|
|
|
450
505
|
return "";
|
|
451
506
|
});
|
|
452
507
|
const sentinel = res.status === 422 ? ErrUnsupportedPci : httpSentinel(res.status, text);
|
|
453
|
-
|
|
508
|
+
if (errors2.is(sentinel, ErrSdkUpgradeRequired)) {
|
|
509
|
+
return { ok: false, error: buildSdkUpgradeRequiredError(sentinel, text, logger) };
|
|
510
|
+
}
|
|
511
|
+
logger.error("transport http error", {
|
|
454
512
|
status: res.status
|
|
455
513
|
});
|
|
456
514
|
return { ok: false, error: errors2.wrap(sentinel, text) };
|
|
@@ -461,12 +519,12 @@ function createTransport(tc) {
|
|
|
461
519
|
return { ok: false, error: err };
|
|
462
520
|
});
|
|
463
521
|
if (!jsonResult.ok) {
|
|
464
|
-
|
|
522
|
+
logger.error("transport json parse failed", {
|
|
465
523
|
error: jsonResult.error
|
|
466
524
|
});
|
|
467
525
|
return { ok: false, error: errors2.wrap(ErrJsonParse, jsonResult.error.message) };
|
|
468
526
|
}
|
|
469
|
-
|
|
527
|
+
logger.debug("transport success", {
|
|
470
528
|
intentKind: body.intent.kind
|
|
471
529
|
});
|
|
472
530
|
return { ok: true, data: jsonResult.data };
|
|
@@ -484,7 +542,7 @@ function poisonToJSON() {
|
|
|
484
542
|
|
|
485
543
|
// src/client/choice-state.ts
|
|
486
544
|
import * as errors3 from "@superbuilders/errors";
|
|
487
|
-
function choiceState(ctx, stimulus, interaction, options, maxChoices, minChoices) {
|
|
545
|
+
function choiceState(ctx, body, stimulus, interaction, options, maxChoices, minChoices) {
|
|
488
546
|
let submitPending;
|
|
489
547
|
let submitKey;
|
|
490
548
|
let timeoutPending;
|
|
@@ -502,7 +560,7 @@ function choiceState(ctx, stimulus, interaction, options, maxChoices, minChoices
|
|
|
502
560
|
}
|
|
503
561
|
const validation = validateSubmissionForInteraction(interaction, submission);
|
|
504
562
|
if (!validation.ok) {
|
|
505
|
-
ctx.
|
|
563
|
+
ctx.logger.error("choice submit invalid", { selectedKeys, issues: validation.issues });
|
|
506
564
|
return Promise.resolve(ctx.errored(errors3.wrap(ErrInvalidSubmission, submissionValidationMessage(validation)), "interaction", { kind: "interaction", submission }));
|
|
507
565
|
}
|
|
508
566
|
submitKey = key;
|
|
@@ -528,6 +586,7 @@ function choiceState(ctx, stimulus, interaction, options, maxChoices, minChoices
|
|
|
528
586
|
return {
|
|
529
587
|
phase: "interaction",
|
|
530
588
|
kind: "choice",
|
|
589
|
+
body,
|
|
531
590
|
stimulus,
|
|
532
591
|
interaction,
|
|
533
592
|
options,
|
|
@@ -541,7 +600,7 @@ function choiceState(ctx, stimulus, interaction, options, maxChoices, minChoices
|
|
|
541
600
|
|
|
542
601
|
// src/client/extended-text-state.ts
|
|
543
602
|
import * as errors4 from "@superbuilders/errors";
|
|
544
|
-
function extendedTextState(ctx, stimulus, interaction) {
|
|
603
|
+
function extendedTextState(ctx, body, stimulus, interaction) {
|
|
545
604
|
if (interaction.cardinality === "single") {
|
|
546
605
|
let submitText = function(value) {
|
|
547
606
|
const submission = { type: "extended-text", values: [value] };
|
|
@@ -557,7 +616,7 @@ function extendedTextState(ctx, stimulus, interaction) {
|
|
|
557
616
|
}
|
|
558
617
|
const validation = validateSubmissionForInteraction(interaction, submission);
|
|
559
618
|
if (!validation.ok) {
|
|
560
|
-
ctx.
|
|
619
|
+
ctx.logger.error("extended-text submit invalid", { value, issues: validation.issues });
|
|
561
620
|
return Promise.resolve(ctx.errored(errors4.wrap(ErrInvalidSubmission, submissionValidationMessage(validation)), "interaction", { kind: "interaction", submission }));
|
|
562
621
|
}
|
|
563
622
|
submitKey2 = key;
|
|
@@ -586,6 +645,7 @@ function extendedTextState(ctx, stimulus, interaction) {
|
|
|
586
645
|
phase: "interaction",
|
|
587
646
|
kind: "extended-text",
|
|
588
647
|
cardinality: "single",
|
|
648
|
+
body,
|
|
589
649
|
stimulus,
|
|
590
650
|
interaction,
|
|
591
651
|
submitText,
|
|
@@ -611,7 +671,7 @@ function extendedTextState(ctx, stimulus, interaction) {
|
|
|
611
671
|
}
|
|
612
672
|
const validation = validateSubmissionForInteraction(multi, submission);
|
|
613
673
|
if (!validation.ok) {
|
|
614
|
-
ctx.
|
|
674
|
+
ctx.logger.error("extended-text submit invalid", { values, issues: validation.issues });
|
|
615
675
|
return Promise.resolve(ctx.errored(errors4.wrap(ErrInvalidSubmission, submissionValidationMessage(validation)), "interaction", { kind: "interaction", submission }));
|
|
616
676
|
}
|
|
617
677
|
submitKey = key;
|
|
@@ -638,6 +698,7 @@ function extendedTextState(ctx, stimulus, interaction) {
|
|
|
638
698
|
phase: "interaction",
|
|
639
699
|
kind: "extended-text",
|
|
640
700
|
cardinality: "multiple",
|
|
701
|
+
body,
|
|
641
702
|
stimulus,
|
|
642
703
|
interaction: multi,
|
|
643
704
|
maxStrings: multi.maxStrings,
|
|
@@ -649,10 +710,11 @@ function extendedTextState(ctx, stimulus, interaction) {
|
|
|
649
710
|
}
|
|
650
711
|
|
|
651
712
|
// src/client/feedback-state.ts
|
|
652
|
-
function feedbackState(ctx, stimulus, interaction, submission, isCorrect, feedbackContent, review) {
|
|
713
|
+
function feedbackState(ctx, body, stimulus, interaction, submission, isCorrect, feedbackContent, review) {
|
|
653
714
|
let pending;
|
|
654
715
|
return {
|
|
655
716
|
phase: "feedback",
|
|
717
|
+
body,
|
|
656
718
|
stimulus,
|
|
657
719
|
interaction,
|
|
658
720
|
submission,
|
|
@@ -672,7 +734,7 @@ function feedbackState(ctx, stimulus, interaction, submission, isCorrect, feedba
|
|
|
672
734
|
|
|
673
735
|
// src/client/match-state.ts
|
|
674
736
|
import * as errors5 from "@superbuilders/errors";
|
|
675
|
-
function matchState(ctx, stimulus, interaction) {
|
|
737
|
+
function matchState(ctx, body, stimulus, interaction) {
|
|
676
738
|
let submitPending;
|
|
677
739
|
let submitKey;
|
|
678
740
|
let timeoutPending;
|
|
@@ -690,7 +752,7 @@ function matchState(ctx, stimulus, interaction) {
|
|
|
690
752
|
}
|
|
691
753
|
const validation = validateSubmissionForInteraction(interaction, submission);
|
|
692
754
|
if (!validation.ok) {
|
|
693
|
-
ctx.
|
|
755
|
+
ctx.logger.error("match submit invalid", { pairs, issues: validation.issues });
|
|
694
756
|
return Promise.resolve(ctx.errored(errors5.wrap(ErrInvalidSubmission, submissionValidationMessage(validation)), "interaction", { kind: "interaction", submission }));
|
|
695
757
|
}
|
|
696
758
|
submitKey = key;
|
|
@@ -716,6 +778,7 @@ function matchState(ctx, stimulus, interaction) {
|
|
|
716
778
|
return {
|
|
717
779
|
phase: "interaction",
|
|
718
780
|
kind: "match",
|
|
781
|
+
body,
|
|
719
782
|
stimulus,
|
|
720
783
|
interaction,
|
|
721
784
|
sourceChoices: interaction.sourceChoices,
|
|
@@ -729,10 +792,11 @@ function matchState(ctx, stimulus, interaction) {
|
|
|
729
792
|
}
|
|
730
793
|
|
|
731
794
|
// src/client/observation-state.ts
|
|
732
|
-
function observationState(ctx, stimulus) {
|
|
795
|
+
function observationState(ctx, body, stimulus) {
|
|
733
796
|
let pending;
|
|
734
797
|
return {
|
|
735
798
|
phase: "observation",
|
|
799
|
+
body,
|
|
736
800
|
stimulus,
|
|
737
801
|
advance: function advance() {
|
|
738
802
|
if (pending) {
|
|
@@ -747,7 +811,7 @@ function observationState(ctx, stimulus) {
|
|
|
747
811
|
|
|
748
812
|
// src/client/order-state.ts
|
|
749
813
|
import * as errors6 from "@superbuilders/errors";
|
|
750
|
-
function orderState(ctx, stimulus, interaction) {
|
|
814
|
+
function orderState(ctx, body, stimulus, interaction) {
|
|
751
815
|
let submitPending;
|
|
752
816
|
let submitKey;
|
|
753
817
|
let timeoutPending;
|
|
@@ -765,7 +829,7 @@ function orderState(ctx, stimulus, interaction) {
|
|
|
765
829
|
}
|
|
766
830
|
const validation = validateSubmissionForInteraction(interaction, submission);
|
|
767
831
|
if (!validation.ok) {
|
|
768
|
-
ctx.
|
|
832
|
+
ctx.logger.error("order submit invalid", { orderedKeys, issues: validation.issues });
|
|
769
833
|
return Promise.resolve(ctx.errored(errors6.wrap(ErrInvalidSubmission, submissionValidationMessage(validation)), "interaction", { kind: "interaction", submission }));
|
|
770
834
|
}
|
|
771
835
|
submitKey = key;
|
|
@@ -791,6 +855,7 @@ function orderState(ctx, stimulus, interaction) {
|
|
|
791
855
|
return {
|
|
792
856
|
phase: "interaction",
|
|
793
857
|
kind: "order",
|
|
858
|
+
body,
|
|
794
859
|
stimulus,
|
|
795
860
|
interaction,
|
|
796
861
|
choices: interaction.choices,
|
|
@@ -804,7 +869,7 @@ function orderState(ctx, stimulus, interaction) {
|
|
|
804
869
|
|
|
805
870
|
// src/client/pci-state.ts
|
|
806
871
|
import * as errors7 from "@superbuilders/errors";
|
|
807
|
-
function pciInteractionState(ctx, stimulus, interaction) {
|
|
872
|
+
function pciInteractionState(ctx, body, stimulus, interaction) {
|
|
808
873
|
let submitPending;
|
|
809
874
|
let submitKey;
|
|
810
875
|
let timeoutPending;
|
|
@@ -821,7 +886,7 @@ function pciInteractionState(ctx, stimulus, interaction) {
|
|
|
821
886
|
}
|
|
822
887
|
return Promise.resolve(ctx.errored(errors7.wrap(ErrConflict, "cannot submit a different pci payload while submit is in flight"), "interaction", { kind: "interaction", submission }));
|
|
823
888
|
}
|
|
824
|
-
ctx.
|
|
889
|
+
ctx.logger.debug("pci submit", { pciId });
|
|
825
890
|
submitKey = key;
|
|
826
891
|
submitPending = ctx.execute({ kind: "interaction", submission }, "interaction").finally(function clearPending() {
|
|
827
892
|
submitPending = undefined;
|
|
@@ -837,7 +902,7 @@ function pciInteractionState(ctx, stimulus, interaction) {
|
|
|
837
902
|
if (timeoutPending) {
|
|
838
903
|
return timeoutPending;
|
|
839
904
|
}
|
|
840
|
-
ctx.
|
|
905
|
+
ctx.logger.debug("pci timeout", { pciId });
|
|
841
906
|
timeoutPending = ctx.execute(intent, "timeout").finally(function clearPending() {
|
|
842
907
|
timeoutPending = undefined;
|
|
843
908
|
});
|
|
@@ -846,6 +911,7 @@ function pciInteractionState(ctx, stimulus, interaction) {
|
|
|
846
911
|
return {
|
|
847
912
|
phase: "interaction",
|
|
848
913
|
kind: "portable-custom",
|
|
914
|
+
body,
|
|
849
915
|
stimulus,
|
|
850
916
|
interaction,
|
|
851
917
|
pciId,
|
|
@@ -858,7 +924,7 @@ function pciInteractionState(ctx, stimulus, interaction) {
|
|
|
858
924
|
|
|
859
925
|
// src/client/text-entry-state.ts
|
|
860
926
|
import * as errors8 from "@superbuilders/errors";
|
|
861
|
-
function textEntryState(ctx, stimulus, interaction) {
|
|
927
|
+
function textEntryState(ctx, body, stimulus, interaction) {
|
|
862
928
|
let submitPending;
|
|
863
929
|
let submitKey;
|
|
864
930
|
let timeoutPending;
|
|
@@ -876,7 +942,7 @@ function textEntryState(ctx, stimulus, interaction) {
|
|
|
876
942
|
}
|
|
877
943
|
const validation = validateSubmissionForInteraction(interaction, submission);
|
|
878
944
|
if (!validation.ok) {
|
|
879
|
-
ctx.
|
|
945
|
+
ctx.logger.error("text-entry submit invalid", { value, issues: validation.issues });
|
|
880
946
|
return Promise.resolve(ctx.errored(errors8.wrap(ErrInvalidSubmission, submissionValidationMessage(validation)), "interaction", { kind: "interaction", submission }));
|
|
881
947
|
}
|
|
882
948
|
submitKey = key;
|
|
@@ -902,6 +968,7 @@ function textEntryState(ctx, stimulus, interaction) {
|
|
|
902
968
|
return {
|
|
903
969
|
phase: "interaction",
|
|
904
970
|
kind: "text-entry",
|
|
971
|
+
body,
|
|
905
972
|
stimulus,
|
|
906
973
|
interaction,
|
|
907
974
|
submitText,
|
|
@@ -918,6 +985,7 @@ var FATAL_SENTINELS = [
|
|
|
918
985
|
ErrForbidden,
|
|
919
986
|
ErrNotFound,
|
|
920
987
|
ErrNeedsHints,
|
|
988
|
+
ErrSdkUpgradeRequired,
|
|
921
989
|
ErrUnsupportedPci
|
|
922
990
|
];
|
|
923
991
|
function isFatalError(err) {
|
|
@@ -932,13 +1000,24 @@ function isRetriableError(err) {
|
|
|
932
1000
|
return !errors9.is(err, ErrInvalidSubmission);
|
|
933
1001
|
}
|
|
934
1002
|
function makeSession(sc) {
|
|
935
|
-
const
|
|
1003
|
+
const logger = sc.logger;
|
|
936
1004
|
function resolve(result) {
|
|
937
1005
|
switch (result.outcome) {
|
|
938
1006
|
case "advanced":
|
|
939
|
-
return fromAdvanced(result.stimulus, result.interaction);
|
|
940
|
-
case "submitted":
|
|
941
|
-
|
|
1007
|
+
return fromAdvanced(result.frame.body, result.frame.stimulus, result.frame.interaction);
|
|
1008
|
+
case "submitted": {
|
|
1009
|
+
const interaction = result.frame.interaction;
|
|
1010
|
+
if (interaction === null) {
|
|
1011
|
+
logger.error("submitted result without interaction");
|
|
1012
|
+
return {
|
|
1013
|
+
phase: "fatal",
|
|
1014
|
+
error: errors9.wrap(ErrBadRequest, "submitted result missing interaction"),
|
|
1015
|
+
retriable: false,
|
|
1016
|
+
toJSON: poisonToJSON
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
return feedbackState(ctx, result.frame.body, result.frame.stimulus, interaction, result.submission, result.isCorrect, result.feedbackContent, result.review);
|
|
1020
|
+
}
|
|
942
1021
|
case "completed":
|
|
943
1022
|
return { phase: "completed", toJSON: poisonToJSON };
|
|
944
1023
|
}
|
|
@@ -952,13 +1031,13 @@ function makeSession(sc) {
|
|
|
952
1031
|
retriable,
|
|
953
1032
|
retry: function retry() {
|
|
954
1033
|
if (!retriable) {
|
|
955
|
-
|
|
1034
|
+
logger.debug("retry ignored for non-retriable error", { failedPhase });
|
|
956
1035
|
return Promise.resolve(state);
|
|
957
1036
|
}
|
|
958
1037
|
if (pending) {
|
|
959
1038
|
return pending;
|
|
960
1039
|
}
|
|
961
|
-
|
|
1040
|
+
logger.debug("retrying from errored state", { failedPhase });
|
|
962
1041
|
pending = execute(intent, failedPhase);
|
|
963
1042
|
return pending;
|
|
964
1043
|
},
|
|
@@ -975,7 +1054,7 @@ function makeSession(sc) {
|
|
|
975
1054
|
const result = await sc.transport(body);
|
|
976
1055
|
if (!result.ok) {
|
|
977
1056
|
if (isFatalError(result.error)) {
|
|
978
|
-
|
|
1057
|
+
logger.error("fatal transport error", { error: result.error, phase });
|
|
979
1058
|
return { phase: "fatal", error: result.error, retriable: false, toJSON: poisonToJSON };
|
|
980
1059
|
}
|
|
981
1060
|
return errored(result.error, phase, intent);
|
|
@@ -990,13 +1069,13 @@ function makeSession(sc) {
|
|
|
990
1069
|
}
|
|
991
1070
|
return false;
|
|
992
1071
|
}
|
|
993
|
-
function fromAdvanced(stimulus, interaction) {
|
|
1072
|
+
function fromAdvanced(body, stimulus, interaction) {
|
|
994
1073
|
if (interaction === null) {
|
|
995
|
-
return observationState(ctx, stimulus);
|
|
1074
|
+
return observationState(ctx, body, stimulus);
|
|
996
1075
|
}
|
|
997
1076
|
if (interaction.type === "portable-custom") {
|
|
998
1077
|
if (!isPciSupported(interaction.pciId)) {
|
|
999
|
-
|
|
1078
|
+
logger.error("unsupported pci in frame", { pciId: interaction.pciId });
|
|
1000
1079
|
return {
|
|
1001
1080
|
phase: "fatal",
|
|
1002
1081
|
error: errors9.wrap(ErrUnsupportedPci, `pci '${interaction.pciId}'`),
|
|
@@ -1005,25 +1084,25 @@ function makeSession(sc) {
|
|
|
1005
1084
|
};
|
|
1006
1085
|
}
|
|
1007
1086
|
}
|
|
1008
|
-
return pendingInteractionState(stimulus, interaction);
|
|
1087
|
+
return pendingInteractionState(body, stimulus, interaction);
|
|
1009
1088
|
}
|
|
1010
|
-
function pendingInteractionState(stimulus, interaction) {
|
|
1089
|
+
function pendingInteractionState(body, stimulus, interaction) {
|
|
1011
1090
|
switch (interaction.type) {
|
|
1012
1091
|
case "choice":
|
|
1013
|
-
return choiceState(ctx, stimulus, interaction, interaction.options, interaction.maxChoices, interaction.minChoices);
|
|
1092
|
+
return choiceState(ctx, body, stimulus, interaction, interaction.options, interaction.maxChoices, interaction.minChoices);
|
|
1014
1093
|
case "text-entry":
|
|
1015
|
-
return textEntryState(ctx, stimulus, interaction);
|
|
1094
|
+
return textEntryState(ctx, body, stimulus, interaction);
|
|
1016
1095
|
case "extended-text":
|
|
1017
|
-
return extendedTextState(ctx, stimulus, interaction);
|
|
1096
|
+
return extendedTextState(ctx, body, stimulus, interaction);
|
|
1018
1097
|
case "order":
|
|
1019
|
-
return orderState(ctx, stimulus, interaction);
|
|
1098
|
+
return orderState(ctx, body, stimulus, interaction);
|
|
1020
1099
|
case "match":
|
|
1021
|
-
return matchState(ctx, stimulus, interaction);
|
|
1100
|
+
return matchState(ctx, body, stimulus, interaction);
|
|
1022
1101
|
case "portable-custom":
|
|
1023
|
-
return pciInteractionState(ctx, stimulus, interaction);
|
|
1102
|
+
return pciInteractionState(ctx, body, stimulus, interaction);
|
|
1024
1103
|
}
|
|
1025
1104
|
}
|
|
1026
|
-
const ctx = {
|
|
1105
|
+
const ctx = { logger, execute, errored };
|
|
1027
1106
|
return { execute };
|
|
1028
1107
|
}
|
|
1029
1108
|
|
|
@@ -1037,9 +1116,9 @@ function isMalformedJws(token) {
|
|
|
1037
1116
|
return dotCount !== 2;
|
|
1038
1117
|
}
|
|
1039
1118
|
function create(config) {
|
|
1040
|
-
const
|
|
1119
|
+
const logger = config.logger;
|
|
1041
1120
|
if (isMalformedJws(config.accessToken)) {
|
|
1042
|
-
|
|
1121
|
+
logger.error("malformed access token", { prefix: ACCESS_TOKEN_PREFIX });
|
|
1043
1122
|
throw errors10.wrap(ErrMalformedAccessToken, `token must start with '${ACCESS_TOKEN_PREFIX}' and contain two dots`);
|
|
1044
1123
|
}
|
|
1045
1124
|
const transport = createTransport({
|
|
@@ -1048,15 +1127,15 @@ function create(config) {
|
|
|
1048
1127
|
origin: config.origin,
|
|
1049
1128
|
fetch: config.fetch,
|
|
1050
1129
|
abort: config.abort,
|
|
1051
|
-
|
|
1130
|
+
logger
|
|
1052
1131
|
});
|
|
1053
1132
|
let startPromise;
|
|
1054
1133
|
async function doStart() {
|
|
1055
|
-
|
|
1134
|
+
logger.debug("start", { subject: config.subject });
|
|
1056
1135
|
const s = makeSession({
|
|
1057
1136
|
supportedPcis: config.supportedPcis,
|
|
1058
1137
|
subject: config.subject,
|
|
1059
|
-
|
|
1138
|
+
logger,
|
|
1060
1139
|
transport
|
|
1061
1140
|
});
|
|
1062
1141
|
return s.execute({ kind: "observation" }, "observation");
|
|
@@ -1064,7 +1143,7 @@ function create(config) {
|
|
|
1064
1143
|
return {
|
|
1065
1144
|
start() {
|
|
1066
1145
|
if (startPromise) {
|
|
1067
|
-
|
|
1146
|
+
logger.debug("start already called");
|
|
1068
1147
|
return startPromise;
|
|
1069
1148
|
}
|
|
1070
1149
|
startPromise = doStart();
|
|
@@ -1076,4 +1155,4 @@ export {
|
|
|
1076
1155
|
create
|
|
1077
1156
|
};
|
|
1078
1157
|
|
|
1079
|
-
//# debugId=
|
|
1158
|
+
//# debugId=5A77D78E02028F9D64756E2164756E21
|