@superbuilders/primer-tives 1.0.0 → 1.1.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 +66 -7
- package/dist/client/choice-state.d.ts.map +1 -1
- package/dist/client/extended-text-state.d.ts.map +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +337 -179
- package/dist/client/index.js.map +13 -11
- package/dist/client/match-state.d.ts.map +1 -1
- package/dist/client/order-state.d.ts.map +1 -1
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/text-entry-state.d.ts.map +1 -1
- package/dist/client/transport.d.ts +1 -1
- package/dist/client/transport.d.ts.map +1 -1
- package/dist/client/types.d.ts +2 -115
- package/dist/client/types.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +4 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +305 -0
- package/dist/contracts/index.js.map +11 -0
- package/dist/contracts/pci-schemas.d.ts +25 -0
- package/dist/contracts/pci-schemas.d.ts.map +1 -0
- package/dist/contracts/types.d.ts +118 -0
- package/dist/contracts/types.d.ts.map +1 -0
- package/dist/contracts/validation.d.ts +132 -0
- package/dist/contracts/validation.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +10 -0
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -5
- package/dist/server/index.js.map +5 -5
- package/package.json +17 -4
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Dependency note: `@superbuilders/errors` is installed automatically and is used
|
|
|
19
19
|
|
|
20
20
|
| Import | Runs on | Wraps |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| `@superbuilders/primer-tives/server` | your backend | `POST /api/v0/students`, `POST /api/v0/auth/exchange`, `POST /api/v0/auth/exchange/timeback` |
|
|
22
|
+
| `@superbuilders/primer-tives/server` | your backend | `POST /api/v0/students`, `PATCH /api/v0/students/:id/hints`, `POST /api/v0/auth/exchange`, `POST /api/v0/auth/exchange/timeback` |
|
|
23
23
|
| `@superbuilders/primer-tives/client` | the browser | `POST /api/v0/advance` |
|
|
24
24
|
|
|
25
25
|
## Supported student flows
|
|
@@ -32,8 +32,9 @@ Use this when **your system** owns the learner identity.
|
|
|
32
32
|
|
|
33
33
|
1. Call `createStudent()` once to mint a stable Primer `studentId`.
|
|
34
34
|
2. Persist that `studentId` in your own database alongside your user record.
|
|
35
|
-
3.
|
|
36
|
-
4.
|
|
35
|
+
3. **Before the student's first session**, call `setStudentHints(studentId, { gradeLevel })` at least once. Native students are created hint-less, and the first `/advance` call fails without a `gradeLevel` on record.
|
|
36
|
+
4. At each session start, call `exchangeStudentForAccessToken(studentId)`.
|
|
37
|
+
5. Hand the returned `accessToken` to the browser SDK.
|
|
37
38
|
|
|
38
39
|
### 2. Live-authoritative Timeback students
|
|
39
40
|
|
|
@@ -56,6 +57,7 @@ Persisting the returned `studentId` is fine if you want a stable local foreign k
|
|
|
56
57
|
import * as errors from "@superbuilders/errors"
|
|
57
58
|
import {
|
|
58
59
|
createPrimerServer,
|
|
60
|
+
ErrBadRequest,
|
|
59
61
|
ErrConflict,
|
|
60
62
|
ErrInvalidSecretKey,
|
|
61
63
|
ErrStudentNotFound
|
|
@@ -63,7 +65,7 @@ import {
|
|
|
63
65
|
|
|
64
66
|
const primer = createPrimerServer({
|
|
65
67
|
origin: "https://sb-primer.vercel.app",
|
|
66
|
-
secretKey: process.env.
|
|
68
|
+
secretKey: process.env.PRIMER_DEMO_SECRET_KEY!,
|
|
67
69
|
logger: console
|
|
68
70
|
})
|
|
69
71
|
|
|
@@ -81,6 +83,20 @@ if (createResult.error) {
|
|
|
81
83
|
const studentId = createResult.data
|
|
82
84
|
// persist `studentId` alongside your own user record
|
|
83
85
|
|
|
86
|
+
// Required before the first session for native students.
|
|
87
|
+
const hintsResult = await errors.try(
|
|
88
|
+
primer.setStudentHints(studentId, { gradeLevel: "3" })
|
|
89
|
+
)
|
|
90
|
+
if (hintsResult.error) {
|
|
91
|
+
if (errors.is(hintsResult.error, ErrStudentNotFound)) {
|
|
92
|
+
throw new Error("Stored Primer student id no longer exists on this frontend")
|
|
93
|
+
}
|
|
94
|
+
if (errors.is(hintsResult.error, ErrBadRequest)) {
|
|
95
|
+
throw new Error("Invalid hint payload (e.g. unsupported gradeLevel)")
|
|
96
|
+
}
|
|
97
|
+
throw hintsResult.error
|
|
98
|
+
}
|
|
99
|
+
|
|
84
100
|
// Every session start.
|
|
85
101
|
const tokenResult = await errors.try(
|
|
86
102
|
primer.exchangeStudentForAccessToken(studentId)
|
|
@@ -114,7 +130,7 @@ import {
|
|
|
114
130
|
|
|
115
131
|
const primer = createPrimerServer({
|
|
116
132
|
origin: "https://sb-primer.vercel.app",
|
|
117
|
-
secretKey: process.env.
|
|
133
|
+
secretKey: process.env.PRIMER_DEMO_SECRET_KEY!,
|
|
118
134
|
logger: console
|
|
119
135
|
})
|
|
120
136
|
|
|
@@ -201,6 +217,10 @@ import {
|
|
|
201
217
|
type PrimerServerConfig,
|
|
202
218
|
type SessionToken,
|
|
203
219
|
type TimebackSession,
|
|
220
|
+
type PlacementHints,
|
|
221
|
+
type PlacementHintsResult,
|
|
222
|
+
type GradeLevel,
|
|
223
|
+
GRADE_LEVELS,
|
|
204
224
|
type PrimerLogger,
|
|
205
225
|
ErrBadRequest,
|
|
206
226
|
ErrConflict,
|
|
@@ -230,11 +250,12 @@ interface PrimerServerConfig {
|
|
|
230
250
|
function createPrimerServer(config: PrimerServerConfig): PrimerServer
|
|
231
251
|
```
|
|
232
252
|
|
|
233
|
-
Returns a `PrimerServer` with exactly **
|
|
253
|
+
Returns a `PrimerServer` with exactly **four** methods:
|
|
234
254
|
|
|
235
255
|
```ts
|
|
236
256
|
interface PrimerServer {
|
|
237
257
|
createStudent(): Promise<string>
|
|
258
|
+
setStudentHints(studentId: string, hints: PlacementHints): Promise<PlacementHintsResult>
|
|
238
259
|
exchangeStudentForAccessToken(studentId: string): Promise<SessionToken>
|
|
239
260
|
exchangeTimebackStudentForAccessToken(sourcedId: string): Promise<TimebackSession>
|
|
240
261
|
}
|
|
@@ -256,9 +277,26 @@ Notes:
|
|
|
256
277
|
|
|
257
278
|
- Call this when your system is the source of truth for learner identity.
|
|
258
279
|
- Persist the returned `studentId` in your own database.
|
|
280
|
+
- **Before the first session**, call `setStudentHints(studentId, { gradeLevel })`. Native students are created without a `gradeLevel`, and `/advance` requires one.
|
|
259
281
|
- Use that stored `studentId` with `exchangeStudentForAccessToken(studentId)` at each session start.
|
|
260
282
|
- `logger` is required. Pass any object implementing `debug/info/warn/error`; `console` is acceptable for basic integrations.
|
|
261
283
|
|
|
284
|
+
### `setStudentHints(studentId, hints): Promise<PlacementHintsResult>`
|
|
285
|
+
|
|
286
|
+
Partial upsert of a native/manual student's placement-routing hints. Omitted fields are left untouched; the server returns the persisted state after upsert.
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
const { gradeLevel } = await primer.setStudentHints(studentId, {
|
|
290
|
+
gradeLevel: "3"
|
|
291
|
+
})
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
- **Required** for native/manual students before their first session. Without a `gradeLevel` on record, the first `/advance` call fails server-side.
|
|
295
|
+
- `gradeLevel` is the only hint today; future hint kinds (raw context, interests, etc.) will appear as additional optional fields on `PlacementHints`.
|
|
296
|
+
- Safe to call repeatedly — each call is a partial upsert.
|
|
297
|
+
- Not needed for Timeback-linked students: `exchangeTimebackStudentForAccessToken` syncs the grade level from the authority on every call.
|
|
298
|
+
- Throws `ErrStudentNotFound` if `studentId` is unknown; `ErrBadRequest` if the payload fails validation (e.g., unsupported `gradeLevel`).
|
|
299
|
+
|
|
262
300
|
### `exchangeStudentForAccessToken(studentId): Promise<SessionToken>`
|
|
263
301
|
|
|
264
302
|
Mint a short-lived access token for an existing **native/manual** Primer student.
|
|
@@ -320,6 +358,27 @@ interface TimebackSession {
|
|
|
320
358
|
}
|
|
321
359
|
```
|
|
322
360
|
|
|
361
|
+
### `PlacementHints`
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
interface PlacementHints {
|
|
365
|
+
readonly gradeLevel?: GradeLevel
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Partial shape: pass only the fields you want to set. Today the only hint is `gradeLevel` (the learner's current grade). Re-export `GRADE_LEVELS` enumerates the supported values.
|
|
370
|
+
|
|
371
|
+
### `PlacementHintsResult`
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
interface PlacementHintsResult {
|
|
375
|
+
readonly studentId: string
|
|
376
|
+
readonly gradeLevel: GradeLevel | null
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
The persisted state after upsert. `gradeLevel` is `null` only on native students who have never had one set.
|
|
381
|
+
|
|
323
382
|
## Error sentinels (`/server`)
|
|
324
383
|
|
|
325
384
|
All `/server` methods throw sentinel-wrapped `Error`s. Use `errors.try()` and `errors.is()` from `@superbuilders/errors`.
|
|
@@ -351,7 +410,7 @@ import {
|
|
|
351
410
|
|
|
352
411
|
const primer = createPrimerServer({
|
|
353
412
|
origin: "https://sb-primer.vercel.app",
|
|
354
|
-
secretKey: process.env.
|
|
413
|
+
secretKey: process.env.PRIMER_DEMO_SECRET_KEY!,
|
|
355
414
|
logger: console
|
|
356
415
|
})
|
|
357
416
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"choice-state.d.ts","sourceRoot":"","sources":["../../src/client/choice-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"choice-state.d.ts","sourceRoot":"","sources":["../../src/client/choice-state.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AACxF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAA;AACnE,OAAO,KAAK,EACX,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,MAAM,0CAA0C,CAAA;AAGjD,iBAAS,WAAW,CAAC,IAAI,SAAS,KAAK,EACtC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,EACzB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,EACjC,WAAW,EAAE,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,EACnE,OAAO,EAAE,cAAc,EAAE,EACzB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAChB,WAAW,CAAC,IAAI,CAAC,CAqFnB;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extended-text-state.d.ts","sourceRoot":"","sources":["../../src/client/extended-text-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extended-text-state.d.ts","sourceRoot":"","sources":["../../src/client/extended-text-state.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AACxF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAA;AACnE,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAChB,2BAA2B,EAC3B,MAAM,0CAA0C,CAAA;AAGjD,iBAAS,iBAAiB,CAAC,IAAI,SAAS,KAAK,EAC5C,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,EACzB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,EACjC,WAAW,EAAE,OAAO,CAAC,2BAA2B,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,GAC1E,WAAW,CAAC,IAAI,CAAC,CAqKnB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAE/E,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAA;AAC9D,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAEhF,OAAO,EACN,aAAa,EACb,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,MAAM,oCAAoC,CAAA;AAE3C,YAAY,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,YAAY,EACZ,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,SAAS,EACT,aAAa,EACb,uBAAuB,EACvB,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,eAAe,EACf,cAAc,EACd,MAAM,0CAA0C,CAAA;AAEjD,YAAY,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,MAAM,4CAA4C,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAE/E,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAA;AAC9D,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAEhF,OAAO,EACN,aAAa,EACb,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,MAAM,oCAAoC,CAAA;AAE3C,YAAY,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,YAAY,EACZ,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,SAAS,EACT,aAAa,EACb,uBAAuB,EACvB,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,eAAe,EACf,cAAc,EACd,MAAM,0CAA0C,CAAA;AAEjD,YAAY,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,MAAM,4CAA4C,CAAA;AAEnD,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,MAAM,4CAA4C,CAAA;AAEnD,YAAY,EACX,sBAAsB,EACtB,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC1B,KAAK,EACL,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,MAAM,wCAAwC,CAAA"}
|