@superbuilders/primer-tives 0.0.3 → 0.0.4

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 (42) hide show
  1. package/README.md +40 -46
  2. package/dist/choice-state.d.ts +8 -0
  3. package/dist/choice-state.d.ts.map +1 -0
  4. package/dist/client.d.ts +2 -8
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/consumed.d.ts +6 -0
  7. package/dist/consumed.d.ts.map +1 -0
  8. package/dist/errors.d.ts +2 -1
  9. package/dist/errors.d.ts.map +1 -1
  10. package/dist/extended-text-state.d.ts +8 -0
  11. package/dist/extended-text-state.d.ts.map +1 -0
  12. package/dist/feedback-state.d.ts +7 -0
  13. package/dist/feedback-state.d.ts.map +1 -0
  14. package/dist/index.d.ts +9 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +573 -0
  17. package/dist/index.js.map +21 -0
  18. package/dist/observation-state.d.ts +6 -0
  19. package/dist/observation-state.d.ts.map +1 -0
  20. package/dist/pci-state.d.ts +6 -0
  21. package/dist/pci-state.d.ts.map +1 -0
  22. package/dist/session-context.d.ts +24 -0
  23. package/dist/session-context.d.ts.map +1 -0
  24. package/dist/session.d.ts +16 -0
  25. package/dist/session.d.ts.map +1 -0
  26. package/dist/text-entry-state.d.ts +8 -0
  27. package/dist/text-entry-state.d.ts.map +1 -0
  28. package/dist/transport.d.ts +46 -0
  29. package/dist/transport.d.ts.map +1 -0
  30. package/dist/types.d.ts +5 -2
  31. package/dist/types.d.ts.map +1 -1
  32. package/package.json +4 -20
  33. package/dist/client.js +0 -400
  34. package/dist/client.js.map +0 -11
  35. package/dist/content.js +0 -27
  36. package/dist/content.js.map +0 -10
  37. package/dist/errors.js +0 -36
  38. package/dist/errors.js.map +0 -10
  39. package/dist/pci.js +0 -2
  40. package/dist/pci.js.map +0 -9
  41. package/dist/types.js +0 -2
  42. package/dist/types.js.map +0 -9
