@pie-players/pie-section-player 0.3.71 → 0.3.73
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 +30 -0
- package/dist/chunks/pie-api-client-22de9d9c.js +111 -104
- package/dist/controllers/SectionController.d.ts +8 -0
- package/dist/pie-section-player.js +15451 -14741
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -908,6 +908,36 @@ await controller?.updateItemSession?.("q1", {
|
|
|
908
908
|
The same controller snapshot is what the persistence strategy saves/loads.
|
|
909
909
|
When a controller is reused for the same `sectionId`/`attemptId`, `updateInput()` refreshes composition input while preserving in-memory section session data.
|
|
910
910
|
|
|
911
|
+
### Commit at a section boundary
|
|
912
|
+
|
|
913
|
+
A delivery element coalesces its `session-changed` dispatch, so a response the
|
|
914
|
+
learner has finished entering can still be pending when the section moves. The
|
|
915
|
+
controller commits pending element sessions before item navigation, before
|
|
916
|
+
`updateInput()` snapshots the session for a section swap, and before `persist()`.
|
|
917
|
+
The player also commits when an item shell tears down and when the page goes
|
|
918
|
+
hidden.
|
|
919
|
+
|
|
920
|
+
The commit reaches the controller, and the controller's own
|
|
921
|
+
`PIE_ITEM_SESSION_CHANGED_EVENT` is what reaches a host. A raw `session-changed`
|
|
922
|
+
does not leave a section: `<pie-item-shell>` stops it and re-dispatches the
|
|
923
|
+
normalized event, so a host listening on `document` for `session-changed`
|
|
924
|
+
receives nothing from inside a section player, before this change or after it.
|
|
925
|
+
Host code persists from the controller's events or from its session snapshot.
|
|
926
|
+
|
|
927
|
+
Navigation inside a section keeps every item mounted, so nothing is discarded
|
|
928
|
+
and the element's own debounce would complete on its own. The commit still runs
|
|
929
|
+
there because the response belongs to the item being left: a host that persists
|
|
930
|
+
on the navigation event, or a `persist()` that follows it, would otherwise
|
|
931
|
+
snapshot a session the learner had already changed.
|
|
932
|
+
|
|
933
|
+
`SectionController` stays DOM-free; the player supplies the commit through
|
|
934
|
+
`setPendingSessionCommit()`, declared on `SectionControllerHandle`. The player
|
|
935
|
+
registers it both on the controllers it creates and on one the toolkit has
|
|
936
|
+
already built, since the first section's controller usually exists before the
|
|
937
|
+
player can override the factory. A host-built controller that leaves the method
|
|
938
|
+
unimplemented keeps the behaviour it had before the hook existed, and loses a
|
|
939
|
+
pending response at those boundaries.
|
|
940
|
+
|
|
911
941
|
## Content trust boundary
|
|
912
942
|
|
|
913
943
|
Section-player layouts embed `<pie-item-player>` elements for each item.
|
|
@@ -28,134 +28,141 @@ var i = {
|
|
|
28
28
|
path: "/api/authoring/release"
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
|
-
function
|
|
32
|
-
return
|
|
31
|
+
function S(n) {
|
|
32
|
+
return n ? n.endsWith("/") ? n.slice(0, -1) : n : "";
|
|
33
33
|
}
|
|
34
|
-
function r(
|
|
35
|
-
return
|
|
34
|
+
function r(n, o) {
|
|
35
|
+
return n ? typeof n == "string" ? {
|
|
36
36
|
method: o.method,
|
|
37
|
-
path:
|
|
37
|
+
path: n
|
|
38
38
|
} : {
|
|
39
|
-
method:
|
|
40
|
-
path:
|
|
39
|
+
method: n.method ?? o.method,
|
|
40
|
+
path: n.path
|
|
41
41
|
} : o;
|
|
42
42
|
}
|
|
43
|
-
function d(
|
|
44
|
-
|
|
43
|
+
function d(n, o) {
|
|
44
|
+
if (/^https?:\/\//i.test(o)) return o;
|
|
45
|
+
const e = S(n), t = o.startsWith("/") ? o : `/${o}`;
|
|
46
|
+
return e.endsWith("/api") && t.startsWith("/api/") ? `${e}${t.slice(4)}` : `${e}${t}`;
|
|
45
47
|
}
|
|
46
|
-
async function l(
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
49
|
-
if (typeof
|
|
50
|
-
const
|
|
51
|
-
return
|
|
48
|
+
async function l(n, o) {
|
|
49
|
+
const e = n ?? o;
|
|
50
|
+
if (!e) return null;
|
|
51
|
+
if (typeof e.getToken == "function") {
|
|
52
|
+
const t = await e.getToken();
|
|
53
|
+
return t ? String(t) : null;
|
|
52
54
|
}
|
|
53
|
-
return
|
|
55
|
+
return e.token ? String(e.token) : null;
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
var w = 65536;
|
|
58
|
+
function P(n) {
|
|
59
|
+
return (typeof TextEncoder < "u" ? new TextEncoder().encode(n).length : n.length) > w;
|
|
60
|
+
}
|
|
61
|
+
async function c(n, o, e, t, s, a) {
|
|
62
|
+
const p = JSON.stringify(e ?? {}), g = a?.keepalive === !0 && !P(p), h = typeof AbortController < "u" ? new AbortController() : null, I = !g && typeof t?.timeoutMs == "number" && t.timeoutMs > 0 ? t.timeoutMs : 0, m = h && I > 0 ? setTimeout(() => h.abort(), I) : null;
|
|
57
63
|
try {
|
|
58
|
-
const
|
|
64
|
+
const f = {
|
|
59
65
|
"content-type": "application/json",
|
|
60
|
-
...
|
|
66
|
+
...t?.headers || {}
|
|
61
67
|
};
|
|
62
|
-
|
|
63
|
-
const
|
|
68
|
+
s && (f.authorization = `Bearer ${s}`);
|
|
69
|
+
const v = await fetch(n, {
|
|
64
70
|
method: o,
|
|
65
|
-
headers:
|
|
66
|
-
body:
|
|
67
|
-
signal:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
headers: f,
|
|
72
|
+
body: p,
|
|
73
|
+
signal: m ? h?.signal : void 0,
|
|
74
|
+
keepalive: g
|
|
75
|
+
}), u = await v.json().catch(() => null);
|
|
76
|
+
if (!v.ok) {
|
|
77
|
+
const y = (u && typeof u == "object" && "error" in u ? String(u.error) : "") || `Backend request failed with status ${v.status}`;
|
|
78
|
+
throw new Error(y);
|
|
72
79
|
}
|
|
73
80
|
return u;
|
|
74
81
|
} finally {
|
|
75
82
|
m && clearTimeout(m);
|
|
76
83
|
}
|
|
77
84
|
}
|
|
78
|
-
async function
|
|
79
|
-
const
|
|
80
|
-
return c(d(
|
|
81
|
-
itemId:
|
|
82
|
-
sessionId:
|
|
83
|
-
assignmentId:
|
|
84
|
-
env:
|
|
85
|
-
overrides:
|
|
86
|
-
},
|
|
85
|
+
async function b(n, o, e) {
|
|
86
|
+
const t = r(n.endpoints?.load, i.load), s = await l(n.auth, o);
|
|
87
|
+
return c(d(n.baseUrl, t.path), t.method, {
|
|
88
|
+
itemId: e.itemId,
|
|
89
|
+
sessionId: e.sessionId,
|
|
90
|
+
assignmentId: e.assignmentId,
|
|
91
|
+
env: e.env,
|
|
92
|
+
overrides: e.requestOptions?.overrides
|
|
93
|
+
}, n.request, s);
|
|
87
94
|
}
|
|
88
|
-
async function
|
|
89
|
-
const
|
|
90
|
-
return c(d(
|
|
91
|
-
sessionId:
|
|
92
|
-
data:
|
|
93
|
-
env:
|
|
94
|
-
itemId:
|
|
95
|
-
assignmentId:
|
|
96
|
-
models:
|
|
97
|
-
passageModels:
|
|
98
|
-
overrides:
|
|
99
|
-
},
|
|
95
|
+
async function T(n, o, e, t) {
|
|
96
|
+
const s = r(n.endpoints?.saveSession, i.saveSession), a = await l(n.auth, o), p = e.session.id || e.sessionId;
|
|
97
|
+
return c(d(n.baseUrl, s.path), s.method, {
|
|
98
|
+
sessionId: p,
|
|
99
|
+
data: e.session.data,
|
|
100
|
+
env: e.env,
|
|
101
|
+
itemId: e.itemId,
|
|
102
|
+
assignmentId: e.assignmentId,
|
|
103
|
+
models: e.models,
|
|
104
|
+
passageModels: e.passageModels,
|
|
105
|
+
overrides: e.requestOptions?.overrides
|
|
106
|
+
}, n.request, a, { keepalive: t?.keepalive === !0 });
|
|
100
107
|
}
|
|
101
|
-
async function
|
|
102
|
-
const
|
|
103
|
-
return c(d(
|
|
104
|
-
sessionId:
|
|
105
|
-
data:
|
|
106
|
-
env:
|
|
107
|
-
itemId:
|
|
108
|
-
assignmentId:
|
|
109
|
-
models:
|
|
110
|
-
passageModels:
|
|
111
|
-
overrides:
|
|
112
|
-
},
|
|
108
|
+
async function A(n, o, e) {
|
|
109
|
+
const t = r(n.endpoints?.model, i.model), s = await l(n.auth, o), a = e.session.id || e.sessionId;
|
|
110
|
+
return c(d(n.baseUrl, t.path), t.method, {
|
|
111
|
+
sessionId: a,
|
|
112
|
+
data: e.session.data,
|
|
113
|
+
env: e.env,
|
|
114
|
+
itemId: e.itemId,
|
|
115
|
+
assignmentId: e.assignmentId,
|
|
116
|
+
models: e.models,
|
|
117
|
+
passageModels: e.passageModels,
|
|
118
|
+
overrides: e.requestOptions?.overrides
|
|
119
|
+
}, n.request, s);
|
|
113
120
|
}
|
|
114
|
-
async function
|
|
115
|
-
const
|
|
116
|
-
return c(d(
|
|
117
|
-
...
|
|
118
|
-
sessionId:
|
|
119
|
-
data:
|
|
120
|
-
env:
|
|
121
|
-
itemId:
|
|
122
|
-
assignmentId:
|
|
123
|
-
overrides:
|
|
124
|
-
},
|
|
121
|
+
async function O(n, o, e) {
|
|
122
|
+
const t = r(n.endpoints?.score, i.score), s = await l(n.auth, o), a = e.session.id || e.sessionId;
|
|
123
|
+
return c(d(n.baseUrl, t.path), t.method, {
|
|
124
|
+
...e.options,
|
|
125
|
+
sessionId: a,
|
|
126
|
+
data: e.session.data,
|
|
127
|
+
env: e.env,
|
|
128
|
+
itemId: e.itemId,
|
|
129
|
+
assignmentId: e.assignmentId,
|
|
130
|
+
overrides: e.requestOptions?.overrides
|
|
131
|
+
}, n.request, s);
|
|
125
132
|
}
|
|
126
|
-
async function
|
|
127
|
-
const
|
|
128
|
-
return c(d(
|
|
129
|
-
contentId:
|
|
130
|
-
collectionId:
|
|
131
|
-
env:
|
|
132
|
-
},
|
|
133
|
+
async function q(n, o, e) {
|
|
134
|
+
const t = r(n.endpoints?.load, i.authoringLoad), s = await l(n.auth, o);
|
|
135
|
+
return c(d(n.baseUrl, t.path), t.method, {
|
|
136
|
+
contentId: e.contentId,
|
|
137
|
+
collectionId: e.collectionId,
|
|
138
|
+
env: e.env
|
|
139
|
+
}, n.request, s);
|
|
133
140
|
}
|
|
134
|
-
async function
|
|
135
|
-
const
|
|
136
|
-
return c(d(
|
|
137
|
-
contentId:
|
|
138
|
-
collectionId:
|
|
139
|
-
config:
|
|
140
|
-
env:
|
|
141
|
-
options:
|
|
142
|
-
},
|
|
141
|
+
async function k(n, o, e) {
|
|
142
|
+
const t = r(n.endpoints?.saveContent, i.authoringSaveContent), s = await l(n.auth, o);
|
|
143
|
+
return c(d(n.baseUrl, t.path), t.method, {
|
|
144
|
+
contentId: e.contentId,
|
|
145
|
+
collectionId: e.collectionId,
|
|
146
|
+
config: e.config,
|
|
147
|
+
env: e.env,
|
|
148
|
+
options: e.options
|
|
149
|
+
}, n.request, s);
|
|
143
150
|
}
|
|
144
|
-
async function
|
|
145
|
-
const
|
|
146
|
-
return c(d(
|
|
147
|
-
contentId:
|
|
148
|
-
collectionId:
|
|
149
|
-
env:
|
|
150
|
-
options:
|
|
151
|
-
},
|
|
151
|
+
async function C(n, o, e) {
|
|
152
|
+
const t = r(n.endpoints?.releaseContent, i.authoringReleaseContent), s = await l(n.auth, o);
|
|
153
|
+
return c(d(n.baseUrl, t.path), t.method, {
|
|
154
|
+
contentId: e.contentId,
|
|
155
|
+
collectionId: e.collectionId,
|
|
156
|
+
env: e.env,
|
|
157
|
+
options: e.options
|
|
158
|
+
}, n.request, s);
|
|
152
159
|
}
|
|
153
160
|
export {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
q as callPieApiAuthoringLoad,
|
|
162
|
+
C as callPieApiAuthoringReleaseContent,
|
|
163
|
+
k as callPieApiAuthoringSaveContent,
|
|
164
|
+
b as callPieApiDeliveryLoad,
|
|
165
|
+
A as callPieApiDeliveryModel,
|
|
166
|
+
T as callPieApiDeliverySave,
|
|
167
|
+
O as callPieApiDeliveryScore
|
|
161
168
|
};
|
|
@@ -9,6 +9,7 @@ export declare class SectionController implements SectionControllerHandle {
|
|
|
9
9
|
private readonly sessionService;
|
|
10
10
|
private readonly itemNavigationService;
|
|
11
11
|
private sessionPersistence;
|
|
12
|
+
private pendingSessionCommit;
|
|
12
13
|
private state;
|
|
13
14
|
private readonly listeners;
|
|
14
15
|
private readonly trackedRenderables;
|
|
@@ -38,6 +39,13 @@ export declare class SectionController implements SectionControllerHandle {
|
|
|
38
39
|
private mediaAttachWatch;
|
|
39
40
|
private emitChange;
|
|
40
41
|
subscribe(listener: SectionControllerChangeListener): () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Register a commit for pending element sessions, run before a boundary this
|
|
44
|
+
* controller owns. The owner of the section's DOM supplies it; a host-built
|
|
45
|
+
* controller that never registers one keeps today's behaviour.
|
|
46
|
+
*/
|
|
47
|
+
setPendingSessionCommit(commit: (() => void) | null): void;
|
|
48
|
+
private commitPendingItemSessions;
|
|
41
49
|
initialize(input?: unknown): Promise<void>;
|
|
42
50
|
updateInput(input?: unknown): Promise<void>;
|
|
43
51
|
configureSessionPersistence(config: SectionSessionPersistenceConfig): void;
|