@superbuilders/primer-tives 1.1.1 → 1.1.2

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 (73) hide show
  1. package/package.json +1 -1
  2. package/dist/client/choice-state.d.ts +0 -8
  3. package/dist/client/choice-state.d.ts.map +0 -1
  4. package/dist/client/consumed.d.ts +0 -3
  5. package/dist/client/consumed.d.ts.map +0 -1
  6. package/dist/client/content.d.ts +0 -20
  7. package/dist/client/content.d.ts.map +0 -1
  8. package/dist/client/create.d.ts +0 -20
  9. package/dist/client/create.d.ts.map +0 -1
  10. package/dist/client/extended-text-state.d.ts +0 -8
  11. package/dist/client/extended-text-state.d.ts.map +0 -1
  12. package/dist/client/feedback-state.d.ts +0 -7
  13. package/dist/client/feedback-state.d.ts.map +0 -1
  14. package/dist/client/index.d.ts +0 -11
  15. package/dist/client/index.d.ts.map +0 -1
  16. package/dist/client/index.js +0 -1123
  17. package/dist/client/index.js.map +0 -26
  18. package/dist/client/match-state.d.ts +0 -8
  19. package/dist/client/match-state.d.ts.map +0 -1
  20. package/dist/client/observation-state.d.ts +0 -6
  21. package/dist/client/observation-state.d.ts.map +0 -1
  22. package/dist/client/order-state.d.ts +0 -8
  23. package/dist/client/order-state.d.ts.map +0 -1
  24. package/dist/client/pci-state.d.ts +0 -6
  25. package/dist/client/pci-state.d.ts.map +0 -1
  26. package/dist/client/pci.d.ts +0 -38
  27. package/dist/client/pci.d.ts.map +0 -1
  28. package/dist/client/session-context.d.ts +0 -19
  29. package/dist/client/session-context.d.ts.map +0 -1
  30. package/dist/client/session.d.ts +0 -18
  31. package/dist/client/session.d.ts.map +0 -1
  32. package/dist/client/text-entry-state.d.ts +0 -8
  33. package/dist/client/text-entry-state.d.ts.map +0 -1
  34. package/dist/client/transport.d.ts +0 -46
  35. package/dist/client/transport.d.ts.map +0 -1
  36. package/dist/client/types.d.ts +0 -194
  37. package/dist/client/types.d.ts.map +0 -1
  38. package/dist/contracts/index.d.ts +0 -4
  39. package/dist/contracts/index.d.ts.map +0 -1
  40. package/dist/contracts/index.js +0 -328
  41. package/dist/contracts/index.js.map +0 -11
  42. package/dist/contracts/pci-schemas.d.ts +0 -25
  43. package/dist/contracts/pci-schemas.d.ts.map +0 -1
  44. package/dist/contracts/types.d.ts +0 -118
  45. package/dist/contracts/types.d.ts.map +0 -1
  46. package/dist/contracts/validation.d.ts +0 -158
  47. package/dist/contracts/validation.d.ts.map +0 -1
  48. package/dist/errors.d.ts +0 -23
  49. package/dist/errors.d.ts.map +0 -1
  50. package/dist/errors.js +0 -48
  51. package/dist/errors.js.map +0 -10
  52. package/dist/grade-level.d.ts +0 -5
  53. package/dist/grade-level.d.ts.map +0 -1
  54. package/dist/index.d.ts +0 -3
  55. package/dist/index.d.ts.map +0 -1
  56. package/dist/index.js +0 -372
  57. package/dist/index.js.map +0 -12
  58. package/dist/logger.d.ts +0 -8
  59. package/dist/logger.d.ts.map +0 -1
  60. package/dist/server/create-server.d.ts +0 -44
  61. package/dist/server/create-server.d.ts.map +0 -1
  62. package/dist/server/exchange.d.ts +0 -22
  63. package/dist/server/exchange.d.ts.map +0 -1
  64. package/dist/server/hints.d.ts +0 -25
  65. package/dist/server/hints.d.ts.map +0 -1
  66. package/dist/server/index.d.ts +0 -9
  67. package/dist/server/index.d.ts.map +0 -1
  68. package/dist/server/index.js +0 -531
  69. package/dist/server/index.js.map +0 -15
  70. package/dist/server/students.d.ts +0 -12
  71. package/dist/server/students.d.ts.map +0 -1
  72. package/dist/subject.d.ts +0 -6
  73. package/dist/subject.d.ts.map +0 -1
