@superbuilders/primer-tives 3.6.0 → 3.7.1

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 CHANGED
@@ -17,7 +17,7 @@ bun add @superbuilders/primer-tives
17
17
 
18
18
  ## Version
19
19
 
20
- The current SDK version is `3.6.0`.
20
+ The current SDK version is `3.7.1`.
21
21
 
22
22
  ## Entrypoints
23
23
 
@@ -42,7 +42,6 @@ import * as logger from "@superbuilders/slog"
42
42
  import { start, type PrimerOptions } from "@superbuilders/primer-tives/client"
43
43
 
44
44
  const options = {
45
- origin: "https://primerlearn.dev",
46
45
  publishableKey: "pk_...",
47
46
  subject: "math",
48
47
  supportedPcis: ["urn:primer:pci:fraction-input"],
@@ -56,7 +55,6 @@ If your application already has a learner access token, pass it directly. `start
56
55
 
57
56
  ```ts
58
57
  const options = {
59
- origin: "https://primerlearn.dev",
60
58
  publishableKey: "pk_...",
61
59
  accessToken,
62
60
  subject: "math",
@@ -92,7 +90,6 @@ Vocabulary and science currently have no required PCI capabilities, so `supporte
92
90
 
93
91
  ```ts
94
92
  const options = {
95
- origin: "https://primerlearn.dev",
96
93
  publishableKey: "pk_...",
97
94
  subject: "vocabulary",
98
95
  logger
@@ -105,7 +102,6 @@ Omitting `subject` means the SDK asks Primer for the all-subject runtime scope.
105
102
 
106
103
  ```ts
107
104
  const options = {
108
- origin: "https://primerlearn.dev",
109
105
  publishableKey: "pk_...",
110
106
  supportedPcis: ["urn:primer:pci:fraction-input"],
111
107
  logger
@@ -142,7 +138,6 @@ import { start, type PrimerOptions } from "@superbuilders/primer-tives/client"
142
138
  import { ErrAuthUnavailable, ErrMalformedAccessToken } from "@superbuilders/primer-tives/errors"
143
139
 
144
140
  const options = {
145
- origin,
146
141
  publishableKey,
147
142
  accessToken,
148
143
  subject: "math",
@@ -174,7 +169,6 @@ if (state.phase === "fatal") {
174
169
 
175
170
  ```ts
176
171
  type PrimerOptions<S extends Subject | undefined = undefined, Supported extends readonly PciId[] = []> = {
177
- readonly origin: string
178
172
  readonly publishableKey: string
179
173
  readonly accessToken?: string
180
174
  readonly subject?: S
@@ -187,7 +181,6 @@ type PrimerOptions<S extends Subject | undefined = undefined, Supported extends
187
181
 
188
182
  | Field | Required | Meaning |
189
183
  | --- | --- | --- |
190
- | `origin` | Yes | Primer deployment origin. |
191
184
  | `publishableKey` | Yes | Public key identifying the Primer frontend your runtime belongs to. |
192
185
  | `accessToken` | No | Learner access token. When present, `start` uses it for the learning runtime. |
193
186
  | `subject` | No | Public content scope: `"math"`, `"vocabulary"`, or `"science"`. Omitted means all-subject scope. |
@@ -198,6 +191,8 @@ type PrimerOptions<S extends Subject | undefined = undefined, Supported extends
198
191
 
199
192
  The presence or absence of `accessToken` selects startup auth semantics.
200
193
 
194
+ The SDK uses Primer's production runtime by default.
195
+
201
196
  | Shape | Semantics |
202
197
  | --- | --- |
203
198
  | `accessToken` present | `start` validates the token shape locally and uses it for learning runtime state. |
@@ -288,7 +283,6 @@ This fails at compile time because math can emit a required PCI:
288
283
 
289
284
  ```ts
290
285
  await start({
291
- origin,
292
286
  publishableKey,
293
287
  subject: "math",
294
288
  logger
@@ -299,7 +293,6 @@ This passes:
299
293
 
300
294
  ```ts
301
295
  const options = {
302
- origin,
303
296
  publishableKey,
304
297
  subject: "math",
305
298
  supportedPcis: ["urn:primer:pci:fraction-input"],
@@ -1288,7 +1281,6 @@ import * as logger from "@superbuilders/slog"
1288
1281
  import { start, type PrimerOptions } from "@superbuilders/primer-tives/client"
1289
1282
 
1290
1283
  const options = {
1291
- origin,
1292
1284
  publishableKey,
1293
1285
  subject: "vocabulary",
1294
1286
  logger
@@ -1341,7 +1333,6 @@ import { ErrUnsupportedPci } from "@superbuilders/primer-tives/errors"
1341
1333
  declare const fetchMock: typeof globalThis.fetch
1342
1334
 
1343
1335
  const options = {
1344
- origin: "https://primer.test",
1345
1336
  publishableKey: "pk_test",
1346
1337
  accessToken: "eyJ.test.token",
1347
1338
  subject: "vocabulary",
@@ -1388,7 +1379,7 @@ grade level
1388
1379
  1. Import `start` and `PrimerOptions` from `@superbuilders/primer-tives/client`.
1389
1380
  2. Import shared renderer contracts from `@superbuilders/primer-tives/contracts`.
1390
1381
  3. Define options with `satisfies PrimerOptions<...>` so subject and PCI requirements stay visible at the declaration site.
1391
- 4. Pass `origin`, `publishableKey`, and `logger` to `start`.
1382
+ 4. Pass `publishableKey` and `logger` to `start`.
1392
1383
  5. Either pass `accessToken` or handle `UnauthenticatedState`.
1393
1384
  6. Choose a public `subject`, or omit `subject` for all-subject runtime scope.
1394
1385
  7. Declare every required renderer PCI in `supportedPcis`.
@@ -11,10 +11,7 @@ declare function browserStorage(options: HostedAuthOptions | undefined, logger:
11
11
  declare function currentUrl(options: HostedAuthOptions | undefined, logger: PrimerLogger): URL;
12
12
  declare function redirectUri(options: HostedAuthOptions | undefined, url: URL, logger: PrimerLogger): string;
13
13
  declare function randomClientState(logger: PrimerLogger): string;
14
- declare function clearCallbackHash(options: HostedAuthOptions | undefined, url: URL): void;
15
14
  declare function openAuthPopup(url: string, options: HostedAuthOptions | undefined, logger: PrimerLogger): Window;
16
- declare function readablePopupUrl(popup: Window): string | null;
17
- declare function sleep(ms: number): Promise<void>;
18
- export { browserStorage, clearCallbackHash, currentUrl, openAuthPopup, randomClientState, readablePopupUrl, redirectUri, sleep };
15
+ export { browserStorage, currentUrl, openAuthPopup, randomClientState, redirectUri };
19
16
  export type { HostedAuthOptions };
20
17
  //# sourceMappingURL=browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../src/client/auth/browser.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,KAAK,iBAAiB,GAAG;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAS7F;AAED,iBAAS,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,GAAG,CAarF;AAED,iBAAS,WAAW,CACnB,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,YAAY,GAClB,MAAM,CASR;AAED,iBAAS,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAYvD;AAED,iBAAS,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CASjF;AAED,iBAAS,aAAa,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,MAAM,EAAE,YAAY,GAClB,MAAM,CAmBR;AAED,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQtD;AAED,iBAAS,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxC;AAED,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,KAAK,EACL,CAAA;AACD,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../src/client/auth/browser.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,KAAK,iBAAiB,GAAG;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAS7F;AAED,iBAAS,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,GAAG,CAarF;AAED,iBAAS,WAAW,CACnB,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,YAAY,GAClB,MAAM,CASR;AAED,iBAAS,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAYvD;AAED,iBAAS,aAAa,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,MAAM,EAAE,YAAY,GAClB,MAAM,CAmBR;AAED,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAA;AACpF,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"hosted-popup.d.ts","sourceRoot":"","sources":["../../../src/client/auth/hosted-popup.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAKN,KAAK,iBAAiB,EACtB,MAAM,iDAAiD,CAAA;AAMxD,KAAK,iBAAiB,GAAG;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;IACpC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAC7B,CAAA;AA6CD,iBAAe,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B1E;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAC3B,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
1
+ {"version":3,"file":"hosted-popup.d.ts","sourceRoot":"","sources":["../../../src/client/auth/hosted-popup.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAGN,KAAK,iBAAiB,EACtB,MAAM,iDAAiD,CAAA;AAOxD,KAAK,iBAAiB,GAAG;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;IACpC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAC7B,CAAA;AAwJD,iBAAe,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAU1E;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAC3B,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/client/auth/provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAKN,KAAK,iBAAiB,EACtB,MAAM,iDAAiD,CAAA;AAMxD,OAAO,EAEN,KAAK,mBAAmB,EACxB,MAAM,sDAAsD,CAAA;AAU7D,KAAK,0BAA0B,GAAG;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAC7B,CAAA;AAED,KAAK,yBAAyB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAA;CACzC,CAAA;AAED,KAAK,gCAAgC,GAAG;IACvC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CAC5B,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CACrB,CAAA;AAED,KAAK,yBAAyB,GAC3B,yBAAyB,GACzB,gCAAgC,GAChC,sBAAsB,CAAA;AAEzB,KAAK,iBAAiB,GAAG,yBAAyB,GAAG,gCAAgC,CAAA;AAkGrF,iBAAS,0BAA0B,CAClC,OAAO,EAAE,0BAA0B,GACjC,yBAAyB,CAqB3B;AAED,iBAAe,gBAAgB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqC/F;AAED,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,CAAA;AACvD,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,CAAA"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/client/auth/provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAIN,KAAK,iBAAiB,EACtB,MAAM,iDAAiD,CAAA;AAExD,OAAO,EAEN,KAAK,mBAAmB,EACxB,MAAM,sDAAsD,CAAA;AAS7D,KAAK,0BAA0B,GAAG;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAC7B,CAAA;AAED,KAAK,yBAAyB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAA;CACzC,CAAA;AAED,KAAK,gCAAgC,GAAG;IACvC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CAC5B,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CACrB,CAAA;AAED,KAAK,yBAAyB,GAC3B,yBAAyB,GACzB,gCAAgC,GAChC,sBAAsB,CAAA;AAEzB,KAAK,iBAAiB,GAAG,yBAAyB,GAAG,gCAAgC,CAAA;AA4DrF,iBAAS,0BAA0B,CAClC,OAAO,EAAE,0BAA0B,GACjC,yBAAyB,CAe3B;AAED,iBAAe,gBAAgB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqC/F;AAED,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,CAAA;AACvD,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,CAAA"}
@@ -1,3 +1,41 @@
1
+ var __dispose = Symbol.dispose || /* @__PURE__ */ Symbol.for("Symbol.dispose");
2
+ var __asyncDispose = Symbol.asyncDispose || /* @__PURE__ */ Symbol.for("Symbol.asyncDispose");
3
+ var __using = (stack, value, async) => {
4
+ if (value != null) {
5
+ if (typeof value !== "object" && typeof value !== "function")
6
+ throw TypeError('Object expected to be assigned to "using" declaration');
7
+ var dispose;
8
+ if (async)
9
+ dispose = value[__asyncDispose];
10
+ if (dispose === undefined)
11
+ dispose = value[__dispose];
12
+ if (typeof dispose !== "function")
13
+ throw TypeError("Object not disposable");
14
+ stack.push([async, dispose, value]);
15
+ } else if (async) {
16
+ stack.push([async]);
17
+ }
18
+ return value;
19
+ };
20
+ var __callDispose = (stack, error, hasError) => {
21
+ var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
22
+ return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
23
+ }, fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e), next = (it) => {
24
+ while (it = stack.pop()) {
25
+ try {
26
+ var result = it[1] && it[1].call(it[2]);
27
+ if (it[0])
28
+ return Promise.resolve(result).then(next, (e) => (fail(e), next()));
29
+ } catch (e) {
30
+ fail(e);
31
+ }
32
+ }
33
+ if (hasError)
34
+ throw error;
35
+ };
36
+ return next();
37
+ };
38
+
1
39
  // src/errors.ts
2
40
  import * as errors from "@superbuilders/errors";
3
41
  var ErrNetwork = errors.new("network");
@@ -341,7 +379,7 @@ function submissionValidationMessage(result) {
341
379
  import * as errors2 from "@superbuilders/errors";
342
380
 
343
381
  // src/version.ts
344
- var SDK_VERSION = "3.6.0";
382
+ var SDK_VERSION = "3.7.1";
345
383
  var NPM_PACKAGE_URL = "https://www.npmjs.com/package/@superbuilders/primer-tives";
346
384
 
347
385
  // src/client/transport.ts
@@ -474,6 +512,8 @@ function createTransport(tc) {
474
512
  const url = `${tc.origin}${ADVANCE_PATH}`;
475
513
  const fetchResult = await fetchFn(url, {
476
514
  method: "POST",
515
+ mode: "cors",
516
+ credentials: "omit",
477
517
  headers: {
478
518
  "Content-Type": "application/json",
479
519
  Authorization: `Bearer ${tc.accessToken.value}`,
@@ -1134,10 +1174,9 @@ function makeSession(sc) {
1134
1174
  }
1135
1175
 
1136
1176
  // src/client/auth/provider.ts
1137
- import * as errors13 from "@superbuilders/errors";
1177
+ import * as errors11 from "@superbuilders/errors";
1138
1178
 
1139
1179
  // src/client/auth/browser.ts
1140
- import * as errors10 from "@superbuilders/errors";
1141
1180
  function browserStorage(options, logger) {
1142
1181
  if (options !== undefined && options.storage !== undefined) {
1143
1182
  return options.storage;
@@ -1185,16 +1224,6 @@ function randomClientState(logger) {
1185
1224
  }
1186
1225
  return result;
1187
1226
  }
1188
- function clearCallbackHash(options, url) {
1189
- if (options !== undefined && options.currentUrl !== undefined) {
1190
- return;
1191
- }
1192
- if (typeof globalThis.history === "undefined") {
1193
- return;
1194
- }
1195
- const cleanUrl = `${url.pathname}${url.search}`;
1196
- globalThis.history.replaceState(globalThis.history.state, "", cleanUrl);
1197
- }
1198
1227
  function openAuthPopup(url, options, logger) {
1199
1228
  if (typeof globalThis.open === "undefined") {
1200
1229
  logger.error("auth popup api unavailable");
@@ -1215,67 +1244,12 @@ function openAuthPopup(url, options, logger) {
1215
1244
  }
1216
1245
  return popup;
1217
1246
  }
1218
- function readablePopupUrl(popup) {
1219
- const result = errors10.trySync(function readLocation() {
1220
- return popup.location.href;
1221
- });
1222
- if (result.error) {
1223
- return null;
1224
- }
1225
- return result.data;
1226
- }
1227
- function sleep(ms) {
1228
- return new Promise(function resolveLater(resolve) {
1229
- setTimeout(resolve, ms);
1230
- });
1231
- }
1232
-
1233
- // src/client/auth/callback.ts
1234
- var ACCESS_TOKEN_HASH_PARAM = "primer_access_token";
1235
- var AUTH_STATUS_HASH_PARAM = "primer_auth";
1236
- var AUTH_STATE_HASH_PARAM = "primer_state";
1237
- var AUTH_SUCCESS = "success";
1238
- var AUTH_ERROR = "error";
1239
- function readAuthCallback(url, logger) {
1240
- if (url.hash.length === 0) {
1241
- return null;
1242
- }
1243
- const hash = new URLSearchParams(url.hash.slice(1));
1244
- const authStatus = hash.get(AUTH_STATUS_HASH_PARAM);
1245
- if (authStatus === null) {
1246
- return null;
1247
- }
1248
- if (authStatus === AUTH_ERROR) {
1249
- logger.error("auth callback returned error");
1250
- throw ErrAuthCallbackInvalid;
1251
- }
1252
- if (authStatus !== AUTH_SUCCESS) {
1253
- logger.error("auth callback status invalid", { authStatus });
1254
- throw ErrAuthCallbackInvalid;
1255
- }
1256
- const accessToken = hash.get(ACCESS_TOKEN_HASH_PARAM);
1257
- const state = hash.get(AUTH_STATE_HASH_PARAM);
1258
- if (accessToken === null || accessToken.length === 0 || state === null || state.length === 0) {
1259
- logger.error("auth callback missing token or state");
1260
- throw ErrAuthCallbackInvalid;
1261
- }
1262
- return { accessToken, state };
1263
- }
1264
- function requireMatchingCallbackState(callback, expectedState, logger) {
1265
- if (expectedState === null) {
1266
- logger.error("auth callback expected state missing");
1267
- throw ErrAuthCallbackInvalid;
1268
- }
1269
- if (callback.state !== expectedState) {
1270
- logger.error("auth callback state mismatch");
1271
- throw ErrAuthStateMismatch;
1272
- }
1273
- }
1274
1247
 
1275
1248
  // src/client/auth/hosted-popup.ts
1276
- import * as errors11 from "@superbuilders/errors";
1277
1249
  var DEFAULT_POPUP_TIMEOUT_MS = 10 * 60 * 1000;
1278
1250
  var POPUP_POLL_MS = 250;
1251
+ var AUTH_MESSAGE_TYPE = "primer-tives.auth.result.v1";
1252
+ var AUTH_RESPONSE_MODE = "web_message";
1279
1253
  function hostedAuthUrl(config) {
1280
1254
  const logger = config.logger;
1281
1255
  if (!URL.canParse(config.origin)) {
@@ -1286,6 +1260,7 @@ function hostedAuthUrl(config) {
1286
1260
  authUrl.searchParams.set("publishableKey", config.publishableKey);
1287
1261
  authUrl.searchParams.set("redirectUri", redirectUri(config.options, config.currentUrl, logger));
1288
1262
  authUrl.searchParams.set("state", config.clientState);
1263
+ authUrl.searchParams.set("responseMode", AUTH_RESPONSE_MODE);
1289
1264
  return authUrl.toString();
1290
1265
  }
1291
1266
  function popupTimeoutMs(options) {
@@ -1294,62 +1269,132 @@ function popupTimeoutMs(options) {
1294
1269
  }
1295
1270
  return DEFAULT_POPUP_TIMEOUT_MS;
1296
1271
  }
1297
- function readPopupCallback(href, config) {
1298
- const logger = config.logger;
1299
- if (!URL.canParse(href)) {
1272
+ function isRecord(value) {
1273
+ return typeof value === "object" && value !== null;
1274
+ }
1275
+ function stringField(value, key) {
1276
+ const field = value[key];
1277
+ if (typeof field !== "string" || field.length === 0) {
1300
1278
  return null;
1301
1279
  }
1302
- const callbackResult = errors11.trySync(function readCallback() {
1303
- return readAuthCallback(new URL(href), logger);
1304
- });
1305
- if (callbackResult.error) {
1306
- logger.error("hosted auth popup callback invalid", { error: callbackResult.error });
1307
- throw callbackResult.error;
1280
+ return field;
1281
+ }
1282
+ function readPopupMessage(event, popup, config, expectedOrigin) {
1283
+ if (event.source !== popup) {
1284
+ return { kind: "ignore" };
1308
1285
  }
1309
- const callback = callbackResult.data;
1310
- if (callback === null) {
1311
- return null;
1286
+ if (event.origin !== expectedOrigin) {
1287
+ return { kind: "ignore" };
1288
+ }
1289
+ const data = event.data;
1290
+ if (!isRecord(data)) {
1291
+ return { kind: "ignore" };
1292
+ }
1293
+ const messageType = stringField(data, "type");
1294
+ if (messageType !== AUTH_MESSAGE_TYPE) {
1295
+ return { kind: "ignore" };
1296
+ }
1297
+ const state = stringField(data, "state");
1298
+ if (state === null) {
1299
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1300
+ }
1301
+ if (state !== config.clientState) {
1302
+ return { kind: "error", error: ErrAuthStateMismatch };
1303
+ }
1304
+ const status = stringField(data, "status");
1305
+ if (status === "error") {
1306
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1307
+ }
1308
+ if (status !== "success") {
1309
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1312
1310
  }
1313
- if (callback.state !== config.clientState) {
1314
- logger.error("hosted auth popup state mismatch");
1315
- throw ErrAuthStateMismatch;
1311
+ const accessToken = stringField(data, "accessToken");
1312
+ if (accessToken === null) {
1313
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1316
1314
  }
1317
- return callback.accessToken;
1315
+ return { kind: "success", accessToken };
1318
1316
  }
1319
- async function beginHostedPopup(config) {
1320
- const logger = config.logger;
1321
- const popup = openAuthPopup(hostedAuthUrl(config), config.options, logger);
1322
- const expiresAt = Date.now() + popupTimeoutMs(config.options);
1323
- while (Date.now() < expiresAt) {
1324
- if (popup.closed) {
1325
- logger.error("hosted auth popup closed");
1326
- throw ErrAuthCancelled;
1327
- }
1328
- const href = readablePopupUrl(popup);
1329
- if (href !== null) {
1330
- const accessTokenResult = errors11.trySync(function readAccessToken() {
1331
- return readPopupCallback(href, config);
1332
- });
1333
- if (accessTokenResult.error) {
1334
- popup.close();
1335
- logger.error("hosted auth popup failed", { error: accessTokenResult.error });
1336
- throw accessTokenResult.error;
1317
+ async function waitForPopupMessage(popup, config, expectedOrigin) {
1318
+ let __stack = [];
1319
+ try {
1320
+ const logger = config.logger;
1321
+ const stack = __using(__stack, new AsyncDisposableStack, 1);
1322
+ stack.defer(function closePopup() {
1323
+ popup.close();
1324
+ });
1325
+ const result = await new Promise(function waitForMessage(resolve, reject) {
1326
+ let settled = false;
1327
+ function finishWithError(error) {
1328
+ if (settled) {
1329
+ return;
1330
+ }
1331
+ settled = true;
1332
+ reject(error);
1337
1333
  }
1338
- if (accessTokenResult.data !== null) {
1339
- popup.close();
1334
+ function finishWithToken(token) {
1335
+ if (settled) {
1336
+ return;
1337
+ }
1338
+ settled = true;
1340
1339
  logger.debug("hosted auth popup completed");
1341
- return accessTokenResult.data;
1340
+ resolve(token);
1342
1341
  }
1343
- }
1344
- await sleep(POPUP_POLL_MS);
1342
+ const timeoutId = globalThis.setTimeout(function timeout() {
1343
+ logger.error("hosted auth popup timed out");
1344
+ finishWithError(ErrAuthCancelled);
1345
+ }, popupTimeoutMs(config.options));
1346
+ stack.defer(function clearPopupTimeout() {
1347
+ globalThis.clearTimeout(timeoutId);
1348
+ });
1349
+ const closedPollId = globalThis.setInterval(function checkClosed() {
1350
+ if (!popup.closed) {
1351
+ return;
1352
+ }
1353
+ logger.error("hosted auth popup closed");
1354
+ finishWithError(ErrAuthCancelled);
1355
+ }, POPUP_POLL_MS);
1356
+ stack.defer(function clearClosedPoll() {
1357
+ globalThis.clearInterval(closedPollId);
1358
+ });
1359
+ function handleMessage(event) {
1360
+ const result2 = readPopupMessage(event, popup, config, expectedOrigin);
1361
+ if (result2.kind === "ignore") {
1362
+ return;
1363
+ }
1364
+ if (result2.kind === "error") {
1365
+ logger.error("hosted auth popup failed", { error: result2.error });
1366
+ finishWithError(result2.error);
1367
+ return;
1368
+ }
1369
+ finishWithToken(result2.accessToken);
1370
+ }
1371
+ globalThis.addEventListener("message", handleMessage);
1372
+ stack.defer(function removeMessageListener() {
1373
+ globalThis.removeEventListener("message", handleMessage);
1374
+ });
1375
+ });
1376
+ return result;
1377
+ } catch (_catch) {
1378
+ var _err = _catch, _hasErr = 1;
1379
+ } finally {
1380
+ var _promise = __callDispose(__stack, _err, _hasErr);
1381
+ _promise && await _promise;
1382
+ }
1383
+ }
1384
+ async function beginHostedPopup(config) {
1385
+ const logger = config.logger;
1386
+ const url = hostedAuthUrl(config);
1387
+ if (!URL.canParse(config.origin)) {
1388
+ logger.error("hosted auth origin invalid", { origin: config.origin });
1389
+ throw ErrAuthCallbackInvalid;
1345
1390
  }
1346
- popup.close();
1347
- logger.error("hosted auth popup timed out");
1348
- throw ErrAuthCancelled;
1391
+ const expectedOrigin = new URL(config.origin).origin;
1392
+ const popup = openAuthPopup(url, config.options, logger);
1393
+ return waitForPopupMessage(popup, config, expectedOrigin);
1349
1394
  }
1350
1395
 
1351
1396
  // src/client/auth/access-token.ts
1352
- import * as errors12 from "@superbuilders/errors";
1397
+ import * as errors10 from "@superbuilders/errors";
1353
1398
  var ACCESS_TOKEN_PREFIX = "eyJ";
1354
1399
  var resolvedAccessTokenBrand = Symbol("primer resolved access token");
1355
1400
  function isMalformedJws(token) {
@@ -1362,7 +1407,7 @@ function isMalformedJws(token) {
1362
1407
  function resolveAccessToken(token, logger) {
1363
1408
  if (isMalformedJws(token)) {
1364
1409
  logger.error("malformed access token", { prefix: ACCESS_TOKEN_PREFIX });
1365
- throw errors12.wrap(ErrMalformedAccessToken, `token must start with '${ACCESS_TOKEN_PREFIX}' and contain two dots`);
1410
+ throw errors10.wrap(ErrMalformedAccessToken, `token must start with '${ACCESS_TOKEN_PREFIX}' and contain two dots`);
1366
1411
  }
1367
1412
  return { value: token, [resolvedAccessTokenBrand]: true };
1368
1413
  }
@@ -1389,13 +1434,6 @@ function storeAccessToken(storage, publishableKey, accessToken) {
1389
1434
  function clearStoredAccessToken(storage, publishableKey) {
1390
1435
  storage.removeItem(accessTokenStorageKey(publishableKey));
1391
1436
  }
1392
- function loadAuthState(storage, publishableKey) {
1393
- const state = storage.getItem(authStateStorageKey(publishableKey));
1394
- if (state === null || state.length === 0) {
1395
- return null;
1396
- }
1397
- return state;
1398
- }
1399
1437
  function storeAuthState(storage, publishableKey, state) {
1400
1438
  storage.setItem(authStateStorageKey(publishableKey), state);
1401
1439
  }
@@ -1405,7 +1443,7 @@ function clearAuthState(storage, publishableKey) {
1405
1443
 
1406
1444
  // src/client/auth/provider.ts
1407
1445
  function resolveProvidedAccessToken(token, logger) {
1408
- const result = errors13.trySync(function resolveProvidedToken() {
1446
+ const result = errors11.trySync(function resolveProvidedToken() {
1409
1447
  return resolveAccessToken(token, logger);
1410
1448
  });
1411
1449
  if (result.error) {
@@ -1414,7 +1452,7 @@ function resolveProvidedAccessToken(token, logger) {
1414
1452
  return { kind: "resolved", accessToken: result.data };
1415
1453
  }
1416
1454
  function resolveManagedAccessToken(token, logger) {
1417
- const result = errors13.trySync(function resolveManagedToken() {
1455
+ const result = errors11.trySync(function resolveManagedToken() {
1418
1456
  return resolveAccessToken(token, logger);
1419
1457
  });
1420
1458
  if (result.error) {
@@ -1424,7 +1462,7 @@ function resolveManagedAccessToken(token, logger) {
1424
1462
  }
1425
1463
  function readBrowserAuthContext(options) {
1426
1464
  const logger = options.logger;
1427
- const contextResult = errors13.trySync(function readContext() {
1465
+ const contextResult = errors11.trySync(function readContext() {
1428
1466
  const storage = browserStorage(options.hostedAuth, logger);
1429
1467
  const url = currentUrl(options.hostedAuth, logger);
1430
1468
  return { storage, url };
@@ -1434,36 +1472,6 @@ function readBrowserAuthContext(options) {
1434
1472
  }
1435
1473
  return contextResult.data;
1436
1474
  }
1437
- function resolveCallbackAccessToken(context, options) {
1438
- const logger = options.logger;
1439
- const callbackResult = errors13.trySync(function readCallback() {
1440
- return readAuthCallback(context.url, logger);
1441
- });
1442
- if (callbackResult.error) {
1443
- clearAuthState(context.storage, options.publishableKey);
1444
- return { kind: "unauthenticated", error: callbackResult.error };
1445
- }
1446
- const callback = callbackResult.data;
1447
- if (callback === null) {
1448
- return null;
1449
- }
1450
- const stateResult = errors13.trySync(function requireState() {
1451
- requireMatchingCallbackState(callback, loadAuthState(context.storage, options.publishableKey), logger);
1452
- });
1453
- if (stateResult.error) {
1454
- clearAuthState(context.storage, options.publishableKey);
1455
- return { kind: "unauthenticated", error: stateResult.error };
1456
- }
1457
- const resolved = resolveManagedAccessToken(callback.accessToken, logger);
1458
- if (resolved.kind === "unauthenticated") {
1459
- clearAuthState(context.storage, options.publishableKey);
1460
- return resolved;
1461
- }
1462
- storeAccessToken(context.storage, options.publishableKey, callback.accessToken);
1463
- clearAuthState(context.storage, options.publishableKey);
1464
- clearCallbackHash(options.hostedAuth, context.url);
1465
- return resolved;
1466
- }
1467
1475
  function resolveStoredAccessToken(context, options) {
1468
1476
  const stored = loadStoredAccessToken(context.storage, options.publishableKey);
1469
1477
  if (stored === null) {
@@ -1483,10 +1491,6 @@ function resolveExistingAccessToken(options) {
1483
1491
  if ("kind" in context) {
1484
1492
  return context;
1485
1493
  }
1486
- const callback = resolveCallbackAccessToken(context, options);
1487
- if (callback !== null) {
1488
- return callback;
1489
- }
1490
1494
  const stored = resolveStoredAccessToken(context, options);
1491
1495
  if (stored !== null) {
1492
1496
  return stored;
@@ -1499,7 +1503,7 @@ async function beginHostedLogin(options) {
1499
1503
  if ("kind" in context) {
1500
1504
  return context;
1501
1505
  }
1502
- const clientStateResult = errors13.trySync(function prepareHostedLogin() {
1506
+ const clientStateResult = errors11.trySync(function prepareHostedLogin() {
1503
1507
  const clientState2 = randomClientState(logger);
1504
1508
  storeAuthState(context.storage, options.publishableKey, clientState2);
1505
1509
  return clientState2;
@@ -1508,7 +1512,7 @@ async function beginHostedLogin(options) {
1508
1512
  return { kind: "unauthenticated", error: clientStateResult.error };
1509
1513
  }
1510
1514
  const clientState = clientStateResult.data;
1511
- const accessTokenResult = await errors13.try(beginHostedPopup({
1515
+ const accessTokenResult = await errors11.try(beginHostedPopup({
1512
1516
  origin: options.origin,
1513
1517
  publishableKey: options.publishableKey,
1514
1518
  currentUrl: context.url,
@@ -1551,6 +1555,7 @@ function unauthenticatedState(config) {
1551
1555
  }
1552
1556
 
1553
1557
  // src/client/start.ts
1558
+ var DEFAULT_PRIMER_ORIGIN = "https://primerlearn.dev";
1554
1559
  function supportedPcisOrEmpty(supportedPcis) {
1555
1560
  if (supportedPcis !== undefined) {
1556
1561
  return supportedPcis;
@@ -1563,6 +1568,12 @@ function runtimeSubject(subject) {
1563
1568
  }
1564
1569
  return subject;
1565
1570
  }
1571
+ function primerOrigin(origin) {
1572
+ if (origin !== undefined) {
1573
+ return origin;
1574
+ }
1575
+ return DEFAULT_PRIMER_ORIGIN;
1576
+ }
1566
1577
  async function startRuntime(config, accessToken) {
1567
1578
  const transport = createTransport({
1568
1579
  accessToken,
@@ -1603,9 +1614,10 @@ async function loginAndStart(config) {
1603
1614
  async function start(options) {
1604
1615
  const logger = options.logger;
1605
1616
  logger.debug("start");
1617
+ const origin = primerOrigin(options.origin);
1606
1618
  const config = {
1607
1619
  publishableKey: options.publishableKey,
1608
- origin: options.origin,
1620
+ origin,
1609
1621
  fetch: options.fetch,
1610
1622
  abort: options.abort,
1611
1623
  logger,
@@ -1615,7 +1627,7 @@ async function start(options) {
1615
1627
  const accessToken = resolveExistingAccessToken({
1616
1628
  accessToken: options.accessToken,
1617
1629
  publishableKey: options.publishableKey,
1618
- origin: options.origin,
1630
+ origin,
1619
1631
  logger
1620
1632
  });
1621
1633
  if (accessToken.kind === "fatal") {
@@ -1635,4 +1647,4 @@ export {
1635
1647
  start
1636
1648
  };
1637
1649
 
1638
- //# debugId=94171F205AFFEEE264756E2164756E21
1650
+ //# debugId=F2A9711D50B754AA64756E2164756E21