@superbuilders/primer-tives 1.2.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +744 -533
- package/dist/client/choice-state.d.ts +2 -1
- package/dist/client/choice-state.d.ts.map +1 -1
- package/dist/client/create.d.ts +23 -7
- package/dist/client/create.d.ts.map +1 -1
- package/dist/client/extended-text-state.d.ts +2 -1
- package/dist/client/extended-text-state.d.ts.map +1 -1
- package/dist/client/feedback-state.d.ts +2 -2
- package/dist/client/feedback-state.d.ts.map +1 -1
- package/dist/client/index.js +226 -109
- package/dist/client/index.js.map +21 -17
- package/dist/client/match-state.d.ts +2 -1
- package/dist/client/match-state.d.ts.map +1 -1
- package/dist/client/observation-state.d.ts +2 -1
- package/dist/client/observation-state.d.ts.map +1 -1
- package/dist/client/order-state.d.ts +2 -1
- package/dist/client/order-state.d.ts.map +1 -1
- package/dist/client/pci-state.d.ts +2 -1
- package/dist/client/pci-state.d.ts.map +1 -1
- package/dist/client/session-context.d.ts +1 -1
- package/dist/client/session-context.d.ts.map +1 -1
- package/dist/client/session.d.ts +2 -2
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/text-entry-state.d.ts +2 -1
- package/dist/client/text-entry-state.d.ts.map +1 -1
- package/dist/client/transport.d.ts +13 -11
- package/dist/client/transport.d.ts.map +1 -1
- package/dist/client/types.d.ts +10 -1
- package/dist/client/types.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +4 -3
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +42 -36
- package/dist/contracts/index.js.map +6 -5
- package/dist/contracts/pci-schemas.d.ts +24 -20
- package/dist/contracts/pci-schemas.d.ts.map +1 -1
- package/dist/contracts/pci.d.ts +26 -27
- package/dist/contracts/pci.d.ts.map +1 -1
- package/dist/contracts/types.d.ts +5 -9
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/validation.d.ts +34 -23
- package/dist/contracts/validation.d.ts.map +1 -1
- package/dist/errors.d.ts +3 -6
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -11
- package/dist/errors.js.map +3 -3
- package/dist/server/create-server.d.ts +3 -33
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/exchange.d.ts +7 -14
- package/dist/server/exchange.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +32 -407
- package/dist/server/index.js.map +6 -9
- package/dist/subject-pcis.d.ts +13 -0
- package/dist/subject-pcis.d.ts.map +1 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +5 -1
- package/dist/server/hints.d.ts +0 -25
- package/dist/server/hints.d.ts.map +0 -1
- package/dist/server/students.d.ts +0 -12
- package/dist/server/students.d.ts.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as errors from "@superbuilders/errors";
|
|
|
3
3
|
var ErrNetwork = errors.new("network");
|
|
4
4
|
var ErrJsonParse = errors.new("json parse");
|
|
5
5
|
var ErrUnsupportedPci = errors.new("unsupported pci");
|
|
6
|
+
var ErrMissingRequiredPci = errors.new("missing required pci");
|
|
6
7
|
var ErrInvalidAccessToken = errors.new("invalid access token");
|
|
7
8
|
var ErrMalformedAccessToken = errors.new("malformed access token");
|
|
8
9
|
var ErrTokenExpired = errors.new("access token expired");
|
|
@@ -12,98 +13,46 @@ var ErrTimeout = errors.new("timeout");
|
|
|
12
13
|
var ErrForbidden = errors.new("forbidden");
|
|
13
14
|
var ErrNotFound = errors.new("not found");
|
|
14
15
|
var ErrConflict = errors.new("conflict");
|
|
15
|
-
var ErrExternalAuthorityRequired = errors.new("external authority required");
|
|
16
16
|
var ErrRateLimited = errors.new("rate limited");
|
|
17
17
|
var ErrServiceUnavailable = errors.new("service unavailable");
|
|
18
18
|
var ErrNotSerializable = errors.new("PrimerState is live in-memory state and must not be serialized or stored");
|
|
19
19
|
var ErrInvalidSubmission = errors.new("invalid submission");
|
|
20
20
|
var ErrInvalidSecretKey = errors.new("invalid secret key");
|
|
21
|
-
var
|
|
22
|
-
var ErrUnsupportedGrade = errors.new("unsupported grade");
|
|
23
|
-
var ErrTimebackUnavailable = errors.new("timeback unavailable");
|
|
24
|
-
var ErrNeedsHints = errors.new("student needs hints set before /advance");
|
|
25
|
-
// src/grade-level.ts
|
|
26
|
-
var GRADE_LEVELS = ["K", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
|
|
21
|
+
var ErrSdkUpgradeRequired = errors.new("sdk upgrade required");
|
|
27
22
|
// src/server/exchange.ts
|
|
28
23
|
import * as errors2 from "@superbuilders/errors";
|
|
29
|
-
var
|
|
30
|
-
var TIMEBACK_EXCHANGE_PATH = "/api/v0/auth/exchange/timeback";
|
|
24
|
+
var TOKEN_PATH = "/api/v0/sessions";
|
|
31
25
|
function isObjectRecord(value) {
|
|
32
26
|
return typeof value === "object" && value !== null;
|
|
33
27
|
}
|
|
34
|
-
function
|
|
35
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
36
|
-
}
|
|
37
|
-
function toExchangeErrorBody(data) {
|
|
28
|
+
function toTokenErrorBody(data) {
|
|
38
29
|
if (!isObjectRecord(data)) {
|
|
39
30
|
return {};
|
|
40
31
|
}
|
|
41
32
|
return typeof data.error === "string" ? { error: data.error } : {};
|
|
42
33
|
}
|
|
43
|
-
function
|
|
34
|
+
function parseTokenSuccessBody(data) {
|
|
44
35
|
if (!isObjectRecord(data)) {
|
|
45
36
|
return;
|
|
46
37
|
}
|
|
47
|
-
if (typeof data.access_token !== "string") {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (data.token_type !== "Bearer") {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (!isFiniteNumber(data.expires_in)) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (typeof data.scope !== "string") {
|
|
38
|
+
if (typeof data.access_token !== "string" || data.token_type !== "Bearer") {
|
|
57
39
|
return;
|
|
58
40
|
}
|
|
59
41
|
return {
|
|
60
42
|
access_token: data.access_token,
|
|
61
|
-
token_type:
|
|
62
|
-
expires_in: data.expires_in,
|
|
63
|
-
scope: data.scope
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function parseTimebackExchangeSuccessBody(data) {
|
|
67
|
-
const session = parseSessionTokenSuccessBody(data);
|
|
68
|
-
if (!session || !isObjectRecord(data) || typeof data.student_id !== "string") {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
student_id: data.student_id,
|
|
73
|
-
access_token: session.access_token,
|
|
74
|
-
token_type: session.token_type,
|
|
75
|
-
expires_in: session.expires_in,
|
|
76
|
-
scope: session.scope
|
|
43
|
+
token_type: "Bearer"
|
|
77
44
|
};
|
|
78
45
|
}
|
|
79
46
|
function isAbortError(err) {
|
|
80
47
|
return err.name === "AbortError" || err.name === "TimeoutError";
|
|
81
48
|
}
|
|
82
|
-
function
|
|
83
|
-
if (body.error === "unsupported_grade") {
|
|
84
|
-
return ErrUnsupportedGrade;
|
|
85
|
-
}
|
|
86
|
-
return ErrBadRequest;
|
|
87
|
-
}
|
|
88
|
-
function httpSentinel(status, body) {
|
|
49
|
+
function httpSentinel(status) {
|
|
89
50
|
if (status === 400) {
|
|
90
|
-
return
|
|
51
|
+
return ErrBadRequest;
|
|
91
52
|
}
|
|
92
53
|
if (status === 401) {
|
|
93
54
|
return ErrInvalidSecretKey;
|
|
94
55
|
}
|
|
95
|
-
if (status === 404) {
|
|
96
|
-
return ErrStudentNotFound;
|
|
97
|
-
}
|
|
98
|
-
if (status === 409) {
|
|
99
|
-
if (body.error === "external_authority_required") {
|
|
100
|
-
return ErrExternalAuthorityRequired;
|
|
101
|
-
}
|
|
102
|
-
return ErrConflict;
|
|
103
|
-
}
|
|
104
|
-
if (status === 502) {
|
|
105
|
-
return ErrTimebackUnavailable;
|
|
106
|
-
}
|
|
107
56
|
return ErrServerError;
|
|
108
57
|
}
|
|
109
58
|
async function readErrorBody(res) {
|
|
@@ -115,20 +64,20 @@ async function readErrorBody(res) {
|
|
|
115
64
|
if (!parsed.ok) {
|
|
116
65
|
return {};
|
|
117
66
|
}
|
|
118
|
-
return
|
|
67
|
+
return toTokenErrorBody(parsed.data);
|
|
119
68
|
}
|
|
120
|
-
async function
|
|
69
|
+
async function sendTokenRequest(config, input) {
|
|
121
70
|
const logger = config.logger;
|
|
122
71
|
const fetchFn = config.fetch ? config.fetch : globalThis.fetch;
|
|
123
72
|
const signal = config.abort ? config.abort.signal : undefined;
|
|
124
|
-
const url = `${config.origin}${
|
|
73
|
+
const url = `${config.origin}${TOKEN_PATH}`;
|
|
125
74
|
const fetchResult = await fetchFn(url, {
|
|
126
75
|
method: "POST",
|
|
127
76
|
headers: {
|
|
128
77
|
"Content-Type": "application/json",
|
|
129
78
|
Authorization: `Bearer ${config.secretKey}`
|
|
130
79
|
},
|
|
131
|
-
body: JSON.stringify(
|
|
80
|
+
body: JSON.stringify({ verified_email: input.verifiedEmail }),
|
|
132
81
|
signal
|
|
133
82
|
}).then(function ok(response) {
|
|
134
83
|
return { ok: true, response };
|
|
@@ -137,43 +86,15 @@ async function sendExchangeRequest(config, path, body, logContext) {
|
|
|
137
86
|
});
|
|
138
87
|
if (!fetchResult.ok) {
|
|
139
88
|
if (isAbortError(fetchResult.error)) {
|
|
140
|
-
logger.error("
|
|
89
|
+
logger.error("token request timeout");
|
|
141
90
|
throw errors2.wrap(ErrTimeout, fetchResult.error.message);
|
|
142
91
|
}
|
|
143
|
-
logger.error("
|
|
92
|
+
logger.error("token request network error", { error: fetchResult.error });
|
|
144
93
|
throw errors2.wrap(ErrNetwork, fetchResult.error.message);
|
|
145
94
|
}
|
|
146
95
|
return fetchResult.response;
|
|
147
96
|
}
|
|
148
|
-
async function
|
|
149
|
-
const logger = config.logger;
|
|
150
|
-
const jsonResult = await res.json().then(function ok(data) {
|
|
151
|
-
return { ok: true, data };
|
|
152
|
-
}, function fail(err) {
|
|
153
|
-
return { ok: false, error: err };
|
|
154
|
-
});
|
|
155
|
-
if (!jsonResult.ok) {
|
|
156
|
-
logger.error("exchange json parse failed", { ...logContext, error: jsonResult.error });
|
|
157
|
-
throw errors2.wrap(ErrJsonParse, jsonResult.error.message);
|
|
158
|
-
}
|
|
159
|
-
const body = parseSessionTokenSuccessBody(jsonResult.data);
|
|
160
|
-
if (!body) {
|
|
161
|
-
logger.error("exchange success body had invalid shape", {
|
|
162
|
-
...logContext,
|
|
163
|
-
body: jsonResult.data
|
|
164
|
-
});
|
|
165
|
-
throw errors2.wrap(ErrJsonParse, "exchange success body had invalid shape");
|
|
166
|
-
}
|
|
167
|
-
logger.debug("exchange success", {
|
|
168
|
-
...logContext,
|
|
169
|
-
expiresIn: body.expires_in
|
|
170
|
-
});
|
|
171
|
-
return {
|
|
172
|
-
accessToken: body.access_token,
|
|
173
|
-
expiresInSeconds: body.expires_in
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
async function parseTimebackSessionSuccess(config, res, sourcedId) {
|
|
97
|
+
async function parseToken(config, res) {
|
|
177
98
|
const logger = config.logger;
|
|
178
99
|
const jsonResult = await res.json().then(function ok(data) {
|
|
179
100
|
return { ok: true, data };
|
|
@@ -181,332 +102,36 @@ async function parseTimebackSessionSuccess(config, res, sourcedId) {
|
|
|
181
102
|
return { ok: false, error: err };
|
|
182
103
|
});
|
|
183
104
|
if (!jsonResult.ok) {
|
|
184
|
-
logger.error("
|
|
105
|
+
logger.error("token response json parse failed", { error: jsonResult.error });
|
|
185
106
|
throw errors2.wrap(ErrJsonParse, jsonResult.error.message);
|
|
186
107
|
}
|
|
187
|
-
const body =
|
|
188
|
-
if (
|
|
189
|
-
logger.error("
|
|
190
|
-
|
|
191
|
-
body: jsonResult.data
|
|
192
|
-
});
|
|
193
|
-
throw errors2.wrap(ErrJsonParse, "timeback exchange success body had invalid shape");
|
|
194
|
-
}
|
|
195
|
-
logger.debug("timeback exchange success", {
|
|
196
|
-
sourcedId,
|
|
197
|
-
studentId: body.student_id,
|
|
198
|
-
expiresIn: body.expires_in
|
|
199
|
-
});
|
|
200
|
-
return {
|
|
201
|
-
studentId: body.student_id,
|
|
202
|
-
accessToken: body.access_token,
|
|
203
|
-
expiresInSeconds: body.expires_in
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
async function exchangeStudent(config, studentId) {
|
|
207
|
-
const logger = config.logger;
|
|
208
|
-
logger.debug("exchange student request", { studentId });
|
|
209
|
-
const res = await sendExchangeRequest(config, STUDENT_EXCHANGE_PATH, { student_id: studentId }, { studentId, exchangeKind: "student_id" });
|
|
210
|
-
if (!res.ok) {
|
|
211
|
-
const body = await readErrorBody(res);
|
|
212
|
-
const sentinel = httpSentinel(res.status, body);
|
|
213
|
-
const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
|
|
214
|
-
logger.error("exchange student http error", { status: res.status, body, studentId });
|
|
215
|
-
throw errors2.wrap(sentinel, detail);
|
|
108
|
+
const body = parseTokenSuccessBody(jsonResult.data);
|
|
109
|
+
if (body === undefined) {
|
|
110
|
+
logger.error("token response had invalid shape", { body: jsonResult.data });
|
|
111
|
+
throw errors2.wrap(ErrJsonParse, "token response had invalid shape");
|
|
216
112
|
}
|
|
217
|
-
|
|
113
|
+
logger.debug("token request success");
|
|
114
|
+
return body.access_token;
|
|
218
115
|
}
|
|
219
|
-
async function
|
|
116
|
+
async function getToken(config, input) {
|
|
220
117
|
const logger = config.logger;
|
|
221
|
-
logger.debug("
|
|
222
|
-
const res = await
|
|
118
|
+
logger.debug("token request");
|
|
119
|
+
const res = await sendTokenRequest(config, input);
|
|
223
120
|
if (!res.ok) {
|
|
224
121
|
const body = await readErrorBody(res);
|
|
225
|
-
const sentinel = httpSentinel(res.status
|
|
122
|
+
const sentinel = httpSentinel(res.status);
|
|
226
123
|
const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
|
|
227
|
-
logger.error("
|
|
124
|
+
logger.error("token request http error", { status: res.status, body });
|
|
228
125
|
throw errors2.wrap(sentinel, detail);
|
|
229
126
|
}
|
|
230
|
-
return
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// src/server/hints.ts
|
|
234
|
-
import * as errors3 from "@superbuilders/errors";
|
|
235
|
-
var STUDENTS_PATH = "/api/v0/students";
|
|
236
|
-
function isObjectRecord2(value) {
|
|
237
|
-
return typeof value === "object" && value !== null;
|
|
238
|
-
}
|
|
239
|
-
function toHintsErrorBody(data) {
|
|
240
|
-
if (!isObjectRecord2(data)) {
|
|
241
|
-
return {};
|
|
242
|
-
}
|
|
243
|
-
return typeof data.error === "string" ? { error: data.error } : {};
|
|
244
|
-
}
|
|
245
|
-
function parseHintsSuccess(data) {
|
|
246
|
-
if (!isObjectRecord2(data)) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
if (typeof data.student_id !== "string") {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
if (data.grade_level !== null && typeof data.grade_level !== "string") {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
return {
|
|
256
|
-
student_id: data.student_id,
|
|
257
|
-
grade_level: data.grade_level
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
function isAbortError2(err) {
|
|
261
|
-
return err.name === "AbortError" || err.name === "TimeoutError";
|
|
262
|
-
}
|
|
263
|
-
function httpSentinel2(status) {
|
|
264
|
-
if (status === 400) {
|
|
265
|
-
return ErrBadRequest;
|
|
266
|
-
}
|
|
267
|
-
if (status === 401) {
|
|
268
|
-
return ErrInvalidSecretKey;
|
|
269
|
-
}
|
|
270
|
-
if (status === 404) {
|
|
271
|
-
return ErrStudentNotFound;
|
|
272
|
-
}
|
|
273
|
-
return ErrServerError;
|
|
274
|
-
}
|
|
275
|
-
async function readErrorBody2(res) {
|
|
276
|
-
const parsed = await res.json().then(function ok(data) {
|
|
277
|
-
return { ok: true, data };
|
|
278
|
-
}, function fail() {
|
|
279
|
-
return { ok: false };
|
|
280
|
-
});
|
|
281
|
-
if (!parsed.ok) {
|
|
282
|
-
return {};
|
|
283
|
-
}
|
|
284
|
-
return toHintsErrorBody(parsed.data);
|
|
285
|
-
}
|
|
286
|
-
function buildRequestBody(hints) {
|
|
287
|
-
const body = {};
|
|
288
|
-
if (hints.gradeLevel !== undefined) {
|
|
289
|
-
body.grade_level = hints.gradeLevel;
|
|
290
|
-
}
|
|
291
|
-
return JSON.stringify(body);
|
|
292
|
-
}
|
|
293
|
-
async function sendSetHintsRequest(config, studentId, hints) {
|
|
294
|
-
const logger = config.logger;
|
|
295
|
-
const fetchFn = config.fetch ? config.fetch : globalThis.fetch;
|
|
296
|
-
const signal = config.abort ? config.abort.signal : undefined;
|
|
297
|
-
const url = `${config.origin}${STUDENTS_PATH}/${encodeURIComponent(studentId)}/hints`;
|
|
298
|
-
const fetchResult = await fetchFn(url, {
|
|
299
|
-
method: "PATCH",
|
|
300
|
-
headers: {
|
|
301
|
-
Authorization: `Bearer ${config.secretKey}`,
|
|
302
|
-
"Content-Type": "application/json"
|
|
303
|
-
},
|
|
304
|
-
body: buildRequestBody(hints),
|
|
305
|
-
signal
|
|
306
|
-
}).then(function ok(response) {
|
|
307
|
-
return { ok: true, response };
|
|
308
|
-
}, function fail(err) {
|
|
309
|
-
return { ok: false, error: err };
|
|
310
|
-
});
|
|
311
|
-
if (!fetchResult.ok) {
|
|
312
|
-
if (isAbortError2(fetchResult.error)) {
|
|
313
|
-
logger.error("set student hints timeout", { studentId });
|
|
314
|
-
throw errors3.wrap(ErrTimeout, fetchResult.error.message);
|
|
315
|
-
}
|
|
316
|
-
logger.error("set student hints network error", {
|
|
317
|
-
studentId,
|
|
318
|
-
error: fetchResult.error
|
|
319
|
-
});
|
|
320
|
-
throw errors3.wrap(ErrNetwork, fetchResult.error.message);
|
|
321
|
-
}
|
|
322
|
-
return fetchResult.response;
|
|
323
|
-
}
|
|
324
|
-
async function parseHintsSuccessResponse(config, res) {
|
|
325
|
-
const logger = config.logger;
|
|
326
|
-
const jsonResult = await res.json().then(function ok(data) {
|
|
327
|
-
return { ok: true, data };
|
|
328
|
-
}, function fail(err) {
|
|
329
|
-
return { ok: false, error: err };
|
|
330
|
-
});
|
|
331
|
-
if (!jsonResult.ok) {
|
|
332
|
-
logger.error("set hints response parse failed", { error: jsonResult.error });
|
|
333
|
-
throw errors3.wrap(ErrJsonParse, jsonResult.error.message);
|
|
334
|
-
}
|
|
335
|
-
const body = parseHintsSuccess(jsonResult.data);
|
|
336
|
-
if (!body) {
|
|
337
|
-
logger.error("set hints response had invalid shape", { body: jsonResult.data });
|
|
338
|
-
throw errors3.wrap(ErrJsonParse, "set hints success body had invalid shape");
|
|
339
|
-
}
|
|
340
|
-
logger.debug("set hints response success", {
|
|
341
|
-
studentId: body.student_id,
|
|
342
|
-
gradeLevel: body.grade_level
|
|
343
|
-
});
|
|
344
|
-
return {
|
|
345
|
-
studentId: body.student_id,
|
|
346
|
-
gradeLevel: coerceGradeLevel(body.grade_level)
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
function coerceGradeLevel(value) {
|
|
350
|
-
if (value === null) {
|
|
351
|
-
return null;
|
|
352
|
-
}
|
|
353
|
-
for (const g of GRADE_LEVELS) {
|
|
354
|
-
if (g === value) {
|
|
355
|
-
return g;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return null;
|
|
359
|
-
}
|
|
360
|
-
async function setStudentHints(config, studentId, hints) {
|
|
361
|
-
const logger = config.logger;
|
|
362
|
-
logger.debug("set student hints request", { studentId, hints });
|
|
363
|
-
const res = await sendSetHintsRequest(config, studentId, hints);
|
|
364
|
-
if (!res.ok) {
|
|
365
|
-
const body = await readErrorBody2(res);
|
|
366
|
-
const sentinel = httpSentinel2(res.status);
|
|
367
|
-
const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
|
|
368
|
-
logger.error("set student hints http error", {
|
|
369
|
-
studentId,
|
|
370
|
-
status: res.status,
|
|
371
|
-
body
|
|
372
|
-
});
|
|
373
|
-
throw errors3.wrap(sentinel, detail);
|
|
374
|
-
}
|
|
375
|
-
return parseHintsSuccessResponse(config, res);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// src/server/students.ts
|
|
379
|
-
import * as errors4 from "@superbuilders/errors";
|
|
380
|
-
var STUDENTS_PATH2 = "/api/v0/students";
|
|
381
|
-
function isObjectRecord3(value) {
|
|
382
|
-
return typeof value === "object" && value !== null;
|
|
383
|
-
}
|
|
384
|
-
function toStudentsErrorBody(data) {
|
|
385
|
-
if (!isObjectRecord3(data)) {
|
|
386
|
-
return {};
|
|
387
|
-
}
|
|
388
|
-
return typeof data.error === "string" ? { error: data.error } : {};
|
|
389
|
-
}
|
|
390
|
-
function parseStudentIdSuccessBody(data) {
|
|
391
|
-
if (!isObjectRecord3(data)) {
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
if (typeof data.student_id !== "string") {
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
return { student_id: data.student_id };
|
|
398
|
-
}
|
|
399
|
-
function isAbortError3(err) {
|
|
400
|
-
return err.name === "AbortError" || err.name === "TimeoutError";
|
|
401
|
-
}
|
|
402
|
-
function httpSentinel3(status) {
|
|
403
|
-
if (status === 400) {
|
|
404
|
-
return ErrBadRequest;
|
|
405
|
-
}
|
|
406
|
-
if (status === 401) {
|
|
407
|
-
return ErrInvalidSecretKey;
|
|
408
|
-
}
|
|
409
|
-
if (status === 409) {
|
|
410
|
-
return ErrConflict;
|
|
411
|
-
}
|
|
412
|
-
return ErrServerError;
|
|
413
|
-
}
|
|
414
|
-
async function readErrorBody3(res) {
|
|
415
|
-
const parsed = await res.json().then(function ok(data) {
|
|
416
|
-
return { ok: true, data };
|
|
417
|
-
}, function fail() {
|
|
418
|
-
return { ok: false };
|
|
419
|
-
});
|
|
420
|
-
if (!parsed.ok) {
|
|
421
|
-
return {};
|
|
422
|
-
}
|
|
423
|
-
return toStudentsErrorBody(parsed.data);
|
|
424
|
-
}
|
|
425
|
-
async function sendCreateStudentRequest(config) {
|
|
426
|
-
const logger = config.logger;
|
|
427
|
-
const fetchFn = config.fetch ? config.fetch : globalThis.fetch;
|
|
428
|
-
const signal = config.abort ? config.abort.signal : undefined;
|
|
429
|
-
const url = `${config.origin}${STUDENTS_PATH2}`;
|
|
430
|
-
const fetchResult = await fetchFn(url, {
|
|
431
|
-
method: "POST",
|
|
432
|
-
headers: {
|
|
433
|
-
Authorization: `Bearer ${config.secretKey}`
|
|
434
|
-
},
|
|
435
|
-
signal
|
|
436
|
-
}).then(function ok(response) {
|
|
437
|
-
return { ok: true, response };
|
|
438
|
-
}, function fail(err) {
|
|
439
|
-
return { ok: false, error: err };
|
|
440
|
-
});
|
|
441
|
-
if (!fetchResult.ok) {
|
|
442
|
-
if (isAbortError3(fetchResult.error)) {
|
|
443
|
-
logger.error("students timeout", { path: STUDENTS_PATH2 });
|
|
444
|
-
throw errors4.wrap(ErrTimeout, fetchResult.error.message);
|
|
445
|
-
}
|
|
446
|
-
logger.error("students network error", {
|
|
447
|
-
path: STUDENTS_PATH2,
|
|
448
|
-
error: fetchResult.error
|
|
449
|
-
});
|
|
450
|
-
throw errors4.wrap(ErrNetwork, fetchResult.error.message);
|
|
451
|
-
}
|
|
452
|
-
return fetchResult.response;
|
|
453
|
-
}
|
|
454
|
-
async function parseStudentIdSuccess(config, res) {
|
|
455
|
-
const logger = config.logger;
|
|
456
|
-
const jsonResult = await res.json().then(function ok(data) {
|
|
457
|
-
return { ok: true, data };
|
|
458
|
-
}, function fail(err) {
|
|
459
|
-
return { ok: false, error: err };
|
|
460
|
-
});
|
|
461
|
-
if (!jsonResult.ok) {
|
|
462
|
-
logger.error("student id response parse failed", {
|
|
463
|
-
operation: "create student",
|
|
464
|
-
error: jsonResult.error
|
|
465
|
-
});
|
|
466
|
-
throw errors4.wrap(ErrJsonParse, jsonResult.error.message);
|
|
467
|
-
}
|
|
468
|
-
const body = parseStudentIdSuccessBody(jsonResult.data);
|
|
469
|
-
if (!body) {
|
|
470
|
-
logger.error("student id response had invalid shape", {
|
|
471
|
-
operation: "create student",
|
|
472
|
-
body: jsonResult.data
|
|
473
|
-
});
|
|
474
|
-
throw errors4.wrap(ErrJsonParse, "create student success body had invalid shape");
|
|
475
|
-
}
|
|
476
|
-
logger.debug("student id response success", {
|
|
477
|
-
operation: "create student",
|
|
478
|
-
studentId: body.student_id
|
|
479
|
-
});
|
|
480
|
-
return body.student_id;
|
|
481
|
-
}
|
|
482
|
-
async function createStudent(config) {
|
|
483
|
-
const logger = config.logger;
|
|
484
|
-
logger.debug("create student request");
|
|
485
|
-
const res = await sendCreateStudentRequest(config);
|
|
486
|
-
if (!res.ok) {
|
|
487
|
-
const body = await readErrorBody3(res);
|
|
488
|
-
const sentinel = httpSentinel3(res.status);
|
|
489
|
-
const detail = body.error ? `${res.status} ${body.error}` : `${res.status}`;
|
|
490
|
-
logger.error("create student http error", { status: res.status, body });
|
|
491
|
-
throw errors4.wrap(sentinel, detail);
|
|
492
|
-
}
|
|
493
|
-
return parseStudentIdSuccess(config, res);
|
|
127
|
+
return parseToken(config, res);
|
|
494
128
|
}
|
|
495
129
|
|
|
496
130
|
// src/server/create-server.ts
|
|
497
131
|
function createPrimerServer(config) {
|
|
498
132
|
return {
|
|
499
|
-
|
|
500
|
-
return
|
|
501
|
-
},
|
|
502
|
-
setStudentHints(studentId, hints) {
|
|
503
|
-
return setStudentHints(config, studentId, hints);
|
|
504
|
-
},
|
|
505
|
-
exchangeStudentForAccessToken(studentId) {
|
|
506
|
-
return exchangeStudent(config, studentId);
|
|
507
|
-
},
|
|
508
|
-
exchangeTimebackStudentForAccessToken(sourcedId) {
|
|
509
|
-
return exchangeTimebackStudent(config, sourcedId);
|
|
133
|
+
getToken(input) {
|
|
134
|
+
return getToken(config, input);
|
|
510
135
|
}
|
|
511
136
|
};
|
|
512
137
|
}
|
|
@@ -514,4 +139,4 @@ export {
|
|
|
514
139
|
createPrimerServer
|
|
515
140
|
};
|
|
516
141
|
|
|
517
|
-
//# debugId=
|
|
142
|
+
//# debugId=3E72DF6B026E0F7B64756E2164756E21
|
package/dist/server/index.js.map
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/errors.ts", "../src/
|
|
3
|
+
"sources": ["../src/errors.ts", "../src/server/exchange.ts", "../src/server/create-server.ts"],
|
|
4
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
|
|
6
|
-
"
|
|
7
|
-
"import
|
|
8
|
-
"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",
|
|
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. Pure\n\t * identity — the student has no hints and no placements yet. Call\n\t * `setStudentHints(studentId, { gradeLevel })` before the student's\n\t * first `/advance`. If a session calls `/advance` without hints set,\n\t * the server returns 412 `needs_hints` (surfaced as `ErrNeedsHints`\n\t * in the browser SDK).\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"
|
|
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 ErrMissingRequiredPci = errors.new(\"missing required 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 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 ErrSdkUpgradeRequired = errors.new(\"sdk upgrade required\")\n\nexport {\n\tErrBadRequest,\n\tErrConflict,\n\tErrForbidden,\n\tErrInvalidAccessToken,\n\tErrInvalidSecretKey,\n\tErrInvalidSubmission,\n\tErrJsonParse,\n\tErrMalformedAccessToken,\n\tErrMissingRequiredPci,\n\tErrNetwork,\n\tErrNotFound,\n\tErrNotSerializable,\n\tErrRateLimited,\n\tErrSdkUpgradeRequired,\n\tErrServerError,\n\tErrServiceUnavailable,\n\tErrTimeout,\n\tErrTokenExpired,\n\tErrUnsupportedPci\n}\n",
|
|
6
|
+
"import * as errors from \"@superbuilders/errors\"\nimport {\n\tErrBadRequest,\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 TOKEN_PATH = \"/api/v0/sessions\"\n\ninterface TokenConfig {\n\treadonly origin: string\n\treadonly secretKey: string\n\treadonly fetch?: typeof globalThis.fetch\n\treadonly abort?: AbortController\n\treadonly logger: PrimerLogger\n}\n\ntype GetTokenInput = {\n\treadonly verifiedEmail: string\n}\n\ninterface TokenSuccessBody {\n\taccess_token: string\n\ttoken_type: \"Bearer\"\n}\n\ninterface TokenErrorBody {\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 toTokenErrorBody(data: unknown): TokenErrorBody {\n\tif (!isObjectRecord(data)) {\n\t\treturn {}\n\t}\n\treturn typeof data.error === \"string\" ? { error: data.error } : {}\n}\n\nfunction parseTokenSuccessBody(data: unknown): TokenSuccessBody | undefined {\n\tif (!isObjectRecord(data)) {\n\t\treturn undefined\n\t}\n\tif (typeof data.access_token !== \"string\" || data.token_type !== \"Bearer\") {\n\t\treturn undefined\n\t}\n\treturn {\n\t\taccess_token: data.access_token,\n\t\ttoken_type: \"Bearer\"\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\treturn ErrServerError\n}\n\nasync function readErrorBody(res: Response): Promise<TokenErrorBody> {\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 toTokenErrorBody(parsed.data)\n}\n\nasync function sendTokenRequest(config: TokenConfig, input: GetTokenInput): 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}${TOKEN_PATH}`\n\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({ verified_email: input.verifiedEmail }),\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(\"token request timeout\")\n\t\t\tthrow errors.wrap(ErrTimeout, fetchResult.error.message)\n\t\t}\n\t\tlogger.error(\"token request network error\", { error: fetchResult.error })\n\t\tthrow errors.wrap(ErrNetwork, fetchResult.error.message)\n\t}\n\n\treturn fetchResult.response\n}\n\nasync function parseToken(config: TokenConfig, 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\tif (!jsonResult.ok) {\n\t\tlogger.error(\"token response json parse failed\", { error: jsonResult.error })\n\t\tthrow errors.wrap(ErrJsonParse, jsonResult.error.message)\n\t}\n\n\tconst body = parseTokenSuccessBody(jsonResult.data)\n\tif (body === undefined) {\n\t\tlogger.error(\"token response had invalid shape\", { body: jsonResult.data })\n\t\tthrow errors.wrap(ErrJsonParse, \"token response had invalid shape\")\n\t}\n\n\tlogger.debug(\"token request success\")\n\treturn body.access_token\n}\n\nasync function getToken(config: TokenConfig, input: GetTokenInput): Promise<string> {\n\tconst logger = config.logger\n\tlogger.debug(\"token request\")\n\n\tconst res = await sendTokenRequest(config, input)\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(\"token request http error\", { status: res.status, body })\n\t\tthrow errors.wrap(sentinel, detail)\n\t}\n\n\treturn parseToken(config, res)\n}\n\nexport type { GetTokenInput, TokenConfig }\nexport { getToken }\n",
|
|
7
|
+
"import type { PrimerLogger } from \"@superbuilders/primer-tives/logger\"\nimport { type GetTokenInput, getToken } from \"@superbuilders/primer-tives/server/exchange\"\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\tgetToken(input: GetTokenInput): Promise<string>\n}\n\nfunction createPrimerServer(config: PrimerServerConfig): PrimerServer {\n\treturn {\n\t\tgetToken(input): Promise<string> {\n\t\t\treturn getToken(config, input)\n\t\t}\n\t}\n}\n\nexport type { GetTokenInput, PrimerServer, PrimerServerConfig }\nexport { createPrimerServer }\n"
|
|
11
8
|
],
|
|
12
|
-
"mappings": "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",
|
|
13
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "3E72DF6B026E0F7B64756E2164756E21",
|
|
14
11
|
"names": []
|
|
15
12
|
}
|