@@ -1,531 +0,0 @@
1
- // src/errors.ts
2
- import * as errors from "@superbuilders/errors";
3
- var ErrNetwork = errors.new("network");
4
- var ErrJsonParse = errors.new("json parse");
5
- var ErrUnsupportedPci = errors.new("unsupported pci");
6
- var ErrInvalidAccessToken = errors.new("invalid access token");
7
- var ErrMalformedAccessToken = errors.new("malformed access token");
8
- var ErrTokenExpired = errors.new("access token expired");
9
- var ErrBadRequest = errors.new("bad request");
10
- var ErrServerError = errors.new("server error");
11
- var ErrTimeout = errors.new("timeout");
12
- var ErrForbidden = errors.new("forbidden");
13
- var ErrNotFound = errors.new("not found");
14
- var ErrConflict = errors.new("conflict");
15
- var ErrExternalAuthorityRequired = errors.new("external authority required");
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 ErrInvalidSecretKey = errors.new("invalid secret key");
21
- var ErrStudentNotFound = errors.new("student not found");
22
- var ErrUnsupportedGrade = errors.new("unsupported grade");
23
- var ErrTimebackUnavailable = errors.new("timeback unavailable");
24
- // src/server/exchange.ts
25
- import * as errors2 from "@superbuilders/errors";
26
- var STUDENT_EXCHANGE_PATH = "/api/v0/auth/exchange";
27
- var TIMEBACK_EXCHANGE_PATH = "/api/v0/auth/exchange/timeback";
28
- function isObjectRecord(value) {
29
- return typeof value === "object" && value !== null;
30
- }
31
- function isFiniteNumber(value) {
32
- return typeof value === "number" && Number.isFinite(value);
33
- }
34
- function toExchangeErrorBody(data) {
35
- if (!isObjectRecord(data)) {
36
- return {};
37
- }
38
- return typeof data.error === "string" ? { error: data.error } : {};
39
- }
40
- function parseSessionTokenSuccessBody(data) {
41
- if (!isObjectRecord(data)) {
42
- return;
43
- }
44
- if (typeof data.access_token !== "string") {
45
- return;
46
- }
47
- if (data.token_type !== "Bearer") {
48
- return;
49
- }
50
- if (!isFiniteNumber(data.expires_in)) {
51
- return;
52
- }
53
- if (typeof data.scope !== "string") {
54
- return;
55
- }
56
- return {
57
- access_token: data.access_token,
58
- token_type: data.token_type,
59
- expires_in: data.expires_in,
60
- scope: data.scope
61
- };
62
- }
63
- function parseTimebackExchangeSuccessBody(data) {
64
- const session = parseSessionTokenSuccessBody(data);
65
- if (!session || !isObjectRecord(data) || typeof data.student_id !== "string") {
66
- return;
67
- }
68
- return {
69
- student_id: data.student_id,
70
- access_token: session.access_token,
71
- token_type: session.token_type,
72
- expires_in: session.expires_in,
73
- scope: session.scope
74
- };
75
- }
76
- function isAbortError(err) {
77
- return err.name === "AbortError" || err.name === "TimeoutError";
78
- }
79
- function mapBadRequest(body) {
80
- if (body.error === "unsupported_grade") {
81
- return ErrUnsupportedGrade;
82
- }
83
- return ErrBadRequest;
84
- }
85
- function httpSentinel(status, body) {
86
- if (status === 400) {
87
- return mapBadRequest(body);
88
- }
89
- if (status === 401) {
90
- return ErrInvalidSecretKey;
91
- }
92
- if (status === 404) {
93
- return ErrStudentNotFound;
94
- }
95
- if (status === 409) {
96
- if (body.error === "external_authority_required") {
97
- return ErrExternalAuthorityRequired;
98
- }
99
- return ErrConflict;
100
- }
101
- if (status === 502) {
102
- return ErrTimebackUnavailable;
103
- }
104
- return ErrServerError;
105
- }
106
- async function readErrorBody(res) {
107
- const parsed = await res.json().then(function ok(data) {
108
- return { ok: true, data };
109
- }, function fail() {
110
- return { ok: false };
111
- });
112
- if (!parsed.ok) {
113
- return {};
114
- }
115
- return toExchangeErrorBody(parsed.data);
116
- }
117
- async function sendExchangeRequest(config, path, body, logContext) {
118
- const logger = config.logger;
119
- const fetchFn = config.fetch ? config.fetch : globalThis.fetch;
120
- const signal = config.abort ? config.abort.signal : undefined;
121
- const url = `${config.origin}${path}`;
122
- const fetchResult = await fetchFn(url, {
123
- method: "POST",
124
- headers: {
125
- "Content-Type": "application/json",
126
- Authorization: `Bearer ${config.secretKey}`
127
- },
128
- body: JSON.stringify(body),
129
- signal
130
- }).then(function ok(response) {
131
- return { ok: true, response };
132
- }, function fail(err) {
133
- return { ok: false, error: err };
134
- });
135
- if (!fetchResult.ok) {
136
- if (isAbortError(fetchResult.error)) {
137
- logger.error("exchange timeout", { path, ...logContext });
138
- throw errors2.wrap(ErrTimeout, fetchResult.error.message);
139
- }
140
- logger.error("exchange network error", { path, ...logContext, error: fetchResult.error });
141
- throw errors2.wrap(ErrNetwork, fetchResult.error.message);
142
- }
143
- return fetchResult.response;
144
- }
145
- async function parseSessionTokenSuccess(config, res, logContext) {
146
- const logger = config.logger;
147
- const jsonResult = await res.json().then(function ok(data) {
148
- return { ok: true, data };
149
- }, function fail(err) {
150
- return { ok: false, error: err };
151
- });
152
- if (!jsonResult.ok) {
153
- logger.error("exchange json parse failed", { ...logContext, error: jsonResult.error });
154
- throw errors2.wrap(ErrJsonParse, jsonResult.error.message);
155
- }
156
- const body = parseSessionTokenSuccessBody(jsonResult.data);
157
- if (!body) {
158
- logger.error("exchange success body had invalid shape", {
159
- ...logContext,
160
- body: jsonResult.data
161
- });
162
- throw errors2.wrap(ErrJsonParse, "exchange success body had invalid shape");
163
- }
164
- logger.debug("exchange success", {
165
- ...logContext,
166
- expiresIn: body.expires_in
167
- });
168
- return {
169
- accessToken: body.access_token,
170
- expiresInSeconds: body.expires_in
171
- };
172
- }
173
- async function parseTimebackSessionSuccess(config, res, sourcedId) {
174
- const logger = config.logger;
175
- const jsonResult = await res.json().then(function ok(data) {
176
- return { ok: true, data };
177
- }, function fail(err) {
178
- return { ok: false, error: err };
179
- });
180
- if (!jsonResult.ok) {
181
- logger.error("timeback exchange json parse failed", { sourcedId, error: jsonResult.error });
182
- throw errors2.wrap(ErrJsonParse, jsonResult.error.message);
183
- }
184
- const body = parseTimebackExchangeSuccessBody(jsonResult.data);
185
- if (!body) {
186
- logger.error("timeback exchange success body had invalid shape", {
187
- sourcedId,
188
- body: jsonResult.data
189
- });
190
- throw errors2.wrap(ErrJsonParse, "timeback exchange success body had invalid shape");
191
- }
192
- logger.debug("timeback exchange success", {
193
- sourcedId,
194
- studentId: body.student_id,
195
- expiresIn: body.expires_in
196
- });
197
- return {
198
- studentId: body.student_id,
199
- accessToken: body.access_token,
200
- expiresInSeconds: body.expires_in
201
- };
202
- }
203
- async function exchangeStudent(config, studentId) {
204
- const logger = config.logger;
205
- logger.debug("exchange student request", { studentId });
206
- const res = await sendExchangeRequest(config, STUDENT_EXCHANGE_PATH, { student_id: studentId }, { studentId, exchangeKind: "student_id" });
207
- if (!res.ok) {
208
- const body = await readErrorBody(res);
209
- const sentinel = httpSentinel(res.status, body);
210
- const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
211
- logger.error("exchange student http error", { status: res.status, body, studentId });
212
- throw errors2.wrap(sentinel, detail);
213
- }
214
- return parseSessionTokenSuccess(config, res, { studentId, exchangeKind: "student_id" });
215
- }
216
- async function exchangeTimebackStudent(config, sourcedId) {
217
- const logger = config.logger;
218
- logger.debug("exchange timeback student request", { sourcedId });
219
- const res = await sendExchangeRequest(config, TIMEBACK_EXCHANGE_PATH, { sourced_id: sourcedId }, { sourcedId, exchangeKind: "timeback" });
220
- if (!res.ok) {
221
- const body = await readErrorBody(res);
222
- const sentinel = httpSentinel(res.status, body);
223
- const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
224
- logger.error("exchange timeback student http error", { status: res.status, body, sourcedId });
225
- throw errors2.wrap(sentinel, detail);
226
- }
227
- return parseTimebackSessionSuccess(config, res, sourcedId);
228
- }
229
-
230
- // src/server/hints.ts
231
- import * as errors3 from "@superbuilders/errors";
232
-
233
- // src/grade-level.ts
234
- var GRADE_LEVELS = ["K", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
235
-
236
- // src/server/hints.ts
237
- var STUDENTS_PATH = "/api/v0/students";
238
- function isObjectRecord2(value) {
239
- return typeof value === "object" && value !== null;
240
- }
241
- function toHintsErrorBody(data) {
242
- if (!isObjectRecord2(data)) {
243
- return {};
244
- }
245
- return typeof data.error === "string" ? { error: data.error } : {};
246
- }
247
- function parseHintsSuccess(data) {
248
- if (!isObjectRecord2(data)) {
249
- return;
250
- }
251
- if (typeof data.student_id !== "string") {
252
- return;
253
- }
254
- if (data.grade_level !== null && typeof data.grade_level !== "string") {
255
- return;
256
- }
257
- return {
258
- student_id: data.student_id,
259
- grade_level: data.grade_level
260
- };
261
- }
262
- function isAbortError2(err) {
263
- return err.name === "AbortError" || err.name === "TimeoutError";
264
- }
265
- function httpSentinel2(status) {
266
- if (status === 400) {
267
- return ErrBadRequest;
268
- }
269
- if (status === 401) {
270
- return ErrInvalidSecretKey;
271
- }
272
- if (status === 404) {
273
- return ErrStudentNotFound;
274
- }
275
- return ErrServerError;
276
- }
277
- async function readErrorBody2(res) {
278
- const parsed = await res.json().then(function ok(data) {
279
- return { ok: true, data };
280
- }, function fail() {
281
- return { ok: false };
282
- });
283
- if (!parsed.ok) {
284
- return {};
285
- }
286
- return toHintsErrorBody(parsed.data);
287
- }
288
- function buildRequestBody(hints) {
289
- const body = {};
290
- if (hints.gradeLevel !== undefined) {
291
- body.grade_level = hints.gradeLevel;
292
- }
293
- return JSON.stringify(body);
294
- }
295
- async function sendSetHintsRequest(config, studentId, hints) {
296
- const logger = config.logger;
297
- const fetchFn = config.fetch ? config.fetch : globalThis.fetch;
298
- const signal = config.abort ? config.abort.signal : undefined;
299
- const url = `${config.origin}${STUDENTS_PATH}/${encodeURIComponent(studentId)}/hints`;
300
- const fetchResult = await fetchFn(url, {
301
- method: "PATCH",
302
- headers: {
303
- Authorization: `Bearer ${config.secretKey}`,
304
- "Content-Type": "application/json"
305
- },
306
- body: buildRequestBody(hints),
307
- signal
308
- }).then(function ok(response) {
309
- return { ok: true, response };
310
- }, function fail(err) {
311
- return { ok: false, error: err };
312
- });
313
- if (!fetchResult.ok) {
314
- if (isAbortError2(fetchResult.error)) {
315
- logger.error("set student hints timeout", { studentId });
316
- throw errors3.wrap(ErrTimeout, fetchResult.error.message);
317
- }
318
- logger.error("set student hints network error", {
319
- studentId,
320
- error: fetchResult.error
321
- });
322
- throw errors3.wrap(ErrNetwork, fetchResult.error.message);
323
- }
324
- return fetchResult.response;
325
- }
326
- async function parseHintsSuccessResponse(config, res) {
327
- const logger = config.logger;
328
- const jsonResult = await res.json().then(function ok(data) {
329
- return { ok: true, data };
330
- }, function fail(err) {
331
- return { ok: false, error: err };
332
- });
333
- if (!jsonResult.ok) {
334
- logger.error("set hints response parse failed", { error: jsonResult.error });
335
- throw errors3.wrap(ErrJsonParse, jsonResult.error.message);
336
- }
337
- const body = parseHintsSuccess(jsonResult.data);
338
- if (!body) {
339
- logger.error("set hints response had invalid shape", { body: jsonResult.data });
340
- throw errors3.wrap(ErrJsonParse, "set hints success body had invalid shape");
341
- }
342
- logger.debug("set hints response success", {
343
- studentId: body.student_id,
344
- gradeLevel: body.grade_level
345
- });
346
- return {
347
- studentId: body.student_id,
348
- gradeLevel: coerceGradeLevel(body.grade_level)
349
- };
350
- }
351
- function coerceGradeLevel(value) {
352
- if (value === null) {
353
- return null;
354
- }
355
- for (const g of GRADE_LEVELS) {
356
- if (g === value) {
357
- return g;
358
- }
359
- }
360
- return null;
361
- }
362
- async function setStudentHints(config, studentId, hints) {
363
- const logger = config.logger;
364
- logger.debug("set student hints request", { studentId, hints });
365
- const res = await sendSetHintsRequest(config, studentId, hints);
366
- if (!res.ok) {
367
- const body = await readErrorBody2(res);
368
- const sentinel = httpSentinel2(res.status);
369
- const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
370
- logger.error("set student hints http error", {
371
- studentId,
372
- status: res.status,
373
- body
374
- });
375
- throw errors3.wrap(sentinel, detail);
376
- }
377
- return parseHintsSuccessResponse(config, res);
378
- }
379
-
380
- // src/server/students.ts
381
- import * as errors4 from "@superbuilders/errors";
382
- var STUDENTS_PATH2 = "/api/v0/students";
383
- function isObjectRecord3(value) {
384
- return typeof value === "object" && value !== null;
385
- }
386
- function toStudentsErrorBody(data) {
387
- if (!isObjectRecord3(data)) {
388
- return {};
389
- }
390
- return typeof data.error === "string" ? { error: data.error } : {};
391
- }
392
- function parseStudentIdSuccessBody(data) {
393
- if (!isObjectRecord3(data)) {
394
- return;
395
- }
396
- if (typeof data.student_id !== "string") {
397
- return;
398
- }
399
- return { student_id: data.student_id };
400
- }
401
- function isAbortError3(err) {
402
- return err.name === "AbortError" || err.name === "TimeoutError";
403
- }
404
- function httpSentinel3(status) {
405
- if (status === 400) {
406
- return ErrBadRequest;
407
- }
408
- if (status === 401) {
409
- return ErrInvalidSecretKey;
410
- }
411
- if (status === 409) {
412
- return ErrConflict;
413
- }
414
- return ErrServerError;
415
- }
416
- async function readErrorBody3(res) {
417
- const parsed = await res.json().then(function ok(data) {
418
- return { ok: true, data };
419
- }, function fail() {
420
- return { ok: false };
421
- });
422
- if (!parsed.ok) {
423
- return {};
424
- }
425
- return toStudentsErrorBody(parsed.data);
426
- }
427
- async function sendCreateStudentRequest(config) {
428
- const logger = config.logger;
429
- const fetchFn = config.fetch ? config.fetch : globalThis.fetch;
430
- const signal = config.abort ? config.abort.signal : undefined;
431
- const url = `${config.origin}${STUDENTS_PATH2}`;
432
- const fetchResult = await fetchFn(url, {
433
- method: "POST",
434
- headers: {
435
- Authorization: `Bearer ${config.secretKey}`
436
- },
437
- signal
438
- }).then(function ok(response) {
439
- return { ok: true, response };
440
- }, function fail(err) {
441
- return { ok: false, error: err };
442
- });
443
- if (!fetchResult.ok) {
444
- if (isAbortError3(fetchResult.error)) {
445
- logger.error("students timeout", { path: STUDENTS_PATH2 });
446
- throw errors4.wrap(ErrTimeout, fetchResult.error.message);
447
- }
448
- logger.error("students network error", {
449
- path: STUDENTS_PATH2,
450
- error: fetchResult.error
451
- });
452
- throw errors4.wrap(ErrNetwork, fetchResult.error.message);
453
- }
454
- return fetchResult.response;
455
- }
456
- async function parseStudentIdSuccess(config, res) {
457
- const logger = config.logger;
458
- const jsonResult = await res.json().then(function ok(data) {
459
- return { ok: true, data };
460
- }, function fail(err) {
461
- return { ok: false, error: err };
462
- });
463
- if (!jsonResult.ok) {
464
- logger.error("student id response parse failed", {
465
- operation: "create student",
466
- error: jsonResult.error
467
- });
468
- throw errors4.wrap(ErrJsonParse, jsonResult.error.message);
469
- }
470
- const body = parseStudentIdSuccessBody(jsonResult.data);
471
- if (!body) {
472
- logger.error("student id response had invalid shape", {
473
- operation: "create student",
474
- body: jsonResult.data
475
- });
476
- throw errors4.wrap(ErrJsonParse, "create student success body had invalid shape");
477
- }
478
- logger.debug("student id response success", {
479
- operation: "create student",
480
- studentId: body.student_id
481
- });
482
- return body.student_id;
483
- }
484
- async function createStudent(config) {
485
- const logger = config.logger;
486
- logger.debug("create student request");
487
- const res = await sendCreateStudentRequest(config);
488
- if (!res.ok) {
489
- const body = await readErrorBody3(res);
490
- const sentinel = httpSentinel3(res.status);
491
- const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
492
- logger.error("create student http error", { status: res.status, body });
493
- throw errors4.wrap(sentinel, detail);
494
- }
495
- return parseStudentIdSuccess(config, res);
496
- }
497
-
498
- // src/server/create-server.ts
499
- function createPrimerServer(config) {
500
- return {
501
- createStudent() {
502
- return createStudent(config);
503
- },
504
- setStudentHints(studentId, hints) {
505
- return setStudentHints(config, studentId, hints);
506
- },
507
- exchangeStudentForAccessToken(studentId) {
508
- return exchangeStudent(config, studentId);
509
- },
510
- exchangeTimebackStudentForAccessToken(sourcedId) {
511
- return exchangeTimebackStudent(config, sourcedId);
512
- }
513
- };
514
- }
515
- export {
516
- createPrimerServer,
517
- GRADE_LEVELS,
518
- ErrUnsupportedGrade,
519
- ErrTimeout,
520
- ErrTimebackUnavailable,
521
- ErrStudentNotFound,
522
- ErrServerError,
523
- ErrNetwork,
524
- ErrJsonParse,
525
- ErrInvalidSecretKey,
526
- ErrExternalAuthorityRequired,
527
- ErrConflict,
528
- ErrBadRequest
529
- };
530
-
531
- //# debugId=36162738F428CAE464756E2164756E21
@@ -1,15 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/errors.ts", "../src/server/exchange.ts", "../src/server/hints.ts", "../src/grade-level.ts", "../src/server/students.ts", "../src/server/create-server.ts"],
4
- "sourcesContent": [
5
- "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 ErrInvalidAccessToken = errors.new(\"invalid access token\")\nconst ErrMalformedAccessToken = errors.new(\"malformed access token\")\nconst ErrTokenExpired = errors.new(\"access token expired\")\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 ErrExternalAuthorityRequired = errors.new(\"external authority required\")\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\")\n\nconst ErrInvalidSecretKey = errors.new(\"invalid secret key\")\nconst ErrStudentNotFound = errors.new(\"student not found\")\nconst ErrUnsupportedGrade = errors.new(\"unsupported grade\")\nconst ErrTimebackUnavailable = errors.new(\"timeback unavailable\")\n\nexport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrExternalAuthorityRequired,\n\tErrForbidden,\n\tErrInvalidAccessToken,\n\tErrInvalidSecretKey,\n\tErrInvalidSubmission,\n\tErrJsonParse,\n\tErrMalformedAccessToken,\n\tErrNetwork,\n\tErrNotFound,\n\tErrNotSerializable,\n\tErrRateLimited,\n\tErrServerError,\n\tErrServiceUnavailable,\n\tErrStudentNotFound,\n\tErrTimebackUnavailable,\n\tErrTimeout,\n\tErrTokenExpired,\n\tErrUnsupportedGrade,\n\tErrUnsupportedPci\n}\n",
6
- "import * as errors from \"@superbuilders/errors\"\nimport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrExternalAuthorityRequired,\n\tErrInvalidSecretKey,\n\tErrJsonParse,\n\tErrNetwork,\n\tErrServerError,\n\tErrStudentNotFound,\n\tErrTimebackUnavailable,\n\tErrTimeout,\n\tErrUnsupportedGrade\n} from \"@superbuilders/primer-tives/errors\"\nimport type { PrimerLogger } from \"@superbuilders/primer-tives/logger\"\n\nconst STUDENT_EXCHANGE_PATH = \"/api/v0/auth/exchange\"\nconst TIMEBACK_EXCHANGE_PATH = \"/api/v0/auth/exchange/timeback\"\n\ninterface ExchangeConfig {\n\treadonly origin: string\n\treadonly secretKey: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly logger: PrimerLogger\n}\n\ninterface SessionToken {\n\treadonly accessToken: string\n\treadonly expiresInSeconds: number\n}\n\ninterface TimebackSession {\n\treadonly studentId: string\n\treadonly accessToken: string\n\treadonly expiresInSeconds: number\n}\n\ninterface SessionTokenSuccessBody {\n\taccess_token: string\n\ttoken_type: \"Bearer\"\n\texpires_in: number\n\tscope: string\n}\n\ninterface TimebackExchangeSuccessBody extends SessionTokenSuccessBody {\n\tstudent_id: string\n}\n\ninterface ExchangeErrorBody {\n\treadonly error?: string\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value)\n}\n\nfunction toExchangeErrorBody(data: unknown): ExchangeErrorBody {\n\tif (!isObjectRecord(data)) {\n\t\treturn {}\n\t}\n\treturn typeof data.error === \"string\" ? { error: data.error } : {}\n}\n\nfunction parseSessionTokenSuccessBody(data: unknown): SessionTokenSuccessBody | undefined {\n\tif (!isObjectRecord(data)) {\n\t\treturn undefined\n\t}\n\tif (typeof data.access_token !== \"string\") {\n\t\treturn undefined\n\t}\n\tif (data.token_type !== \"Bearer\") {\n\t\treturn undefined\n\t}\n\tif (!isFiniteNumber(data.expires_in)) {\n\t\treturn undefined\n\t}\n\tif (typeof data.scope !== \"string\") {\n\t\treturn undefined\n\t}\n\treturn {\n\t\taccess_token: data.access_token,\n\t\ttoken_type: data.token_type,\n\t\texpires_in: data.expires_in,\n\t\tscope: data.scope\n\t}\n}\n\nfunction parseTimebackExchangeSuccessBody(data: unknown): TimebackExchangeSuccessBody | undefined {\n\tconst session = parseSessionTokenSuccessBody(data)\n\tif (!session || !isObjectRecord(data) || typeof data.student_id !== \"string\") {\n\t\treturn undefined\n\t}\n\treturn {\n\t\tstudent_id: data.student_id,\n\t\taccess_token: session.access_token,\n\t\ttoken_type: session.token_type,\n\t\texpires_in: session.expires_in,\n\t\tscope: session.scope\n\t}\n}\n\nfunction isAbortError(err: Error): boolean {\n\treturn err.name === \"AbortError\" || err.name === \"TimeoutError\"\n}\n\nfunction mapBadRequest(body: ExchangeErrorBody): Error {\n\tif (body.error === \"unsupported_grade\") {\n\t\treturn ErrUnsupportedGrade\n\t}\n\treturn ErrBadRequest\n}\n\nfunction httpSentinel(status: number, body: ExchangeErrorBody): Error {\n\tif (status === 400) {\n\t\treturn mapBadRequest(body)\n\t}\n\tif (status === 401) {\n\t\treturn ErrInvalidSecretKey\n\t}\n\tif (status === 404) {\n\t\treturn ErrStudentNotFound\n\t}\n\tif (status === 409) {\n\t\tif (body.error === \"external_authority_required\") {\n\t\t\treturn ErrExternalAuthorityRequired\n\t\t}\n\t\treturn ErrConflict\n\t}\n\tif (status === 502) {\n\t\treturn ErrTimebackUnavailable\n\t}\n\treturn ErrServerError\n}\n\nasync function readErrorBody(res: Response): Promise<ExchangeErrorBody> {\n\tconst parsed = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail() {\n\t\t\treturn { ok: false } as const\n\t\t}\n\t)\n\tif (!parsed.ok) {\n\t\treturn {}\n\t}\n\treturn toExchangeErrorBody(parsed.data)\n}\n\nasync function sendExchangeRequest(\n\tconfig: ExchangeConfig,\n\tpath: string,\n\tbody: Record<string, unknown>,\n\tlogContext: Record<string, unknown>\n): Promise<Response> {\n\tconst logger = config.logger\n\tconst fetchFn = config.fetch ? config.fetch : globalThis.fetch\n\tconst signal = config.abort ? config.abort.signal : undefined\n\n\tconst url = `${config.origin}${path}`\n\tconst fetchResult = await fetchFn(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAuthorization: `Bearer ${config.secretKey}`\n\t\t},\n\t\tbody: JSON.stringify(body),\n\t\tsignal\n\t}).then(\n\t\tfunction ok(response: Response) {\n\t\t\treturn { ok: true, response } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!fetchResult.ok) {\n\t\tif (isAbortError(fetchResult.error)) {\n\t\t\tlogger.error(\"exchange timeout\", { path, ...logContext })\n\t\t\tthrow errors.wrap(ErrTimeout, fetchResult.error.message)\n\t\t}\n\t\tlogger.error(\"exchange network error\", { path, ...logContext, error: fetchResult.error })\n\t\tthrow errors.wrap(ErrNetwork, fetchResult.error.message)\n\t}\n\n\treturn fetchResult.response\n}\n\nasync function parseSessionTokenSuccess(\n\tconfig: ExchangeConfig,\n\tres: Response,\n\tlogContext: Record<string, unknown>\n): Promise<SessionToken> {\n\tconst logger = config.logger\n\tconst jsonResult = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!jsonResult.ok) {\n\t\tlogger.error(\"exchange json parse failed\", { ...logContext, error: jsonResult.error })\n\t\tthrow errors.wrap(ErrJsonParse, jsonResult.error.message)\n\t}\n\n\tconst body = parseSessionTokenSuccessBody(jsonResult.data)\n\tif (!body) {\n\t\tlogger.error(\"exchange success body had invalid shape\", {\n\t\t\t...logContext,\n\t\t\tbody: jsonResult.data\n\t\t})\n\t\tthrow errors.wrap(ErrJsonParse, \"exchange success body had invalid shape\")\n\t}\n\n\tlogger.debug(\"exchange success\", {\n\t\t...logContext,\n\t\texpiresIn: body.expires_in\n\t})\n\treturn {\n\t\taccessToken: body.access_token,\n\t\texpiresInSeconds: body.expires_in\n\t}\n}\n\nasync function parseTimebackSessionSuccess(\n\tconfig: ExchangeConfig,\n\tres: Response,\n\tsourcedId: string\n): Promise<TimebackSession> {\n\tconst logger = config.logger\n\tconst jsonResult = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!jsonResult.ok) {\n\t\tlogger.error(\"timeback exchange json parse failed\", { sourcedId, error: jsonResult.error })\n\t\tthrow errors.wrap(ErrJsonParse, jsonResult.error.message)\n\t}\n\n\tconst body = parseTimebackExchangeSuccessBody(jsonResult.data)\n\tif (!body) {\n\t\tlogger.error(\"timeback exchange success body had invalid shape\", {\n\t\t\tsourcedId,\n\t\t\tbody: jsonResult.data\n\t\t})\n\t\tthrow errors.wrap(ErrJsonParse, \"timeback exchange success body had invalid shape\")\n\t}\n\n\tlogger.debug(\"timeback exchange success\", {\n\t\tsourcedId,\n\t\tstudentId: body.student_id,\n\t\texpiresIn: body.expires_in\n\t})\n\treturn {\n\t\tstudentId: body.student_id,\n\t\taccessToken: body.access_token,\n\t\texpiresInSeconds: body.expires_in\n\t}\n}\n\nasync function exchangeStudent(config: ExchangeConfig, studentId: string): Promise<SessionToken> {\n\tconst logger = config.logger\n\tlogger.debug(\"exchange student request\", { studentId })\n\n\tconst res = await sendExchangeRequest(\n\t\tconfig,\n\t\tSTUDENT_EXCHANGE_PATH,\n\t\t{ student_id: studentId },\n\t\t{ studentId, exchangeKind: \"student_id\" }\n\t)\n\tif (!res.ok) {\n\t\tconst body = await readErrorBody(res)\n\t\tconst sentinel = httpSentinel(res.status, body)\n\t\tconst detail = body.error ? `${res.status} ${body.error}` : `${res.status}`\n\t\tlogger.error(\"exchange student http error\", { status: res.status, body, studentId })\n\t\tthrow errors.wrap(sentinel, detail)\n\t}\n\n\treturn parseSessionTokenSuccess(config, res, { studentId, exchangeKind: \"student_id\" })\n}\n\nasync function exchangeTimebackStudent(\n\tconfig: ExchangeConfig,\n\tsourcedId: string\n): Promise<TimebackSession> {\n\tconst logger = config.logger\n\tlogger.debug(\"exchange timeback student request\", { sourcedId })\n\n\tconst res = await sendExchangeRequest(\n\t\tconfig,\n\t\tTIMEBACK_EXCHANGE_PATH,\n\t\t{ sourced_id: sourcedId },\n\t\t{ sourcedId, exchangeKind: \"timeback\" }\n\t)\n\tif (!res.ok) {\n\t\tconst body = await readErrorBody(res)\n\t\tconst sentinel = httpSentinel(res.status, body)\n\t\tconst detail = body.error ? `${res.status} ${body.error}` : `${res.status}`\n\t\tlogger.error(\"exchange timeback student http error\", { status: res.status, body, sourcedId })\n\t\tthrow errors.wrap(sentinel, detail)\n\t}\n\n\treturn parseTimebackSessionSuccess(config, res, sourcedId)\n}\n\nexport type { ExchangeConfig, SessionToken, TimebackSession }\nexport { exchangeStudent, exchangeTimebackStudent }\n",
7
- "import * as errors from \"@superbuilders/errors\"\nimport {\n\tErrBadRequest,\n\tErrInvalidSecretKey,\n\tErrJsonParse,\n\tErrNetwork,\n\tErrServerError,\n\tErrStudentNotFound,\n\tErrTimeout\n} from \"@superbuilders/primer-tives/errors\"\nimport { GRADE_LEVELS, type GradeLevel } from \"@superbuilders/primer-tives/grade-level\"\nimport type { PrimerLogger } from \"@superbuilders/primer-tives/logger\"\n\nconst STUDENTS_PATH = \"/api/v0/students\"\n\ninterface HintsConfig {\n\treadonly origin: string\n\treadonly secretKey: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly logger: PrimerLogger\n}\n\n/**\n * Partial update of a student's placement hints. Pass only the fields\n * you want to set; omitted fields are left untouched. The server\n * returns the persisted state after upsert.\n */\ninterface PlacementHints {\n\treadonly gradeLevel?: GradeLevel\n}\n\ninterface PlacementHintsResult {\n\treadonly studentId: string\n\treadonly gradeLevel: GradeLevel | null\n}\n\ninterface HintsErrorBody {\n\treadonly error?: string\n}\n\ninterface HintsSuccessWire {\n\treadonly student_id: string\n\treadonly grade_level: string | null\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null\n}\n\nfunction toHintsErrorBody(data: unknown): HintsErrorBody {\n\tif (!isObjectRecord(data)) {\n\t\treturn {}\n\t}\n\treturn typeof data.error === \"string\" ? { error: data.error } : {}\n}\n\nfunction parseHintsSuccess(data: unknown): HintsSuccessWire | undefined {\n\tif (!isObjectRecord(data)) {\n\t\treturn undefined\n\t}\n\tif (typeof data.student_id !== \"string\") {\n\t\treturn undefined\n\t}\n\tif (data.grade_level !== null && typeof data.grade_level !== \"string\") {\n\t\treturn undefined\n\t}\n\treturn {\n\t\tstudent_id: data.student_id,\n\t\tgrade_level: data.grade_level\n\t}\n}\n\nfunction isAbortError(err: Error): boolean {\n\treturn err.name === \"AbortError\" || err.name === \"TimeoutError\"\n}\n\nfunction httpSentinel(status: number): Error {\n\tif (status === 400) {\n\t\treturn ErrBadRequest\n\t}\n\tif (status === 401) {\n\t\treturn ErrInvalidSecretKey\n\t}\n\tif (status === 404) {\n\t\treturn ErrStudentNotFound\n\t}\n\treturn ErrServerError\n}\n\nasync function readErrorBody(res: Response): Promise<HintsErrorBody> {\n\tconst parsed = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail() {\n\t\t\treturn { ok: false } as const\n\t\t}\n\t)\n\tif (!parsed.ok) {\n\t\treturn {}\n\t}\n\treturn toHintsErrorBody(parsed.data)\n}\n\nfunction buildRequestBody(hints: PlacementHints): string {\n\tconst body: Record<string, unknown> = {}\n\tif (hints.gradeLevel !== undefined) {\n\t\tbody.grade_level = hints.gradeLevel\n\t}\n\treturn JSON.stringify(body)\n}\n\nasync function sendSetHintsRequest(\n\tconfig: HintsConfig,\n\tstudentId: string,\n\thints: PlacementHints\n): Promise<Response> {\n\tconst logger = config.logger\n\tconst fetchFn = config.fetch ? config.fetch : globalThis.fetch\n\tconst signal = config.abort ? config.abort.signal : undefined\n\tconst url = `${config.origin}${STUDENTS_PATH}/${encodeURIComponent(studentId)}/hints`\n\n\tconst fetchResult = await fetchFn(url, {\n\t\tmethod: \"PATCH\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${config.secretKey}`,\n\t\t\t\"Content-Type\": \"application/json\"\n\t\t},\n\t\tbody: buildRequestBody(hints),\n\t\tsignal\n\t}).then(\n\t\tfunction ok(response: Response) {\n\t\t\treturn { ok: true, response } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!fetchResult.ok) {\n\t\tif (isAbortError(fetchResult.error)) {\n\t\t\tlogger.error(\"set student hints timeout\", { studentId })\n\t\t\tthrow errors.wrap(ErrTimeout, fetchResult.error.message)\n\t\t}\n\t\tlogger.error(\"set student hints network error\", {\n\t\t\tstudentId,\n\t\t\terror: fetchResult.error\n\t\t})\n\t\tthrow errors.wrap(ErrNetwork, fetchResult.error.message)\n\t}\n\n\treturn fetchResult.response\n}\n\nasync function parseHintsSuccessResponse(\n\tconfig: HintsConfig,\n\tres: Response\n): Promise<PlacementHintsResult> {\n\tconst logger = config.logger\n\tconst jsonResult = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!jsonResult.ok) {\n\t\tlogger.error(\"set hints response parse failed\", { error: jsonResult.error })\n\t\tthrow errors.wrap(ErrJsonParse, jsonResult.error.message)\n\t}\n\n\tconst body = parseHintsSuccess(jsonResult.data)\n\tif (!body) {\n\t\tlogger.error(\"set hints response had invalid shape\", { body: jsonResult.data })\n\t\tthrow errors.wrap(ErrJsonParse, \"set hints success body had invalid shape\")\n\t}\n\n\tlogger.debug(\"set hints response success\", {\n\t\tstudentId: body.student_id,\n\t\tgradeLevel: body.grade_level\n\t})\n\n\treturn {\n\t\tstudentId: body.student_id,\n\t\tgradeLevel: coerceGradeLevel(body.grade_level)\n\t}\n}\n\nfunction coerceGradeLevel(value: string | null): GradeLevel | null {\n\tif (value === null) {\n\t\treturn null\n\t}\n\tfor (const g of GRADE_LEVELS) {\n\t\tif (g === value) {\n\t\t\treturn g\n\t\t}\n\t}\n\treturn null\n}\n\nasync function setStudentHints(\n\tconfig: HintsConfig,\n\tstudentId: string,\n\thints: PlacementHints\n): Promise<PlacementHintsResult> {\n\tconst logger = config.logger\n\tlogger.debug(\"set student hints request\", { studentId, hints })\n\n\tconst res = await sendSetHintsRequest(config, studentId, hints)\n\tif (!res.ok) {\n\t\tconst body = await readErrorBody(res)\n\t\tconst sentinel = httpSentinel(res.status)\n\t\tconst detail = body.error ? `${res.status} ${body.error}` : `${res.status}`\n\t\tlogger.error(\"set student hints http error\", {\n\t\t\tstudentId,\n\t\t\tstatus: res.status,\n\t\t\tbody\n\t\t})\n\t\tthrow errors.wrap(sentinel, detail)\n\t}\n\n\treturn parseHintsSuccessResponse(config, res)\n}\n\nexport type { HintsConfig, PlacementHints, PlacementHintsResult }\nexport { setStudentHints }\n",
8
- "const GRADE_LEVELS = [\"K\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\", \"12\"] as const\n\ntype GradeLevel = (typeof GRADE_LEVELS)[number]\n\nexport { GRADE_LEVELS }\nexport type { GradeLevel }\n",
9
- "import * as errors from \"@superbuilders/errors\"\nimport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrInvalidSecretKey,\n\tErrJsonParse,\n\tErrNetwork,\n\tErrServerError,\n\tErrTimeout\n} from \"@superbuilders/primer-tives/errors\"\nimport type { PrimerLogger } from \"@superbuilders/primer-tives/logger\"\n\nconst STUDENTS_PATH = \"/api/v0/students\"\n\ninterface StudentsConfig {\n\treadonly origin: string\n\treadonly secretKey: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly logger: PrimerLogger\n}\n\ninterface StudentIdSuccessBody {\n\tstudent_id: string\n}\n\ninterface StudentsErrorBody {\n\treadonly error?: string\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null\n}\n\nfunction toStudentsErrorBody(data: unknown): StudentsErrorBody {\n\tif (!isObjectRecord(data)) {\n\t\treturn {}\n\t}\n\treturn typeof data.error === \"string\" ? { error: data.error } : {}\n}\n\nfunction parseStudentIdSuccessBody(data: unknown): StudentIdSuccessBody | undefined {\n\tif (!isObjectRecord(data)) {\n\t\treturn undefined\n\t}\n\tif (typeof data.student_id !== \"string\") {\n\t\treturn undefined\n\t}\n\treturn { student_id: data.student_id }\n}\n\nfunction isAbortError(err: Error): boolean {\n\treturn err.name === \"AbortError\" || err.name === \"TimeoutError\"\n}\n\nfunction httpSentinel(status: number): Error {\n\tif (status === 400) {\n\t\treturn ErrBadRequest\n\t}\n\tif (status === 401) {\n\t\treturn ErrInvalidSecretKey\n\t}\n\tif (status === 409) {\n\t\treturn ErrConflict\n\t}\n\treturn ErrServerError\n}\n\nasync function readErrorBody(res: Response): Promise<StudentsErrorBody> {\n\tconst parsed = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail() {\n\t\t\treturn { ok: false } as const\n\t\t}\n\t)\n\tif (!parsed.ok) {\n\t\treturn {}\n\t}\n\treturn toStudentsErrorBody(parsed.data)\n}\n\nasync function sendCreateStudentRequest(config: StudentsConfig): Promise<Response> {\n\tconst logger = config.logger\n\tconst fetchFn = config.fetch ? config.fetch : globalThis.fetch\n\tconst signal = config.abort ? config.abort.signal : undefined\n\tconst url = `${config.origin}${STUDENTS_PATH}`\n\tconst fetchResult = await fetchFn(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${config.secretKey}`\n\t\t},\n\t\tsignal\n\t}).then(\n\t\tfunction ok(response: Response) {\n\t\t\treturn { ok: true, response } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!fetchResult.ok) {\n\t\tif (isAbortError(fetchResult.error)) {\n\t\t\tlogger.error(\"students timeout\", { path: STUDENTS_PATH })\n\t\t\tthrow errors.wrap(ErrTimeout, fetchResult.error.message)\n\t\t}\n\t\tlogger.error(\"students network error\", {\n\t\t\tpath: STUDENTS_PATH,\n\t\t\terror: fetchResult.error\n\t\t})\n\t\tthrow errors.wrap(ErrNetwork, fetchResult.error.message)\n\t}\n\n\treturn fetchResult.response\n}\n\nasync function parseStudentIdSuccess(config: StudentsConfig, res: Response): Promise<string> {\n\tconst logger = config.logger\n\tconst jsonResult = await res.json().then(\n\t\tfunction ok(data: unknown) {\n\t\t\treturn { ok: true, data } as const\n\t\t},\n\t\tfunction fail(err: Error) {\n\t\t\treturn { ok: false, error: err } as const\n\t\t}\n\t)\n\n\tif (!jsonResult.ok) {\n\t\tlogger.error(\"student id response parse failed\", {\n\t\t\toperation: \"create student\",\n\t\t\terror: jsonResult.error\n\t\t})\n\t\tthrow errors.wrap(ErrJsonParse, jsonResult.error.message)\n\t}\n\n\tconst body = parseStudentIdSuccessBody(jsonResult.data)\n\tif (!body) {\n\t\tlogger.error(\"student id response had invalid shape\", {\n\t\t\toperation: \"create student\",\n\t\t\tbody: jsonResult.data\n\t\t})\n\t\tthrow errors.wrap(ErrJsonParse, \"create student success body had invalid shape\")\n\t}\n\n\tlogger.debug(\"student id response success\", {\n\t\toperation: \"create student\",\n\t\tstudentId: body.student_id\n\t})\n\treturn body.student_id\n}\n\nasync function createStudent(config: StudentsConfig): Promise<string> {\n\tconst logger = config.logger\n\tlogger.debug(\"create student request\")\n\n\tconst res = await sendCreateStudentRequest(config)\n\tif (!res.ok) {\n\t\tconst body = await readErrorBody(res)\n\t\tconst sentinel = httpSentinel(res.status)\n\t\tconst detail = body.error ? `${res.status} ${body.error}` : `${res.status}`\n\t\tlogger.error(\"create student http error\", { status: res.status, body })\n\t\tthrow errors.wrap(sentinel, detail)\n\t}\n\n\treturn parseStudentIdSuccess(config, res)\n}\n\nexport type { StudentsConfig }\nexport { createStudent }\n",
10
- "import type { PrimerLogger } from \"@superbuilders/primer-tives/logger\"\nimport {\n\ttype SessionToken,\n\ttype TimebackSession,\n\texchangeStudent,\n\texchangeTimebackStudent\n} from \"@superbuilders/primer-tives/server/exchange\"\n\nimport {\n\ttype PlacementHints,\n\ttype PlacementHintsResult,\n\tsetStudentHints\n} from \"@superbuilders/primer-tives/server/hints\"\nimport { createStudent } from \"@superbuilders/primer-tives/server/students\"\n\ninterface PrimerServerConfig {\n\treadonly origin: string\n\treadonly secretKey: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly logger: PrimerLogger\n}\n\ninterface PrimerServer {\n\t/**\n\t * Provisions a frontend-owned Primer student and returns the stable\n\t * student id you persist in your own DB keyed by your user. Native\n\t * students are created hint-less; call `setStudentHints` at least\n\t * once (with a `gradeLevel`) before the student's first session, or\n\t * the first `/advance` call will 500.\n\t */\n\tcreateStudent(): Promise<string>\n\n\t/**\n\t * Partial update of a student's placement-routing hints. Pass only\n\t * the fields you want to set; omitted fields are left untouched.\n\t * Returns the persisted state after upsert. Today the only hint is\n\t * `gradeLevel`; future hint kinds (raw context, interests, etc.)\n\t * will appear as additional optional fields.\n\t */\n\tsetStudentHints(studentId: string, hints: PlacementHints): Promise<PlacementHintsResult>\n\n\t/**\n\t * Exchanges a frontend-owned native/manual student id for a short-lived\n\t * access token. Pass `accessToken` from the returned `SessionToken` to\n\t * `create()` on the browser SDK.\n\t */\n\texchangeStudentForAccessToken(studentId: string): Promise<SessionToken>\n\n\t/**\n\t * Verifies the learner against live Timeback authority, resolves or\n\t * provisions the corresponding frontend-owned Primer student, and\n\t * returns both the stable student id and a short-lived access token.\n\t */\n\texchangeTimebackStudentForAccessToken(sourcedId: string): Promise<TimebackSession>\n}\n\nfunction createPrimerServer(config: PrimerServerConfig): PrimerServer {\n\treturn {\n\t\tcreateStudent(): Promise<string> {\n\t\t\treturn createStudent(config)\n\t\t},\n\t\tsetStudentHints(studentId, hints): Promise<PlacementHintsResult> {\n\t\t\treturn setStudentHints(config, studentId, hints)\n\t\t},\n\t\texchangeStudentForAccessToken(studentId): Promise<SessionToken> {\n\t\t\treturn exchangeStudent(config, studentId)\n\t\t},\n\t\texchangeTimebackStudentForAccessToken(sourcedId): Promise<TimebackSession> {\n\t\t\treturn exchangeTimebackStudent(config, sourcedId)\n\t\t}\n\t}\n}\n\nexport type { PrimerServer, PrimerServerConfig }\nexport { createPrimerServer }\n"
11
- ],
12
- "mappings": "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",
13
- "debugId": "36162738F428CAE464756E2164756E21",
14
- "names": []
15
- }
@@ -1,12 +0,0 @@
1
- import type { PrimerLogger } from "../logger";
2
- interface StudentsConfig {
3
- readonly origin: string;
4
- readonly secretKey: string;
5
- readonly fetch?: typeof globalThis.fetch;
6
- readonly abort?: AbortController;
7
- readonly logger: PrimerLogger;
8
- }
9
- declare function createStudent(config: StudentsConfig): Promise<string>;
10
- export type { StudentsConfig };
11
- export { createStudent };
12
- //# sourceMappingURL=students.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"students.d.ts","sourceRoot":"","sources":["../../src/server/students.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAItE,UAAU,cAAc;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAC7B;AAqID,iBAAe,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAcpE;AAED,YAAY,EAAE,cAAc,EAAE,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,CAAA"}
package/dist/subject.d.ts DELETED
@@ -1,6 +0,0 @@
1
- declare const SUBJECTS: readonly ["math", "vocabulary", "science"];
2
- type Subject = (typeof SUBJECTS)[number];
3
- type SubjectScope = Subject | "all";
4
- export { SUBJECTS };
5
- export type { Subject, SubjectScope };
6
- //# sourceMappingURL=subject.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../src/subject.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,QAAQ,4CAA6C,CAAA;AAE3D,KAAK,OAAO,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAExC,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,CAAA;AAEnC,OAAO,EAAE,QAAQ,EAAE,CAAA;AACnB,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,CAAA"}