package/dist/index.js ADDED
@@ -0,0 +1,573 @@
1
+ // src/client.ts
2
+ import * as errors6 from "@superbuilders/errors";
3
+
4
+ // src/errors.ts
5
+ import * as errors from "@superbuilders/errors";
6
+ var ErrNetwork = errors.new("network");
7
+ var ErrJsonParse = errors.new("json parse");
8
+ var ErrUnsupportedPci = errors.new("unsupported pci");
9
+ var ErrInvalidPublishableKey = errors.new("invalid publishable key");
10
+ var ErrBadRequest = errors.new("bad request");
11
+ var ErrServerError = errors.new("server error");
12
+ var ErrTimeout = errors.new("timeout");
13
+ var ErrForbidden = errors.new("forbidden");
14
+ var ErrNotFound = errors.new("not found");
15
+ var ErrConflict = errors.new("conflict");
16
+ var ErrRateLimited = errors.new("rate limited");
17
+ var ErrServiceUnavailable = errors.new("service unavailable");
18
+ var ErrNotSerializable = errors.new("PrimerState is live in-memory state and must not be serialized or stored");
19
+ var ErrInvalidSubmission = errors.new("invalid submission");
20
+ var ErrMalformedPublishableKey = errors.new("malformed publishable key");
21
+ var ErrStateConsumed = errors.new("state already consumed");
22
+
23
+ // src/transport.ts
24
+ import * as errors2 from "@superbuilders/errors";
25
+ var ADVANCE_PATH = "/api/v0/advance";
26
+ function httpSentinel(status) {
27
+ if (status === 400) {
28
+ return ErrBadRequest;
29
+ }
30
+ if (status === 401) {
31
+ return ErrInvalidPublishableKey;
32
+ }
33
+ if (status === 403) {
34
+ return ErrForbidden;
35
+ }
36
+ if (status === 404) {
37
+ return ErrNotFound;
38
+ }
39
+ if (status === 409) {
40
+ return ErrConflict;
41
+ }
42
+ if (status === 422) {
43
+ return ErrUnsupportedPci;
44
+ }
45
+ if (status === 429) {
46
+ return ErrRateLimited;
47
+ }
48
+ if (status === 502 || status === 503 || status === 504) {
49
+ return ErrServiceUnavailable;
50
+ }
51
+ return ErrServerError;
52
+ }
53
+ function isAbortError(err) {
54
+ if (err instanceof DOMException && err.name === "AbortError") {
55
+ return true;
56
+ }
57
+ if (err instanceof DOMException && err.name === "TimeoutError") {
58
+ return true;
59
+ }
60
+ return false;
61
+ }
62
+ function createTransport(tc) {
63
+ const fetchFn = tc.fetch ? tc.fetch : globalThis.fetch;
64
+ const log = tc.log;
65
+ function transportSignal() {
66
+ if (tc.abort) {
67
+ return tc.abort.signal;
68
+ }
69
+ return;
70
+ }
71
+ async function transport(body) {
72
+ log?.debug("transport request", {
73
+ studentId: body.studentId,
74
+ intentKind: body.intent.kind
75
+ });
76
+ const url = tc.origin ? `${tc.origin}${ADVANCE_PATH}` : ADVANCE_PATH;
77
+ const fetchResult = await fetchFn(url, {
78
+ method: "POST",
79
+ headers: {
80
+ "Content-Type": "application/json",
81
+ "X-Primer-Publishable-Key": tc.publishableKey
82
+ },
83
+ body: JSON.stringify(body),
84
+ signal: transportSignal()
85
+ }).then(function ok(r) {
86
+ return { ok: true, response: r };
87
+ }, function fail(err) {
88
+ return { ok: false, error: err };
89
+ });
90
+ if (!fetchResult.ok) {
91
+ if (isAbortError(fetchResult.error)) {
92
+ log?.error("transport timeout", {
93
+ studentId: body.studentId,
94
+ intentKind: body.intent.kind
95
+ });
96
+ return { ok: false, error: errors2.wrap(ErrTimeout, fetchResult.error.message) };
97
+ }
98
+ log?.error("transport network error", {
99
+ studentId: body.studentId,
100
+ error: fetchResult.error
101
+ });
102
+ return { ok: false, error: errors2.wrap(ErrNetwork, fetchResult.error.message) };
103
+ }
104
+ const res = fetchResult.response;
105
+ if (!res.ok) {
106
+ const text = await res.text().catch(function fallback() {
107
+ return "";
108
+ });
109
+ const sentinel = httpSentinel(res.status);
110
+ log?.error("transport http error", {
111
+ studentId: body.studentId,
112
+ status: res.status
113
+ });
114
+ return { ok: false, error: errors2.wrap(sentinel, text) };
115
+ }
116
+ const jsonResult = await res.json().then(function ok(data) {
117
+ return { ok: true, data };
118
+ }, function fail(err) {
119
+ return { ok: false, error: err };
120
+ });
121
+ if (!jsonResult.ok) {
122
+ log?.error("transport json parse failed", {
123
+ studentId: body.studentId,
124
+ error: jsonResult.error
125
+ });
126
+ return { ok: false, error: errors2.wrap(ErrJsonParse, jsonResult.error.message) };
127
+ }
128
+ log?.debug("transport success", {
129
+ studentId: body.studentId,
130
+ intentKind: body.intent.kind
131
+ });
132
+ return { ok: true, data: jsonResult.data };
133
+ }
134
+ return transport;
135
+ }
136
+
137
+ // src/session.ts
138
+ import * as errors5 from "@superbuilders/errors";
139
+
140
+ // src/consumed.ts
141
+ function poisonToJSON() {
142
+ throw ErrNotSerializable;
143
+ }
144
+ var CONSUMED = { phase: "consumed", toJSON: poisonToJSON };
145
+ var CONSUMED_PROMISE = Promise.resolve(CONSUMED);
146
+
147
+ // src/choice-state.ts
148
+ import * as errors3 from "@superbuilders/errors";
149
+ function findUnknownKey(selectedKeys, options) {
150
+ const optionIds = new Set(options.map(function getId(o) {
151
+ return o.identifier;
152
+ }));
153
+ for (const key of selectedKeys) {
154
+ if (!optionIds.has(key)) {
155
+ return key;
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+ function validateChoiceSubmission(log, selectedKeys, options, maxChoices, minChoices) {
161
+ if (selectedKeys.length < minChoices) {
162
+ log?.error("choice submit below minChoices", { selectedKeys, minChoices });
163
+ return errors3.wrap(ErrInvalidSubmission, `need at least ${minChoices} selections`);
164
+ }
165
+ if (selectedKeys.length > maxChoices) {
166
+ log?.error("choice submit above maxChoices", { selectedKeys, maxChoices });
167
+ return errors3.wrap(ErrInvalidSubmission, `at most ${maxChoices} selections`);
168
+ }
169
+ const uniqueKeys = new Set(selectedKeys);
170
+ if (uniqueKeys.size !== selectedKeys.length) {
171
+ log?.error("choice submit has duplicates", { selectedKeys });
172
+ return errors3.wrap(ErrInvalidSubmission, "duplicate selections");
173
+ }
174
+ const unknownKey = findUnknownKey(selectedKeys, options);
175
+ if (unknownKey) {
176
+ log?.error("choice submit has unknown key", { key: unknownKey });
177
+ return errors3.wrap(ErrInvalidSubmission, `unknown option '${unknownKey}'`);
178
+ }
179
+ return null;
180
+ }
181
+ function choiceState(ctx, stimulus, interaction, options, maxChoices, minChoices) {
182
+ let consumed = false;
183
+ return {
184
+ phase: "interaction",
185
+ kind: "choice",
186
+ stimulus,
187
+ interaction,
188
+ options,
189
+ maxChoices,
190
+ minChoices,
191
+ submitChoice: function submitChoice(selectedKeys) {
192
+ if (consumed) {
193
+ ctx.log?.debug("choice submit already consumed");
194
+ return CONSUMED_PROMISE;
195
+ }
196
+ const validationError = validateChoiceSubmission(ctx.log, selectedKeys, options, maxChoices, minChoices);
197
+ if (validationError) {
198
+ return Promise.resolve(ctx.errored(validationError, "interaction", {
199
+ kind: "interaction",
200
+ submission: { type: "choice", selectedKeys }
201
+ }));
202
+ }
203
+ consumed = true;
204
+ return ctx.execute({ kind: "interaction", submission: { type: "choice", selectedKeys } }, "interaction");
205
+ },
206
+ timeout: function timeout() {
207
+ if (consumed) {
208
+ ctx.log?.debug("choice timeout already consumed");
209
+ return CONSUMED_PROMISE;
210
+ }
211
+ consumed = true;
212
+ return ctx.execute({ kind: "timeout" }, "timeout");
213
+ },
214
+ toJSON: poisonToJSON
215
+ };
216
+ }
217
+
218
+ // src/extended-text-state.ts
219
+ import * as errors4 from "@superbuilders/errors";
220
+ function validateExtendedTextSubmission(log, values, minStrings, maxStrings) {
221
+ if (values.length < minStrings) {
222
+ log?.error("extended-text submit below minStrings", { count: values.length, minStrings });
223
+ return errors4.wrap(ErrInvalidSubmission, `need at least ${minStrings} values`);
224
+ }
225
+ if (values.length > maxStrings) {
226
+ log?.error("extended-text submit above maxStrings", { count: values.length, maxStrings });
227
+ return errors4.wrap(ErrInvalidSubmission, `at most ${maxStrings} values`);
228
+ }
229
+ return null;
230
+ }
231
+ function extendedTextState(ctx, stimulus, interaction) {
232
+ const maxStrings = interaction.maxStrings;
233
+ const minStrings = interaction.minStrings;
234
+ if (maxStrings === 1) {
235
+ let consumed2 = false;
236
+ return {
237
+ phase: "interaction",
238
+ kind: "extended-text",
239
+ cardinality: "single",
240
+ stimulus,
241
+ interaction,
242
+ submitText: function submitText(value) {
243
+ if (consumed2) {
244
+ ctx.log?.debug("extended-text single submit already consumed");
245
+ return CONSUMED_PROMISE;
246
+ }
247
+ consumed2 = true;
248
+ return ctx.execute({ kind: "interaction", submission: { type: "extended-text", values: [value] } }, "interaction");
249
+ },
250
+ timeout: function timeout() {
251
+ if (consumed2) {
252
+ ctx.log?.debug("extended-text single timeout already consumed");
253
+ return CONSUMED_PROMISE;
254
+ }
255
+ consumed2 = true;
256
+ return ctx.execute({ kind: "timeout" }, "timeout");
257
+ },
258
+ toJSON: poisonToJSON
259
+ };
260
+ }
261
+ let consumed = false;
262
+ return {
263
+ phase: "interaction",
264
+ kind: "extended-text",
265
+ cardinality: "multiple",
266
+ stimulus,
267
+ interaction,
268
+ maxStrings,
269
+ minStrings,
270
+ submitTexts: function submitTexts(values) {
271
+ if (consumed) {
272
+ ctx.log?.debug("extended-text multiple submit already consumed");
273
+ return CONSUMED_PROMISE;
274
+ }
275
+ const validationError = validateExtendedTextSubmission(ctx.log, values, minStrings, maxStrings);
276
+ if (validationError) {
277
+ return Promise.resolve(ctx.errored(validationError, "interaction", {
278
+ kind: "interaction",
279
+ submission: { type: "extended-text", values }
280
+ }));
281
+ }
282
+ consumed = true;
283
+ return ctx.execute({ kind: "interaction", submission: { type: "extended-text", values } }, "interaction");
284
+ },
285
+ timeout: function timeout() {
286
+ if (consumed) {
287
+ ctx.log?.debug("extended-text multiple timeout already consumed");
288
+ return CONSUMED_PROMISE;
289
+ }
290
+ consumed = true;
291
+ return ctx.execute({ kind: "timeout" }, "timeout");
292
+ },
293
+ toJSON: poisonToJSON
294
+ };
295
+ }
296
+
297
+ // src/feedback-state.ts
298
+ function feedbackState(ctx, stimulus, interaction, submission, isCorrect, feedbackContent, correctAnswer) {
299
+ let consumed = false;
300
+ return {
301
+ phase: "feedback",
302
+ stimulus,
303
+ interaction,
304
+ submission,
305
+ isCorrect,
306
+ feedbackContent,
307
+ correctAnswer,
308
+ advance: function advance() {
309
+ if (consumed) {
310
+ ctx.log?.debug("feedback advance already consumed");
311
+ return CONSUMED_PROMISE;
312
+ }
313
+ consumed = true;
314
+ return ctx.execute({ kind: "observation" }, "observation");
315
+ },
316
+ toJSON: poisonToJSON
317
+ };
318
+ }
319
+
320
+ // src/observation-state.ts
321
+ function observationState(ctx, stimulus) {
322
+ let consumed = false;
323
+ return {
324
+ phase: "observation",
325
+ stimulus,
326
+ advance: function advance() {
327
+ if (consumed) {
328
+ ctx.log?.debug("observation advance already consumed");
329
+ return CONSUMED_PROMISE;
330
+ }
331
+ consumed = true;
332
+ return ctx.execute({ kind: "observation" }, "observation");
333
+ },
334
+ toJSON: poisonToJSON
335
+ };
336
+ }
337
+
338
+ // src/pci-state.ts
339
+ function pciInteractionState(ctx, stimulus, interaction) {
340
+ let consumed = false;
341
+ const { pciId, properties } = interaction;
342
+ function submit(value) {
343
+ if (consumed) {
344
+ ctx.log?.debug("pci submit already consumed", { pciId });
345
+ return CONSUMED_PROMISE;
346
+ }
347
+ consumed = true;
348
+ ctx.log?.debug("pci submit", { pciId });
349
+ const submission = { type: "portable-custom", pciId, value };
350
+ return ctx.execute({ kind: "interaction", submission }, "interaction");
351
+ }
352
+ function timeout() {
353
+ if (consumed) {
354
+ ctx.log?.debug("pci timeout already consumed", { pciId });
355
+ return CONSUMED_PROMISE;
356
+ }
357
+ consumed = true;
358
+ ctx.log?.debug("pci timeout", { pciId });
359
+ return ctx.execute({ kind: "timeout" }, "timeout");
360
+ }
361
+ return {
362
+ phase: "interaction",
363
+ kind: "portable-custom",
364
+ stimulus,
365
+ interaction,
366
+ pciId,
367
+ properties,
368
+ submit,
369
+ timeout,
370
+ toJSON: poisonToJSON
371
+ };
372
+ }
373
+
374
+ // src/text-entry-state.ts
375
+ function textEntryState(ctx, stimulus, interaction) {
376
+ let consumed = false;
377
+ return {
378
+ phase: "interaction",
379
+ kind: "text-entry",
380
+ stimulus,
381
+ interaction,
382
+ submitText: function submitText(value) {
383
+ if (consumed) {
384
+ ctx.log?.debug("text-entry submit already consumed");
385
+ return CONSUMED_PROMISE;
386
+ }
387
+ consumed = true;
388
+ return ctx.execute({ kind: "interaction", submission: { type: "text-entry", value } }, "interaction");
389
+ },
390
+ timeout: function timeout() {
391
+ if (consumed) {
392
+ ctx.log?.debug("text-entry timeout already consumed");
393
+ return CONSUMED_PROMISE;
394
+ }
395
+ consumed = true;
396
+ return ctx.execute({ kind: "timeout" }, "timeout");
397
+ },
398
+ toJSON: poisonToJSON
399
+ };
400
+ }
401
+
402
+ // src/session.ts
403
+ function makeSession(sc) {
404
+ const log = sc.log;
405
+ function resolve(result) {
406
+ switch (result.outcome) {
407
+ case "advanced":
408
+ return fromAdvanced(result.stimulus, result.interaction);
409
+ case "submitted":
410
+ return feedbackState(ctx, result.stimulus, result.interaction, result.submission, result.isCorrect, result.feedbackContent, result.correctAnswer);
411
+ case "completed":
412
+ return { phase: "completed", toJSON: poisonToJSON };
413
+ }
414
+ }
415
+ function errored(error, failedPhase, intent) {
416
+ let retryConsumed = false;
417
+ return {
418
+ phase: "errored",
419
+ error,
420
+ failedPhase,
421
+ retry: function retry() {
422
+ if (retryConsumed) {
423
+ log?.debug("retry already consumed");
424
+ return CONSUMED_PROMISE;
425
+ }
426
+ retryConsumed = true;
427
+ log?.debug("retrying from errored state", { failedPhase });
428
+ return execute(intent, failedPhase);
429
+ },
430
+ toJSON: poisonToJSON
431
+ };
432
+ }
433
+ async function execute(intent, phase) {
434
+ const body = {
435
+ studentId: sc.studentId,
436
+ supportedPcis: sc.supportedPcis,
437
+ intent
438
+ };
439
+ const result = await sc.transport(body);
440
+ if (!result.ok) {
441
+ if (errors5.is(result.error, ErrConflict)) {
442
+ log?.debug("state already consumed server-side", { phase });
443
+ return CONSUMED;
444
+ }
445
+ return errored(result.error, phase, intent);
446
+ }
447
+ return resolve(result.data);
448
+ }
449
+ function isPciSupported(pciId) {
450
+ for (const id of sc.supportedPcis) {
451
+ if (id === pciId) {
452
+ return true;
453
+ }
454
+ }
455
+ return false;
456
+ }
457
+ function fromAdvanced(stimulus, interaction) {
458
+ if (interaction === null) {
459
+ return observationState(ctx, stimulus);
460
+ }
461
+ if (interaction.type === "portable-custom") {
462
+ if (!isPciSupported(interaction.pciId)) {
463
+ log?.error("unsupported pci in frame", { pciId: interaction.pciId });
464
+ return {
465
+ phase: "fatal",
466
+ error: errors5.wrap(ErrUnsupportedPci, `pci '${interaction.pciId}'`),
467
+ toJSON: poisonToJSON
468
+ };
469
+ }
470
+ }
471
+ return pendingInteractionState(stimulus, interaction);
472
+ }
473
+ function pendingInteractionState(stimulus, interaction) {
474
+ switch (interaction.type) {
475
+ case "choice":
476
+ return choiceState(ctx, stimulus, interaction, interaction.options, interaction.maxChoices, interaction.minChoices);
477
+ case "text-entry":
478
+ return textEntryState(ctx, stimulus, interaction);
479
+ case "extended-text":
480
+ return extendedTextState(ctx, stimulus, interaction);
481
+ case "portable-custom":
482
+ return pciInteractionState(ctx, stimulus, interaction);
483
+ }
484
+ }
485
+ const ctx = { log, execute, errored };
486
+ return { execute };
487
+ }
488
+
489
+ // src/client.ts
490
+ var DEFAULT_ORIGIN = "https://sb-primer.vercel.app";
491
+ var PK_PREFIX = "pk_";
492
+ function create(config) {
493
+ const log = config.logger;
494
+ if (!config.publishableKey.startsWith(PK_PREFIX)) {
495
+ log?.error("malformed publishable key", { prefix: PK_PREFIX });
496
+ throw errors6.wrap(ErrMalformedPublishableKey, `key must start with '${PK_PREFIX}'`);
497
+ }
498
+ const transport = createTransport({
499
+ publishableKey: config.publishableKey,
500
+ supportedPcis: config.supportedPcis,
501
+ origin: config.origin,
502
+ fetch: config.fetch,
503
+ abort: config.abort,
504
+ log
505
+ });
506
+ let startPromise;
507
+ async function doStart(studentId) {
508
+ log?.debug("start", { studentId });
509
+ const s = makeSession({
510
+ studentId,
511
+ supportedPcis: config.supportedPcis,
512
+ log,
513
+ transport
514
+ });
515
+ return s.execute({ kind: "observation" }, "observation");
516
+ }
517
+ return {
518
+ start(studentId) {
519
+ if (startPromise) {
520
+ log?.debug("start already called");
521
+ return startPromise;
522
+ }
523
+ startPromise = doStart(studentId);
524
+ return startPromise;
525
+ }
526
+ };
527
+ }
528
+ // src/content.ts
529
+ function inlinesToPlainText(nodes) {
530
+ const parts = [];
531
+ for (const node of nodes) {
532
+ switch (node.type) {
533
+ case "text":
534
+ parts.push(node.value);
535
+ break;
536
+ case "italic":
537
+ parts.push(inlinesToPlainText(node.children));
538
+ break;
539
+ }
540
+ }
541
+ return parts.join("");
542
+ }
543
+ function blocksToPlainText(blocks) {
544
+ return blocks.map(function blockText(block) {
545
+ return inlinesToPlainText(block.children);
546
+ }).join(`
547
+ `);
548
+ }
549
+ export {
550
+ inlinesToPlainText,
551
+ create,
552
+ blocksToPlainText,
553
+ ErrUnsupportedPci,
554
+ ErrTimeout,
555
+ ErrStateConsumed,
556
+ ErrServiceUnavailable,
557
+ ErrServerError,
558
+ ErrRateLimited,
559
+ ErrNotSerializable,
560
+ ErrNotFound,
561
+ ErrNetwork,
562
+ ErrMalformedPublishableKey,
563
+ ErrJsonParse,
564
+ ErrInvalidSubmission,
565
+ ErrInvalidPublishableKey,
566
+ ErrForbidden,
567
+ ErrConflict,
568
+ ErrBadRequest,
569
+ DEFAULT_ORIGIN,
570
+ ADVANCE_PATH
571
+ };
572
+
573
+ //# debugId=CFD2633E4E8D3BCC64756E2164756E21
@@ -0,0 +1,21 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client.ts", "../src/errors.ts", "../src/transport.ts", "../src/session.ts", "../src/consumed.ts", "../src/choice-state.ts", "../src/extended-text-state.ts", "../src/feedback-state.ts", "../src/observation-state.ts", "../src/pci-state.ts", "../src/text-entry-state.ts", "../src/content.ts"],
4
+ "sourcesContent": [
5
+ "import * as errors from \"@superbuilders/errors\"\nimport { ErrMalformedPublishableKey } from \"@superbuilders/primer-tives/errors\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { PrimerLogger } from \"@superbuilders/primer-tives/session-context\"\nimport type { PrimerState } from \"@superbuilders/primer-tives/types\"\nimport { createTransport } from \"@superbuilders/primer-tives/transport\"\nimport { makeSession } from \"@superbuilders/primer-tives/session\"\n\nconst DEFAULT_ORIGIN = \"https://sb-primer.vercel.app\"\nconst PK_PREFIX = \"pk_\"\n\ninterface Config<Pcis extends PciId = PciId> {\n\treadonly publishableKey: string\n\treadonly supportedPcis: readonly Pcis[]\n\treadonly origin?: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly logger?: PrimerLogger\n}\n\ninterface Client<Pcis extends PciId = PciId> {\n\tstart(studentId: string): Promise<PrimerState<Pcis>>\n}\n\nfunction create<const Pcis extends PciId>(config: Config<Pcis>): Client<Pcis> {\n\tconst log = config.logger\n\n\tif (!config.publishableKey.startsWith(PK_PREFIX)) {\n\t\tlog?.error(\"malformed publishable key\", { prefix: PK_PREFIX })\n\t\t// biome-ignore lint/plugin: client SDK — log is optional config.logger, not slog\n\t\tthrow errors.wrap(ErrMalformedPublishableKey, `key must start with '${PK_PREFIX}'`)\n\t}\n\n\tconst transport = createTransport({\n\t\tpublishableKey: config.publishableKey,\n\t\tsupportedPcis: config.supportedPcis,\n\t\torigin: config.origin,\n\t\tfetch: config.fetch,\n\t\tabort: config.abort,\n\t\tlog\n\t})\n\n\tlet startPromise: Promise<PrimerState<Pcis>> | undefined\n\n\tasync function doStart(studentId: string): Promise<PrimerState<Pcis>> {\n\t\tlog?.debug(\"start\", { studentId })\n\t\tconst s = makeSession({\n\t\t\tstudentId,\n\t\t\tsupportedPcis: config.supportedPcis,\n\t\t\tlog,\n\t\t\ttransport\n\t\t})\n\t\treturn s.execute({ kind: \"observation\" }, \"observation\")\n\t}\n\n\treturn {\n\t\tstart(studentId: string): Promise<PrimerState<Pcis>> {\n\t\t\tif (startPromise) {\n\t\t\t\tlog?.debug(\"start already called\")\n\t\t\t\treturn startPromise\n\t\t\t}\n\t\t\tstartPromise = doStart(studentId)\n\t\t\treturn startPromise\n\t\t}\n\t}\n}\n\nexport { DEFAULT_ORIGIN, create }\nexport type { Client, Config, PrimerLogger }\n",
6
+ "import * as errors from \"@superbuilders/errors\"\n\nconst ErrNetwork = errors.new(\"network\")\nconst ErrJsonParse = errors.new(\"json parse\")\nconst ErrUnsupportedPci = errors.new(\"unsupported pci\")\nconst ErrInvalidPublishableKey = errors.new(\"invalid publishable key\")\nconst ErrBadRequest = errors.new(\"bad request\")\nconst ErrServerError = errors.new(\"server error\")\nconst ErrTimeout = errors.new(\"timeout\")\nconst ErrForbidden = errors.new(\"forbidden\")\nconst ErrNotFound = errors.new(\"not found\")\nconst ErrConflict = errors.new(\"conflict\")\nconst ErrRateLimited = errors.new(\"rate limited\")\nconst ErrServiceUnavailable = errors.new(\"service unavailable\")\nconst ErrNotSerializable = errors.new(\n\t\"PrimerState is live in-memory state and must not be serialized or stored\"\n)\nconst ErrInvalidSubmission = errors.new(\"invalid submission\")\nconst ErrMalformedPublishableKey = errors.new(\"malformed publishable key\")\nconst ErrStateConsumed = errors.new(\"state already consumed\")\n\nexport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrForbidden,\n\tErrInvalidPublishableKey,\n\tErrInvalidSubmission,\n\tErrMalformedPublishableKey,\n\tErrJsonParse,\n\tErrNetwork,\n\tErrNotFound,\n\tErrNotSerializable,\n\tErrRateLimited,\n\tErrServerError,\n\tErrServiceUnavailable,\n\tErrStateConsumed,\n\tErrTimeout,\n\tErrUnsupportedPci\n}\n",
7
+ "import * as errors from \"@superbuilders/errors\"\nimport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrForbidden,\n\tErrInvalidPublishableKey,\n\tErrJsonParse,\n\tErrNetwork,\n\tErrNotFound,\n\tErrRateLimited,\n\tErrServerError,\n\tErrServiceUnavailable,\n\tErrTimeout,\n\tErrUnsupportedPci\n} from \"@superbuilders/primer-tives/errors\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { SessionContext, WireIntent } from \"@superbuilders/primer-tives/session-context\"\nimport type { ContentInline } from \"@superbuilders/primer-tives/content\"\nimport type { RendererCorrectAnswer, RendererInteraction, RendererStimulus, RendererSubmission } from \"@superbuilders/primer-tives/types\"\n\nconst ADVANCE_PATH = \"/api/v0/advance\"\n\ntype WireResult<Pcis extends PciId = PciId> =\n\t| {\n\t\t\toutcome: \"advanced\"\n\t\t\tstimulus: RendererStimulus | null\n\t\t\tinteraction: RendererInteraction<Pcis> | null\n\t }\n\t| {\n\t\t\toutcome: \"submitted\"\n\t\t\tstimulus: RendererStimulus | null\n\t\t\tinteraction: RendererInteraction<Pcis>\n\t\t\tsubmission: RendererSubmission<Pcis>\n\t\t\tisCorrect: boolean\n\t\t\tfeedbackContent: ContentInline[]\n\t\t\tcorrectAnswer: RendererCorrectAnswer | null\n\t }\n\t| { outcome: \"completed\" }\n\ninterface WireRequestBody<Pcis extends PciId = PciId> {\n\tstudentId: string\n\tsupportedPcis: readonly PciId[]\n\tintent: WireIntent<Pcis>\n}\n\ntype TransportResult<Pcis extends PciId = PciId> =\n\t| { ok: true; data: WireResult<Pcis> }\n\t| { ok: false; error: Error }\n\ninterface TransportConfig<Pcis extends PciId = PciId> {\n\treadonly publishableKey: string\n\treadonly supportedPcis: readonly Pcis[]\n\treadonly origin?: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly log: SessionContext[\"log\"]\n}\n\nfunction httpSentinel(status: number): Error {\n\tif (status === 400) {\n\t\treturn ErrBadRequest\n\t}\n\tif (status === 401) {\n\t\treturn ErrInvalidPublishableKey\n\t}\n\tif (status === 403) {\n\t\treturn ErrForbidden\n\t}\n\tif (status === 404) {\n\t\treturn ErrNotFound\n\t}\n\tif (status === 409) {\n\t\treturn ErrConflict\n\t}\n\tif (status === 422) {\n\t\treturn ErrUnsupportedPci\n\t}\n\tif (status === 429) {\n\t\treturn ErrRateLimited\n\t}\n\tif (status === 502 || status === 503 || status === 504) {\n\t\treturn ErrServiceUnavailable\n\t}\n\treturn ErrServerError\n}\n\nfunction isAbortError(err: unknown): boolean {\n\tif (err instanceof DOMException && err.name === \"AbortError\") {\n\t\treturn true\n\t}\n\tif (err instanceof DOMException && err.name === \"TimeoutError\") {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunction createTransport<Pcis extends PciId>(tc: TransportConfig<Pcis>) {\n\tconst fetchFn = tc.fetch ? tc.fetch : globalThis.fetch\n\tconst log = tc.log\n\n\tfunction transportSignal(): AbortSignal | undefined {\n\t\tif (tc.abort) {\n\t\t\treturn tc.abort.signal\n\t\t}\n\t\treturn undefined\n\t}\n\n\tasync function transport(body: WireRequestBody<Pcis>): Promise<TransportResult<Pcis>> {\n\t\tlog?.debug(\"transport request\", {\n\t\t\tstudentId: body.studentId,\n\t\t\tintentKind: body.intent.kind\n\t\t})\n\n\t\tconst url = tc.origin ? `${tc.origin}${ADVANCE_PATH}` : ADVANCE_PATH\n\t\tconst fetchResult = await fetchFn(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-Primer-Publishable-Key\": tc.publishableKey\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: transportSignal()\n\t\t}).then(\n\t\t\tfunction ok(r: Response) {\n\t\t\t\treturn { ok: true, response: r } as const\n\t\t\t},\n\t\t\tfunction fail(err: Error) {\n\t\t\t\treturn { ok: false, error: err } as const\n\t\t\t}\n\t\t)\n\n\t\tif (!fetchResult.ok) {\n\t\t\tif (isAbortError(fetchResult.error)) {\n\t\t\t\tlog?.error(\"transport timeout\", {\n\t\t\t\t\tstudentId: body.studentId,\n\t\t\t\t\tintentKind: body.intent.kind\n\t\t\t\t})\n\t\t\t\treturn { ok: false, error: errors.wrap(ErrTimeout, fetchResult.error.message) }\n\t\t\t}\n\t\t\tlog?.error(\"transport network error\", {\n\t\t\t\tstudentId: body.studentId,\n\t\t\t\terror: fetchResult.error\n\t\t\t})\n\t\t\treturn { ok: false, error: errors.wrap(ErrNetwork, fetchResult.error.message) }\n\t\t}\n\n\t\tconst res = fetchResult.response\n\n\t\tif (!res.ok) {\n\t\t\tconst text = await res.text().catch(function fallback() {\n\t\t\t\treturn \"\"\n\t\t\t})\n\t\t\tconst sentinel = httpSentinel(res.status)\n\t\t\tlog?.error(\"transport http error\", {\n\t\t\t\tstudentId: body.studentId,\n\t\t\t\tstatus: res.status\n\t\t\t})\n\t\t\treturn { ok: false, error: errors.wrap(sentinel, text) }\n\t\t}\n\n\t\tconst jsonResult = await res.json().then(\n\t\t\tfunction ok(data: WireResult<Pcis>) {\n\t\t\t\treturn { ok: true, data } as const\n\t\t\t},\n\t\t\tfunction fail(err: Error) {\n\t\t\t\treturn { ok: false, error: err } as const\n\t\t\t}\n\t\t)\n\n\t\tif (!jsonResult.ok) {\n\t\t\tlog?.error(\"transport json parse failed\", {\n\t\t\t\tstudentId: body.studentId,\n\t\t\t\terror: jsonResult.error\n\t\t\t})\n\t\t\treturn { ok: false, error: errors.wrap(ErrJsonParse, jsonResult.error.message) }\n\t\t}\n\n\t\tlog?.debug(\"transport success\", {\n\t\t\tstudentId: body.studentId,\n\t\t\tintentKind: body.intent.kind\n\t\t})\n\n\t\treturn { ok: true, data: jsonResult.data }\n\t}\n\n\treturn transport\n}\n\nexport { ADVANCE_PATH, createTransport, httpSentinel, isAbortError }\nexport type { TransportConfig, TransportResult, WireRequestBody, WireResult }\n",
8
+ "import * as errors from \"@superbuilders/errors\"\nimport { CONSUMED, CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport { ErrConflict, ErrUnsupportedPci } from \"@superbuilders/primer-tives/errors\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { PrimerLogger, SessionContext, TransitionPhase, WireIntent } from \"@superbuilders/primer-tives/session-context\"\nimport type { TransportResult, WireRequestBody, WireResult } from \"@superbuilders/primer-tives/transport\"\nimport type {\n\tErroredState,\n\tPrimerState,\n\tRendererInteraction,\n\tRendererStimulus\n} from \"@superbuilders/primer-tives/types\"\nimport { choiceState } from \"@superbuilders/primer-tives/choice-state\"\nimport { extendedTextState } from \"@superbuilders/primer-tives/extended-text-state\"\nimport { feedbackState } from \"@superbuilders/primer-tives/feedback-state\"\nimport { observationState } from \"@superbuilders/primer-tives/observation-state\"\nimport { pciInteractionState } from \"@superbuilders/primer-tives/pci-state\"\nimport { textEntryState } from \"@superbuilders/primer-tives/text-entry-state\"\n\ninterface SessionConfig<Pcis extends PciId = PciId> {\n\treadonly studentId: string\n\treadonly supportedPcis: readonly Pcis[]\n\treadonly log: PrimerLogger | undefined\n\treadonly transport: (body: WireRequestBody<Pcis>) => Promise<TransportResult<Pcis>>\n}\n\nfunction makeSession<Pcis extends PciId>(sc: SessionConfig<Pcis>) {\n\tconst log = sc.log\n\n\tfunction resolve(result: WireResult<Pcis>): PrimerState<Pcis> {\n\t\tswitch (result.outcome) {\n\t\t\tcase \"advanced\":\n\t\t\t\treturn fromAdvanced(result.stimulus, result.interaction)\n\t\t\tcase \"submitted\":\n\t\t\t\treturn feedbackState(\n\t\t\t\t\tctx,\n\t\t\t\t\tresult.stimulus,\n\t\t\t\t\tresult.interaction,\n\t\t\t\t\tresult.submission,\n\t\t\t\t\tresult.isCorrect,\n\t\t\t\t\tresult.feedbackContent,\n\t\t\t\t\tresult.correctAnswer\n\t\t\t\t)\n\t\t\tcase \"completed\":\n\t\t\t\treturn { phase: \"completed\", toJSON: poisonToJSON }\n\t\t}\n\t}\n\n\tfunction errored(\n\t\terror: Error,\n\t\tfailedPhase: TransitionPhase,\n\t\tintent: WireIntent<Pcis>\n\t): ErroredState<Pcis> {\n\t\tlet retryConsumed = false\n\t\treturn {\n\t\t\tphase: \"errored\",\n\t\t\terror,\n\t\t\tfailedPhase,\n\t\t\tretry: function retry() {\n\t\t\t\tif (retryConsumed) {\n\t\t\t\t\tlog?.debug(\"retry already consumed\")\n\t\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t\t}\n\t\t\t\tretryConsumed = true\n\t\t\t\tlog?.debug(\"retrying from errored state\", { failedPhase })\n\t\t\t\treturn execute(intent, failedPhase)\n\t\t\t},\n\t\t\ttoJSON: poisonToJSON\n\t\t}\n\t}\n\n\tasync function execute(\n\t\tintent: WireIntent<Pcis>,\n\t\tphase: TransitionPhase\n\t): Promise<PrimerState<Pcis>> {\n\t\tconst body: WireRequestBody<Pcis> = {\n\t\t\tstudentId: sc.studentId,\n\t\t\tsupportedPcis: sc.supportedPcis,\n\t\t\tintent\n\t\t}\n\n\t\tconst result = await sc.transport(body)\n\t\tif (!result.ok) {\n\t\t\tif (errors.is(result.error, ErrConflict)) {\n\t\t\t\tlog?.debug(\"state already consumed server-side\", { phase })\n\t\t\t\treturn CONSUMED\n\t\t\t}\n\t\t\treturn errored(result.error, phase, intent)\n\t\t}\n\n\t\treturn resolve(result.data)\n\t}\n\n\tfunction isPciSupported(pciId: string): boolean {\n\t\tfor (const id of sc.supportedPcis) {\n\t\t\tif (id === pciId) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tfunction fromAdvanced(\n\t\tstimulus: RendererStimulus | null,\n\t\tinteraction: RendererInteraction<Pcis> | null\n\t): PrimerState<Pcis> {\n\t\tif (interaction === null) {\n\t\t\treturn observationState(ctx, stimulus)\n\t\t}\n\t\tif (interaction.type === \"portable-custom\") {\n\t\t\tif (!isPciSupported(interaction.pciId)) {\n\t\t\t\tlog?.error(\"unsupported pci in frame\", { pciId: interaction.pciId })\n\t\t\t\treturn {\n\t\t\t\t\tphase: \"fatal\",\n\t\t\t\t\terror: errors.wrap(ErrUnsupportedPci, `pci '${interaction.pciId}'`),\n\t\t\t\t\ttoJSON: poisonToJSON\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn pendingInteractionState(stimulus, interaction)\n\t}\n\n\tfunction pendingInteractionState(\n\t\tstimulus: RendererStimulus | null,\n\t\tinteraction: RendererInteraction<Pcis>\n\t): PrimerState<Pcis> {\n\t\tswitch (interaction.type) {\n\t\t\tcase \"choice\":\n\t\t\t\treturn choiceState(\n\t\t\t\t\tctx,\n\t\t\t\t\tstimulus,\n\t\t\t\t\tinteraction,\n\t\t\t\t\tinteraction.options,\n\t\t\t\t\tinteraction.maxChoices,\n\t\t\t\t\tinteraction.minChoices\n\t\t\t\t)\n\t\t\tcase \"text-entry\":\n\t\t\t\treturn textEntryState(ctx, stimulus, interaction)\n\t\t\tcase \"extended-text\":\n\t\t\t\treturn extendedTextState(ctx, stimulus, interaction)\n\t\t\tcase \"portable-custom\":\n\t\t\t\treturn pciInteractionState(ctx, stimulus, interaction)\n\t\t}\n\t}\n\n\tconst ctx: SessionContext<Pcis> = { log, execute, errored }\n\n\treturn { execute }\n}\n\nexport { makeSession }\nexport type { SessionConfig }\n",
9
+ "import { ErrNotSerializable } from \"@superbuilders/primer-tives/errors\"\nimport type { ConsumedState } from \"@superbuilders/primer-tives/types\"\n\nfunction poisonToJSON(): never {\n\t// biome-ignore lint/plugin: intentional toJSON trap — logging here would spam on every accidental serialize attempt\n\tthrow ErrNotSerializable\n}\n\nconst CONSUMED: ConsumedState = { phase: \"consumed\", toJSON: poisonToJSON }\nconst CONSUMED_PROMISE: Promise<ConsumedState> = Promise.resolve(CONSUMED)\n\nexport { CONSUMED, CONSUMED_PROMISE, poisonToJSON }\n",
10
+ "import { CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport { ErrInvalidSubmission } from \"@superbuilders/primer-tives/errors\"\nimport type { SessionContext } from \"@superbuilders/primer-tives/session-context\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { PrimerState, RendererChoice, RendererInteraction, RendererStimulus } from \"@superbuilders/primer-tives/types\"\nimport * as errors from \"@superbuilders/errors\"\n\nfunction findUnknownKey(selectedKeys: string[], options: RendererChoice[]): string | null {\n\tconst optionIds = new Set(\n\t\toptions.map(function getId(o) {\n\t\t\treturn o.identifier\n\t\t})\n\t)\n\tfor (const key of selectedKeys) {\n\t\tif (!optionIds.has(key)) {\n\t\t\treturn key\n\t\t}\n\t}\n\treturn null\n}\n\nfunction validateChoiceSubmission(\n\tlog: SessionContext[\"log\"],\n\tselectedKeys: string[],\n\toptions: RendererChoice[],\n\tmaxChoices: number,\n\tminChoices: number\n): Error | null {\n\tif (selectedKeys.length < minChoices) {\n\t\tlog?.error(\"choice submit below minChoices\", { selectedKeys, minChoices })\n\t\treturn errors.wrap(ErrInvalidSubmission, `need at least ${minChoices} selections`)\n\t}\n\tif (selectedKeys.length > maxChoices) {\n\t\tlog?.error(\"choice submit above maxChoices\", { selectedKeys, maxChoices })\n\t\treturn errors.wrap(ErrInvalidSubmission, `at most ${maxChoices} selections`)\n\t}\n\tconst uniqueKeys = new Set(selectedKeys)\n\tif (uniqueKeys.size !== selectedKeys.length) {\n\t\tlog?.error(\"choice submit has duplicates\", { selectedKeys })\n\t\treturn errors.wrap(ErrInvalidSubmission, \"duplicate selections\")\n\t}\n\tconst unknownKey = findUnknownKey(selectedKeys, options)\n\tif (unknownKey) {\n\t\tlog?.error(\"choice submit has unknown key\", { key: unknownKey })\n\t\treturn errors.wrap(ErrInvalidSubmission, `unknown option '${unknownKey}'`)\n\t}\n\treturn null\n}\n\nfunction choiceState<Pcis extends PciId>(\n\tctx: SessionContext<Pcis>,\n\tstimulus: RendererStimulus | null,\n\tinteraction: Extract<RendererInteraction<Pcis>, { type: \"choice\" }>,\n\toptions: RendererChoice[],\n\tmaxChoices: number,\n\tminChoices: number\n): PrimerState<Pcis> {\n\tlet consumed = false\n\treturn {\n\t\tphase: \"interaction\",\n\t\tkind: \"choice\",\n\t\tstimulus,\n\t\tinteraction,\n\t\toptions,\n\t\tmaxChoices,\n\t\tminChoices,\n\t\tsubmitChoice: function submitChoice(selectedKeys: string[]) {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"choice submit already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconst validationError = validateChoiceSubmission(\n\t\t\t\tctx.log,\n\t\t\t\tselectedKeys,\n\t\t\t\toptions,\n\t\t\t\tmaxChoices,\n\t\t\t\tminChoices\n\t\t\t)\n\t\t\tif (validationError) {\n\t\t\t\treturn Promise.resolve(\n\t\t\t\t\tctx.errored(validationError, \"interaction\", {\n\t\t\t\t\t\tkind: \"interaction\",\n\t\t\t\t\t\tsubmission: { type: \"choice\", selectedKeys }\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute(\n\t\t\t\t{ kind: \"interaction\", submission: { type: \"choice\", selectedKeys } },\n\t\t\t\t\"interaction\"\n\t\t\t)\n\t\t},\n\t\ttimeout: function timeout() {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"choice timeout already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute({ kind: \"timeout\" }, \"timeout\")\n\t\t},\n\t\ttoJSON: poisonToJSON\n\t}\n}\n\nexport { choiceState }\n",
11
+ "import { CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport { ErrInvalidSubmission } from \"@superbuilders/primer-tives/errors\"\nimport type { SessionContext } from \"@superbuilders/primer-tives/session-context\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { PrimerState, RendererInteraction, RendererStimulus } from \"@superbuilders/primer-tives/types\"\nimport * as errors from \"@superbuilders/errors\"\n\nfunction validateExtendedTextSubmission(\n\tlog: SessionContext[\"log\"],\n\tvalues: string[],\n\tminStrings: number,\n\tmaxStrings: number\n): Error | null {\n\tif (values.length < minStrings) {\n\t\tlog?.error(\"extended-text submit below minStrings\", { count: values.length, minStrings })\n\t\treturn errors.wrap(ErrInvalidSubmission, `need at least ${minStrings} values`)\n\t}\n\tif (values.length > maxStrings) {\n\t\tlog?.error(\"extended-text submit above maxStrings\", { count: values.length, maxStrings })\n\t\treturn errors.wrap(ErrInvalidSubmission, `at most ${maxStrings} values`)\n\t}\n\treturn null\n}\n\nfunction extendedTextState<Pcis extends PciId>(\n\tctx: SessionContext<Pcis>,\n\tstimulus: RendererStimulus | null,\n\tinteraction: RendererInteraction<Pcis> & { type: \"extended-text\" }\n): PrimerState<Pcis> {\n\tconst maxStrings = interaction.maxStrings\n\tconst minStrings = interaction.minStrings\n\tif (maxStrings === 1) {\n\t\tlet consumed = false\n\t\treturn {\n\t\t\tphase: \"interaction\",\n\t\t\tkind: \"extended-text\",\n\t\t\tcardinality: \"single\",\n\t\t\tstimulus,\n\t\t\tinteraction,\n\t\t\tsubmitText: function submitText(value: string) {\n\t\t\t\tif (consumed) {\n\t\t\t\t\tctx.log?.debug(\"extended-text single submit already consumed\")\n\t\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t\t}\n\t\t\t\tconsumed = true\n\t\t\t\treturn ctx.execute(\n\t\t\t\t\t{ kind: \"interaction\", submission: { type: \"extended-text\", values: [value] } },\n\t\t\t\t\t\"interaction\"\n\t\t\t\t)\n\t\t\t},\n\t\t\ttimeout: function timeout() {\n\t\t\t\tif (consumed) {\n\t\t\t\t\tctx.log?.debug(\"extended-text single timeout already consumed\")\n\t\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t\t}\n\t\t\t\tconsumed = true\n\t\t\t\treturn ctx.execute({ kind: \"timeout\" }, \"timeout\")\n\t\t\t},\n\t\t\ttoJSON: poisonToJSON\n\t\t}\n\t}\n\tlet consumed = false\n\treturn {\n\t\tphase: \"interaction\",\n\t\tkind: \"extended-text\",\n\t\tcardinality: \"multiple\",\n\t\tstimulus,\n\t\tinteraction,\n\t\tmaxStrings,\n\t\tminStrings,\n\t\tsubmitTexts: function submitTexts(values: string[]) {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"extended-text multiple submit already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconst validationError = validateExtendedTextSubmission(ctx.log, values, minStrings, maxStrings)\n\t\t\tif (validationError) {\n\t\t\t\treturn Promise.resolve(\n\t\t\t\t\tctx.errored(validationError, \"interaction\", {\n\t\t\t\t\t\tkind: \"interaction\",\n\t\t\t\t\t\tsubmission: { type: \"extended-text\", values }\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute(\n\t\t\t\t{ kind: \"interaction\", submission: { type: \"extended-text\", values } },\n\t\t\t\t\"interaction\"\n\t\t\t)\n\t\t},\n\t\ttimeout: function timeout() {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"extended-text multiple timeout already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute({ kind: \"timeout\" }, \"timeout\")\n\t\t},\n\t\ttoJSON: poisonToJSON\n\t}\n}\n\nexport { extendedTextState }\n",
12
+ "import { CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport type { ContentInline } from \"@superbuilders/primer-tives/content\"\nimport type { SessionContext } from \"@superbuilders/primer-tives/session-context\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type {\n\tPrimerState,\n\tRendererCorrectAnswer,\n\tRendererInteraction,\n\tRendererStimulus,\n\tRendererSubmission\n} from \"@superbuilders/primer-tives/types\"\n\nfunction feedbackState<Pcis extends PciId>(\n\tctx: SessionContext<Pcis>,\n\tstimulus: RendererStimulus | null,\n\tinteraction: RendererInteraction<Pcis>,\n\tsubmission: RendererSubmission<Pcis>,\n\tisCorrect: boolean,\n\tfeedbackContent: ContentInline[],\n\tcorrectAnswer: RendererCorrectAnswer | null\n): PrimerState<Pcis> {\n\tlet consumed = false\n\treturn {\n\t\tphase: \"feedback\",\n\t\tstimulus,\n\t\tinteraction,\n\t\tsubmission,\n\t\tisCorrect,\n\t\tfeedbackContent,\n\t\tcorrectAnswer,\n\t\tadvance: function advance() {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"feedback advance already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute({ kind: \"observation\" }, \"observation\")\n\t\t},\n\t\ttoJSON: poisonToJSON\n\t}\n}\n\nexport { feedbackState }\n",
13
+ "import { CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport type { SessionContext } from \"@superbuilders/primer-tives/session-context\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { PrimerState, RendererStimulus } from \"@superbuilders/primer-tives/types\"\n\nfunction observationState<Pcis extends PciId>(\n\tctx: SessionContext<Pcis>,\n\tstimulus: RendererStimulus | null\n): PrimerState<Pcis> {\n\tlet consumed = false\n\treturn {\n\t\tphase: \"observation\",\n\t\tstimulus,\n\t\tadvance: function advance() {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"observation advance already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute({ kind: \"observation\" }, \"observation\")\n\t\t},\n\t\ttoJSON: poisonToJSON\n\t}\n}\n\nexport { observationState }\n",
14
+ "import { CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport type { PciId, PciValue } from \"@superbuilders/primer-tives/pci\"\nimport type { SessionContext } from \"@superbuilders/primer-tives/session-context\"\nimport type { PciInteraction, PciInteractionState, PrimerState, RendererStimulus } from \"@superbuilders/primer-tives/types\"\n\nfunction pciInteractionState<Pcis extends PciId>(\n\tctx: SessionContext<Pcis>,\n\tstimulus: RendererStimulus | null,\n\tinteraction: PciInteraction<Pcis>\n): PciInteractionState<Pcis> {\n\tlet consumed = false\n\tconst { pciId, properties } = interaction\n\tfunction submit(value: PciValue<typeof pciId>): Promise<PrimerState<Pcis>> {\n\t\tif (consumed) {\n\t\t\tctx.log?.debug(\"pci submit already consumed\", { pciId })\n\t\t\treturn CONSUMED_PROMISE\n\t\t}\n\t\tconsumed = true\n\t\tctx.log?.debug(\"pci submit\", { pciId })\n\t\tconst submission = { type: \"portable-custom\" as const, pciId, value }\n\t\treturn ctx.execute({ kind: \"interaction\", submission }, \"interaction\")\n\t}\n\tfunction timeout(): Promise<PrimerState<Pcis>> {\n\t\tif (consumed) {\n\t\t\tctx.log?.debug(\"pci timeout already consumed\", { pciId })\n\t\t\treturn CONSUMED_PROMISE\n\t\t}\n\t\tconsumed = true\n\t\tctx.log?.debug(\"pci timeout\", { pciId })\n\t\treturn ctx.execute({ kind: \"timeout\" }, \"timeout\")\n\t}\n\t// biome-ignore lint/plugin: TS cannot verify mapped-union construction from generic Pcis — pciId↔properties correlation preserved by input\n\treturn {\n\t\tphase: \"interaction\",\n\t\tkind: \"portable-custom\",\n\t\tstimulus,\n\t\tinteraction,\n\t\tpciId,\n\t\tproperties,\n\t\tsubmit,\n\t\ttimeout,\n\t\ttoJSON: poisonToJSON\n\t} as PciInteractionState<Pcis>\n}\n\nexport { pciInteractionState }\n",
15
+ "import { CONSUMED_PROMISE, poisonToJSON } from \"@superbuilders/primer-tives/consumed\"\nimport type { SessionContext } from \"@superbuilders/primer-tives/session-context\"\nimport type { PciId } from \"@superbuilders/primer-tives/pci\"\nimport type { PrimerState, RendererInteraction, RendererStimulus } from \"@superbuilders/primer-tives/types\"\n\nfunction textEntryState<Pcis extends PciId>(\n\tctx: SessionContext<Pcis>,\n\tstimulus: RendererStimulus | null,\n\tinteraction: Extract<RendererInteraction<Pcis>, { type: \"text-entry\" }>\n): PrimerState<Pcis> {\n\tlet consumed = false\n\treturn {\n\t\tphase: \"interaction\",\n\t\tkind: \"text-entry\",\n\t\tstimulus,\n\t\tinteraction,\n\t\tsubmitText: function submitText(value: string) {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"text-entry submit already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute(\n\t\t\t\t{ kind: \"interaction\", submission: { type: \"text-entry\", value } },\n\t\t\t\t\"interaction\"\n\t\t\t)\n\t\t},\n\t\ttimeout: function timeout() {\n\t\t\tif (consumed) {\n\t\t\t\tctx.log?.debug(\"text-entry timeout already consumed\")\n\t\t\t\treturn CONSUMED_PROMISE\n\t\t\t}\n\t\t\tconsumed = true\n\t\t\treturn ctx.execute({ kind: \"timeout\" }, \"timeout\")\n\t\t},\n\t\ttoJSON: poisonToJSON\n\t}\n}\n\nexport { textEntryState }\n",
16
+ "type ContentInline = { type: \"text\"; value: string } | { type: \"italic\"; children: ContentInline[] }\n\ntype ContentBlock = { type: \"paragraph\"; children: ContentInline[] }\n\nfunction inlinesToPlainText(nodes: ContentInline[]): string {\n\tconst parts: string[] = []\n\tfor (const node of nodes) {\n\t\tswitch (node.type) {\n\t\t\tcase \"text\":\n\t\t\t\tparts.push(node.value)\n\t\t\t\tbreak\n\t\t\tcase \"italic\":\n\t\t\t\tparts.push(inlinesToPlainText(node.children))\n\t\t\t\tbreak\n\t\t}\n\t}\n\treturn parts.join(\"\")\n}\n\nfunction blocksToPlainText(blocks: ContentBlock[]): string {\n\treturn blocks\n\t\t.map(function blockText(block) {\n\t\t\treturn inlinesToPlainText(block.children)\n\t\t})\n\t\t.join(\"\\n\")\n}\n\nexport type { ContentBlock, ContentInline }\nexport { blocksToPlainText, inlinesToPlainText }\n"
17
+ ],
18
+ "mappings": "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",
19
+ "debugId": "CFD2633E4E8D3BCC64756E2164756E21",
20
+ "names": []
21
+ }