@superbuilders/primer-tives 3.5.1 → 3.7.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.
Files changed (37) hide show
  1. package/README.md +234 -126
  2. package/dist/client/auth/browser.d.ts +1 -4
  3. package/dist/client/auth/browser.d.ts.map +1 -1
  4. package/dist/client/auth/hosted-popup.d.ts.map +1 -1
  5. package/dist/client/auth/provider.d.ts +18 -3
  6. package/dist/client/auth/provider.d.ts.map +1 -1
  7. package/dist/client/auth/storage.d.ts +2 -1
  8. package/dist/client/auth/storage.d.ts.map +1 -1
  9. package/dist/client/index.d.ts +3 -3
  10. package/dist/client/index.d.ts.map +1 -1
  11. package/dist/client/index.js +323 -165
  12. package/dist/client/index.js.map +10 -10
  13. package/dist/client/session-context.d.ts +1 -1
  14. package/dist/client/session-context.d.ts.map +1 -1
  15. package/dist/client/{create.d.ts → start.d.ts} +7 -5
  16. package/dist/client/start.d.ts.map +1 -0
  17. package/dist/client/start.type-test.d.ts +2 -0
  18. package/dist/client/start.type-test.d.ts.map +1 -0
  19. package/dist/client/types.d.ts +7 -2
  20. package/dist/client/types.d.ts.map +1 -1
  21. package/dist/client/unauthenticated-state.d.ts +10 -0
  22. package/dist/client/unauthenticated-state.d.ts.map +1 -0
  23. package/dist/contracts/index.js +39 -1
  24. package/dist/contracts/index.js.map +2 -2
  25. package/dist/errors.js +39 -1
  26. package/dist/errors.js.map +2 -2
  27. package/dist/grade-level.js +39 -1
  28. package/dist/grade-level.js.map +2 -2
  29. package/dist/subject-pcis.js +39 -1
  30. package/dist/subject-pcis.js.map +2 -2
  31. package/dist/subject.js +39 -1
  32. package/dist/subject.js.map +2 -2
  33. package/dist/version.d.ts +1 -1
  34. package/package.json +1 -1
  35. package/dist/client/create.d.ts.map +0 -1
  36. package/dist/client/create.type-test.d.ts +0 -2
  37. package/dist/client/create.type-test.d.ts.map +0 -1
@@ -8,7 +8,22 @@ type AccessTokenResolverOptions = {
8
8
  readonly hostedAuth?: HostedAuthOptions;
9
9
  readonly logger: PrimerLogger;
10
10
  };
11
- declare function resolveRuntimeAccessToken(options: AccessTokenResolverOptions): Promise<ResolvedAccessToken>;
12
- export { resolveRuntimeAccessToken };
13
- export type { AccessTokenResolverOptions };
11
+ type ResolvedAccessTokenResult = {
12
+ readonly kind: "resolved";
13
+ readonly accessToken: ResolvedAccessToken;
14
+ };
15
+ type UnauthenticatedAccessTokenResult = {
16
+ readonly kind: "unauthenticated";
17
+ readonly error: Error | null;
18
+ };
19
+ type FatalAccessTokenResult = {
20
+ readonly kind: "fatal";
21
+ readonly error: Error;
22
+ };
23
+ type ExistingAccessTokenResult = ResolvedAccessTokenResult | UnauthenticatedAccessTokenResult | FatalAccessTokenResult;
24
+ type HostedLoginResult = ResolvedAccessTokenResult | UnauthenticatedAccessTokenResult;
25
+ declare function resolveExistingAccessToken(options: AccessTokenResolverOptions): ExistingAccessTokenResult;
26
+ declare function beginHostedLogin(options: AccessTokenResolverOptions): Promise<HostedLoginResult>;
27
+ export { beginHostedLogin, resolveExistingAccessToken };
28
+ export type { AccessTokenResolverOptions, ExistingAccessTokenResult, HostedLoginResult };
14
29
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/client/auth/provider.ts"],"names":[],"mappings":"AAAA,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;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;AAqCD,iBAAe,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAK9B;AAED,OAAO,EAAE,yBAAyB,EAAE,CAAA;AACpC,YAAY,EAAE,0BAA0B,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"}
@@ -2,8 +2,9 @@ declare function accessTokenStorageKey(publishableKey: string): string;
2
2
  declare function authStateStorageKey(publishableKey: string): string;
3
3
  declare function loadStoredAccessToken(storage: Storage, publishableKey: string): string | null;
4
4
  declare function storeAccessToken(storage: Storage, publishableKey: string, accessToken: string): void;
5
+ declare function clearStoredAccessToken(storage: Storage, publishableKey: string): void;
5
6
  declare function loadAuthState(storage: Storage, publishableKey: string): string | null;
6
7
  declare function storeAuthState(storage: Storage, publishableKey: string, state: string): void;
7
8
  declare function clearAuthState(storage: Storage, publishableKey: string): void;
8
- export { accessTokenStorageKey, authStateStorageKey, clearAuthState, loadAuthState, loadStoredAccessToken, storeAccessToken, storeAuthState };
9
+ export { accessTokenStorageKey, authStateStorageKey, clearAuthState, clearStoredAccessToken, loadAuthState, loadStoredAccessToken, storeAccessToken, storeAuthState };
9
10
  //# sourceMappingURL=storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/client/auth/storage.ts"],"names":[],"mappings":"AAGA,iBAAS,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,iBAAS,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,iBAAS,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMtF;AAED,iBAAS,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAE7F;AAED,iBAAS,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9E;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAErF;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAEtE;AAED,OAAO,EACN,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,CAAA"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/client/auth/storage.ts"],"names":[],"mappings":"AAGA,iBAAS,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,iBAAS,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,iBAAS,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMtF;AAED,iBAAS,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAE7F;AAED,iBAAS,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAE9E;AAED,iBAAS,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9E;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAErF;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAEtE;AAED,OAAO,EACN,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,CAAA"}
@@ -1,4 +1,4 @@
1
- export { create } from "./create";
2
- export type { PrimerOptions } from "./create";
3
- export type { ChoiceState, CompletedState, ErroredState, ExtendedTextMultipleState, ExtendedTextSingleState, ExtendedTextState, FatalState, FeedbackState, InteractionState, MatchState, NonSerializable, ObservationState, OrderState, PciInteractionState, PciPendingRenderProps, PciRenderProps, PciSubmittedRenderProps, PrimerState, TextEntryState } from "./types";
1
+ export { start } from "./start";
2
+ export type { PrimerOptions } from "./start";
3
+ export type { ChoiceState, CompletedState, ErroredState, ExtendedTextMultipleState, ExtendedTextSingleState, ExtendedTextState, FatalState, FeedbackState, InteractionState, MatchState, NonSerializable, ObservationState, OrderState, PciInteractionState, PciPendingRenderProps, PciRenderProps, PciSubmittedRenderProps, PrimerState, TextEntryState, UnauthenticatedState } from "./types";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -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,aAAa,EAAE,MAAM,2CAA2C,CAAA;AAE9E,YAAY,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EACvB,WAAW,EACX,cAAc,EACd,MAAM,0CAA0C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0CAA0C,CAAA;AAChE,YAAY,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAA;AAE7E,YAAY,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EACvB,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,MAAM,0CAA0C,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.5.1";
382
+ var SDK_VERSION = "3.7.0";
345
383
  var NPM_PACKAGE_URL = "https://www.npmjs.com/package/@superbuilders/primer-tives";
346
384
 
347
385
  // src/client/transport.ts
@@ -1133,8 +1171,10 @@ function makeSession(sc) {
1133
1171
  return { execute };
1134
1172
  }
1135
1173
 
1174
+ // src/client/auth/provider.ts
1175
+ import * as errors11 from "@superbuilders/errors";
1176
+
1136
1177
  // src/client/auth/browser.ts
1137
- import * as errors10 from "@superbuilders/errors";
1138
1178
  function browserStorage(options, logger) {
1139
1179
  if (options !== undefined && options.storage !== undefined) {
1140
1180
  return options.storage;
@@ -1182,16 +1222,6 @@ function randomClientState(logger) {
1182
1222
  }
1183
1223
  return result;
1184
1224
  }
1185
- function clearCallbackHash(options, url) {
1186
- if (options !== undefined && options.currentUrl !== undefined) {
1187
- return;
1188
- }
1189
- if (typeof globalThis.history === "undefined") {
1190
- return;
1191
- }
1192
- const cleanUrl = `${url.pathname}${url.search}`;
1193
- globalThis.history.replaceState(globalThis.history.state, "", cleanUrl);
1194
- }
1195
1225
  function openAuthPopup(url, options, logger) {
1196
1226
  if (typeof globalThis.open === "undefined") {
1197
1227
  logger.error("auth popup api unavailable");
@@ -1212,67 +1242,12 @@ function openAuthPopup(url, options, logger) {
1212
1242
  }
1213
1243
  return popup;
1214
1244
  }
1215
- function readablePopupUrl(popup) {
1216
- const result = errors10.trySync(function readLocation() {
1217
- return popup.location.href;
1218
- });
1219
- if (result.error) {
1220
- return null;
1221
- }
1222
- return result.data;
1223
- }
1224
- function sleep(ms) {
1225
- return new Promise(function resolveLater(resolve) {
1226
- setTimeout(resolve, ms);
1227
- });
1228
- }
1229
-
1230
- // src/client/auth/callback.ts
1231
- var ACCESS_TOKEN_HASH_PARAM = "primer_access_token";
1232
- var AUTH_STATUS_HASH_PARAM = "primer_auth";
1233
- var AUTH_STATE_HASH_PARAM = "primer_state";
1234
- var AUTH_SUCCESS = "success";
1235
- var AUTH_ERROR = "error";
1236
- function readAuthCallback(url, logger) {
1237
- if (url.hash.length === 0) {
1238
- return null;
1239
- }
1240
- const hash = new URLSearchParams(url.hash.slice(1));
1241
- const authStatus = hash.get(AUTH_STATUS_HASH_PARAM);
1242
- if (authStatus === null) {
1243
- return null;
1244
- }
1245
- if (authStatus === AUTH_ERROR) {
1246
- logger.error("auth callback returned error");
1247
- throw ErrAuthCallbackInvalid;
1248
- }
1249
- if (authStatus !== AUTH_SUCCESS) {
1250
- logger.error("auth callback status invalid", { authStatus });
1251
- throw ErrAuthCallbackInvalid;
1252
- }
1253
- const accessToken = hash.get(ACCESS_TOKEN_HASH_PARAM);
1254
- const state = hash.get(AUTH_STATE_HASH_PARAM);
1255
- if (accessToken === null || accessToken.length === 0 || state === null || state.length === 0) {
1256
- logger.error("auth callback missing token or state");
1257
- throw ErrAuthCallbackInvalid;
1258
- }
1259
- return { accessToken, state };
1260
- }
1261
- function requireMatchingCallbackState(callback, expectedState, logger) {
1262
- if (expectedState === null) {
1263
- logger.error("auth callback expected state missing");
1264
- throw ErrAuthCallbackInvalid;
1265
- }
1266
- if (callback.state !== expectedState) {
1267
- logger.error("auth callback state mismatch");
1268
- throw ErrAuthStateMismatch;
1269
- }
1270
- }
1271
1245
 
1272
1246
  // src/client/auth/hosted-popup.ts
1273
- import * as errors11 from "@superbuilders/errors";
1274
1247
  var DEFAULT_POPUP_TIMEOUT_MS = 10 * 60 * 1000;
1275
1248
  var POPUP_POLL_MS = 250;
1249
+ var AUTH_MESSAGE_TYPE = "primer-tives.auth.result.v1";
1250
+ var AUTH_RESPONSE_MODE = "web_message";
1276
1251
  function hostedAuthUrl(config) {
1277
1252
  const logger = config.logger;
1278
1253
  if (!URL.canParse(config.origin)) {
@@ -1283,6 +1258,7 @@ function hostedAuthUrl(config) {
1283
1258
  authUrl.searchParams.set("publishableKey", config.publishableKey);
1284
1259
  authUrl.searchParams.set("redirectUri", redirectUri(config.options, config.currentUrl, logger));
1285
1260
  authUrl.searchParams.set("state", config.clientState);
1261
+ authUrl.searchParams.set("responseMode", AUTH_RESPONSE_MODE);
1286
1262
  return authUrl.toString();
1287
1263
  }
1288
1264
  function popupTimeoutMs(options) {
@@ -1291,62 +1267,132 @@ function popupTimeoutMs(options) {
1291
1267
  }
1292
1268
  return DEFAULT_POPUP_TIMEOUT_MS;
1293
1269
  }
1294
- function readPopupCallback(href, config) {
1295
- const logger = config.logger;
1296
- if (!URL.canParse(href)) {
1270
+ function isRecord(value) {
1271
+ return typeof value === "object" && value !== null;
1272
+ }
1273
+ function stringField(value, key) {
1274
+ const field = value[key];
1275
+ if (typeof field !== "string" || field.length === 0) {
1297
1276
  return null;
1298
1277
  }
1299
- const callbackResult = errors11.trySync(function readCallback() {
1300
- return readAuthCallback(new URL(href), logger);
1301
- });
1302
- if (callbackResult.error) {
1303
- logger.error("hosted auth popup callback invalid", { error: callbackResult.error });
1304
- throw callbackResult.error;
1278
+ return field;
1279
+ }
1280
+ function readPopupMessage(event, popup, config, expectedOrigin) {
1281
+ if (event.source !== popup) {
1282
+ return { kind: "ignore" };
1305
1283
  }
1306
- const callback = callbackResult.data;
1307
- if (callback === null) {
1308
- return null;
1284
+ if (event.origin !== expectedOrigin) {
1285
+ return { kind: "ignore" };
1309
1286
  }
1310
- if (callback.state !== config.clientState) {
1311
- logger.error("hosted auth popup state mismatch");
1312
- throw ErrAuthStateMismatch;
1287
+ const data = event.data;
1288
+ if (!isRecord(data)) {
1289
+ return { kind: "ignore" };
1313
1290
  }
1314
- return callback.accessToken;
1291
+ const messageType = stringField(data, "type");
1292
+ if (messageType !== AUTH_MESSAGE_TYPE) {
1293
+ return { kind: "ignore" };
1294
+ }
1295
+ const state = stringField(data, "state");
1296
+ if (state === null) {
1297
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1298
+ }
1299
+ if (state !== config.clientState) {
1300
+ return { kind: "error", error: ErrAuthStateMismatch };
1301
+ }
1302
+ const status = stringField(data, "status");
1303
+ if (status === "error") {
1304
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1305
+ }
1306
+ if (status !== "success") {
1307
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1308
+ }
1309
+ const accessToken = stringField(data, "accessToken");
1310
+ if (accessToken === null) {
1311
+ return { kind: "error", error: ErrAuthCallbackInvalid };
1312
+ }
1313
+ return { kind: "success", accessToken };
1315
1314
  }
1316
- async function beginHostedPopup(config) {
1317
- const logger = config.logger;
1318
- const popup = openAuthPopup(hostedAuthUrl(config), config.options, logger);
1319
- const expiresAt = Date.now() + popupTimeoutMs(config.options);
1320
- while (Date.now() < expiresAt) {
1321
- if (popup.closed) {
1322
- logger.error("hosted auth popup closed");
1323
- throw ErrAuthCancelled;
1324
- }
1325
- const href = readablePopupUrl(popup);
1326
- if (href !== null) {
1327
- const accessTokenResult = errors11.trySync(function readAccessToken() {
1328
- return readPopupCallback(href, config);
1329
- });
1330
- if (accessTokenResult.error) {
1331
- popup.close();
1332
- logger.error("hosted auth popup failed", { error: accessTokenResult.error });
1333
- throw accessTokenResult.error;
1315
+ async function waitForPopupMessage(popup, config, expectedOrigin) {
1316
+ let __stack = [];
1317
+ try {
1318
+ const logger = config.logger;
1319
+ const stack = __using(__stack, new AsyncDisposableStack, 1);
1320
+ stack.defer(function closePopup() {
1321
+ popup.close();
1322
+ });
1323
+ const result = await new Promise(function waitForMessage(resolve, reject) {
1324
+ let settled = false;
1325
+ function finishWithError(error) {
1326
+ if (settled) {
1327
+ return;
1328
+ }
1329
+ settled = true;
1330
+ reject(error);
1334
1331
  }
1335
- if (accessTokenResult.data !== null) {
1336
- popup.close();
1332
+ function finishWithToken(token) {
1333
+ if (settled) {
1334
+ return;
1335
+ }
1336
+ settled = true;
1337
1337
  logger.debug("hosted auth popup completed");
1338
- return accessTokenResult.data;
1338
+ resolve(token);
1339
1339
  }
1340
- }
1341
- await sleep(POPUP_POLL_MS);
1340
+ const timeoutId = globalThis.setTimeout(function timeout() {
1341
+ logger.error("hosted auth popup timed out");
1342
+ finishWithError(ErrAuthCancelled);
1343
+ }, popupTimeoutMs(config.options));
1344
+ stack.defer(function clearPopupTimeout() {
1345
+ globalThis.clearTimeout(timeoutId);
1346
+ });
1347
+ const closedPollId = globalThis.setInterval(function checkClosed() {
1348
+ if (!popup.closed) {
1349
+ return;
1350
+ }
1351
+ logger.error("hosted auth popup closed");
1352
+ finishWithError(ErrAuthCancelled);
1353
+ }, POPUP_POLL_MS);
1354
+ stack.defer(function clearClosedPoll() {
1355
+ globalThis.clearInterval(closedPollId);
1356
+ });
1357
+ function handleMessage(event) {
1358
+ const result2 = readPopupMessage(event, popup, config, expectedOrigin);
1359
+ if (result2.kind === "ignore") {
1360
+ return;
1361
+ }
1362
+ if (result2.kind === "error") {
1363
+ logger.error("hosted auth popup failed", { error: result2.error });
1364
+ finishWithError(result2.error);
1365
+ return;
1366
+ }
1367
+ finishWithToken(result2.accessToken);
1368
+ }
1369
+ globalThis.addEventListener("message", handleMessage);
1370
+ stack.defer(function removeMessageListener() {
1371
+ globalThis.removeEventListener("message", handleMessage);
1372
+ });
1373
+ });
1374
+ return result;
1375
+ } catch (_catch) {
1376
+ var _err = _catch, _hasErr = 1;
1377
+ } finally {
1378
+ var _promise = __callDispose(__stack, _err, _hasErr);
1379
+ _promise && await _promise;
1380
+ }
1381
+ }
1382
+ async function beginHostedPopup(config) {
1383
+ const logger = config.logger;
1384
+ const url = hostedAuthUrl(config);
1385
+ if (!URL.canParse(config.origin)) {
1386
+ logger.error("hosted auth origin invalid", { origin: config.origin });
1387
+ throw ErrAuthCallbackInvalid;
1342
1388
  }
1343
- popup.close();
1344
- logger.error("hosted auth popup timed out");
1345
- throw ErrAuthCancelled;
1389
+ const expectedOrigin = new URL(config.origin).origin;
1390
+ const popup = openAuthPopup(url, config.options, logger);
1391
+ return waitForPopupMessage(popup, config, expectedOrigin);
1346
1392
  }
1347
1393
 
1348
1394
  // src/client/auth/access-token.ts
1349
- import * as errors12 from "@superbuilders/errors";
1395
+ import * as errors10 from "@superbuilders/errors";
1350
1396
  var ACCESS_TOKEN_PREFIX = "eyJ";
1351
1397
  var resolvedAccessTokenBrand = Symbol("primer resolved access token");
1352
1398
  function isMalformedJws(token) {
@@ -1359,7 +1405,7 @@ function isMalformedJws(token) {
1359
1405
  function resolveAccessToken(token, logger) {
1360
1406
  if (isMalformedJws(token)) {
1361
1407
  logger.error("malformed access token", { prefix: ACCESS_TOKEN_PREFIX });
1362
- throw errors12.wrap(ErrMalformedAccessToken, `token must start with '${ACCESS_TOKEN_PREFIX}' and contain two dots`);
1408
+ throw errors10.wrap(ErrMalformedAccessToken, `token must start with '${ACCESS_TOKEN_PREFIX}' and contain two dots`);
1363
1409
  }
1364
1410
  return { value: token, [resolvedAccessTokenBrand]: true };
1365
1411
  }
@@ -1383,12 +1429,8 @@ function loadStoredAccessToken(storage, publishableKey) {
1383
1429
  function storeAccessToken(storage, publishableKey, accessToken) {
1384
1430
  storage.setItem(accessTokenStorageKey(publishableKey), accessToken);
1385
1431
  }
1386
- function loadAuthState(storage, publishableKey) {
1387
- const state = storage.getItem(authStateStorageKey(publishableKey));
1388
- if (state === null || state.length === 0) {
1389
- return null;
1390
- }
1391
- return state;
1432
+ function clearStoredAccessToken(storage, publishableKey) {
1433
+ storage.removeItem(accessTokenStorageKey(publishableKey));
1392
1434
  }
1393
1435
  function storeAuthState(storage, publishableKey, state) {
1394
1436
  storage.setItem(authStateStorageKey(publishableKey), state);
@@ -1398,44 +1440,119 @@ function clearAuthState(storage, publishableKey) {
1398
1440
  }
1399
1441
 
1400
1442
  // src/client/auth/provider.ts
1401
- async function resolveHostedAccessToken(options) {
1443
+ function resolveProvidedAccessToken(token, logger) {
1444
+ const result = errors11.trySync(function resolveProvidedToken() {
1445
+ return resolveAccessToken(token, logger);
1446
+ });
1447
+ if (result.error) {
1448
+ return { kind: "fatal", error: result.error };
1449
+ }
1450
+ return { kind: "resolved", accessToken: result.data };
1451
+ }
1452
+ function resolveManagedAccessToken(token, logger) {
1453
+ const result = errors11.trySync(function resolveManagedToken() {
1454
+ return resolveAccessToken(token, logger);
1455
+ });
1456
+ if (result.error) {
1457
+ return { kind: "unauthenticated", error: result.error };
1458
+ }
1459
+ return { kind: "resolved", accessToken: result.data };
1460
+ }
1461
+ function readBrowserAuthContext(options) {
1402
1462
  const logger = options.logger;
1403
- const storage = browserStorage(options.hostedAuth, logger);
1404
- const url = currentUrl(options.hostedAuth, logger);
1405
- const callback = readAuthCallback(url, logger);
1406
- if (callback !== null) {
1407
- requireMatchingCallbackState(callback, loadAuthState(storage, options.publishableKey), logger);
1408
- storeAccessToken(storage, options.publishableKey, callback.accessToken);
1409
- clearAuthState(storage, options.publishableKey);
1410
- clearCallbackHash(options.hostedAuth, url);
1411
- return resolveAccessToken(callback.accessToken, logger);
1412
- }
1413
- const stored = loadStoredAccessToken(storage, options.publishableKey);
1463
+ const contextResult = errors11.trySync(function readContext() {
1464
+ const storage = browserStorage(options.hostedAuth, logger);
1465
+ const url = currentUrl(options.hostedAuth, logger);
1466
+ return { storage, url };
1467
+ });
1468
+ if (contextResult.error) {
1469
+ return { kind: "unauthenticated", error: contextResult.error };
1470
+ }
1471
+ return contextResult.data;
1472
+ }
1473
+ function resolveStoredAccessToken(context, options) {
1474
+ const stored = loadStoredAccessToken(context.storage, options.publishableKey);
1475
+ if (stored === null) {
1476
+ return null;
1477
+ }
1478
+ const resolved = resolveManagedAccessToken(stored, options.logger);
1479
+ if (resolved.kind === "unauthenticated") {
1480
+ clearStoredAccessToken(context.storage, options.publishableKey);
1481
+ }
1482
+ return resolved;
1483
+ }
1484
+ function resolveExistingAccessToken(options) {
1485
+ if (options.accessToken !== undefined) {
1486
+ return resolveProvidedAccessToken(options.accessToken, options.logger);
1487
+ }
1488
+ const context = readBrowserAuthContext(options);
1489
+ if ("kind" in context) {
1490
+ return context;
1491
+ }
1492
+ const stored = resolveStoredAccessToken(context, options);
1414
1493
  if (stored !== null) {
1415
- return resolveAccessToken(stored, logger);
1494
+ return stored;
1495
+ }
1496
+ return { kind: "unauthenticated", error: null };
1497
+ }
1498
+ async function beginHostedLogin(options) {
1499
+ const logger = options.logger;
1500
+ const context = readBrowserAuthContext(options);
1501
+ if ("kind" in context) {
1502
+ return context;
1503
+ }
1504
+ const clientStateResult = errors11.trySync(function prepareHostedLogin() {
1505
+ const clientState2 = randomClientState(logger);
1506
+ storeAuthState(context.storage, options.publishableKey, clientState2);
1507
+ return clientState2;
1508
+ });
1509
+ if (clientStateResult.error) {
1510
+ return { kind: "unauthenticated", error: clientStateResult.error };
1416
1511
  }
1417
- const clientState = randomClientState(logger);
1418
- storeAuthState(storage, options.publishableKey, clientState);
1419
- const accessToken = await beginHostedPopup({
1512
+ const clientState = clientStateResult.data;
1513
+ const accessTokenResult = await errors11.try(beginHostedPopup({
1420
1514
  origin: options.origin,
1421
1515
  publishableKey: options.publishableKey,
1422
- currentUrl: url,
1516
+ currentUrl: context.url,
1423
1517
  clientState,
1424
1518
  options: options.hostedAuth,
1425
1519
  logger
1426
- });
1427
- storeAccessToken(storage, options.publishableKey, accessToken);
1428
- clearAuthState(storage, options.publishableKey);
1429
- return resolveAccessToken(accessToken, logger);
1520
+ }));
1521
+ if (accessTokenResult.error) {
1522
+ clearAuthState(context.storage, options.publishableKey);
1523
+ return { kind: "unauthenticated", error: accessTokenResult.error };
1524
+ }
1525
+ const resolved = resolveManagedAccessToken(accessTokenResult.data, logger);
1526
+ if (resolved.kind === "unauthenticated") {
1527
+ clearAuthState(context.storage, options.publishableKey);
1528
+ return resolved;
1529
+ }
1530
+ storeAccessToken(context.storage, options.publishableKey, accessTokenResult.data);
1531
+ clearAuthState(context.storage, options.publishableKey);
1532
+ return resolved;
1430
1533
  }
1431
- async function resolveRuntimeAccessToken(options) {
1432
- if (options.accessToken !== undefined) {
1433
- return resolveAccessToken(options.accessToken, options.logger);
1534
+
1535
+ // src/client/unauthenticated-state.ts
1536
+ function unauthenticatedState(config) {
1537
+ let pending;
1538
+ function login() {
1539
+ if (pending) {
1540
+ return pending;
1541
+ }
1542
+ pending = config.login().finally(function clearPending() {
1543
+ pending = undefined;
1544
+ });
1545
+ return pending;
1434
1546
  }
1435
- return resolveHostedAccessToken(options);
1547
+ return {
1548
+ phase: "unauthenticated",
1549
+ error: config.error,
1550
+ login,
1551
+ toJSON: poisonToJSON
1552
+ };
1436
1553
  }
1437
1554
 
1438
- // src/client/create.ts
1555
+ // src/client/start.ts
1439
1556
  function supportedPcisOrEmpty(supportedPcis) {
1440
1557
  if (supportedPcis !== undefined) {
1441
1558
  return supportedPcis;
@@ -1448,35 +1565,76 @@ function runtimeSubject(subject) {
1448
1565
  }
1449
1566
  return subject;
1450
1567
  }
1451
- async function create(options) {
1452
- const logger = options.logger;
1453
- logger.debug("create");
1454
- const subject = runtimeSubject(options.subject);
1455
- const accessToken = await resolveRuntimeAccessToken({
1456
- accessToken: options.accessToken,
1457
- publishableKey: options.publishableKey,
1458
- origin: options.origin,
1459
- logger
1460
- });
1568
+ async function startRuntime(config, accessToken) {
1461
1569
  const transport = createTransport({
1462
1570
  accessToken,
1571
+ publishableKey: config.publishableKey,
1572
+ subject: config.subject,
1573
+ origin: config.origin,
1574
+ fetch: config.fetch,
1575
+ abort: config.abort,
1576
+ logger: config.logger
1577
+ });
1578
+ const session = makeSession({
1579
+ subject: config.subject,
1580
+ supportedPcis: config.supportedPcis,
1581
+ logger: config.logger,
1582
+ transport
1583
+ });
1584
+ return session.execute({ kind: "observation" }, "start");
1585
+ }
1586
+ function makeUnauthenticatedState(config, error) {
1587
+ return unauthenticatedState({
1588
+ error,
1589
+ login: function login() {
1590
+ return loginAndStart(config);
1591
+ }
1592
+ });
1593
+ }
1594
+ async function loginAndStart(config) {
1595
+ const result = await beginHostedLogin({
1596
+ origin: config.origin,
1597
+ publishableKey: config.publishableKey,
1598
+ logger: config.logger
1599
+ });
1600
+ if (result.kind === "unauthenticated") {
1601
+ return makeUnauthenticatedState(config, result.error);
1602
+ }
1603
+ return startRuntime(config, result.accessToken);
1604
+ }
1605
+ async function start(options) {
1606
+ const logger = options.logger;
1607
+ logger.debug("start");
1608
+ const config = {
1463
1609
  publishableKey: options.publishableKey,
1464
- subject,
1465
1610
  origin: options.origin,
1466
1611
  fetch: options.fetch,
1467
1612
  abort: options.abort,
1468
- logger
1469
- });
1470
- const session = makeSession({
1471
- subject,
1472
- supportedPcis: supportedPcisOrEmpty(options.supportedPcis),
1473
1613
  logger,
1474
- transport
1614
+ subject: runtimeSubject(options.subject),
1615
+ supportedPcis: supportedPcisOrEmpty(options.supportedPcis)
1616
+ };
1617
+ const accessToken = resolveExistingAccessToken({
1618
+ accessToken: options.accessToken,
1619
+ publishableKey: options.publishableKey,
1620
+ origin: options.origin,
1621
+ logger
1475
1622
  });
1476
- return session.execute({ kind: "observation" }, "observation");
1623
+ if (accessToken.kind === "fatal") {
1624
+ return {
1625
+ phase: "fatal",
1626
+ error: accessToken.error,
1627
+ retriable: false,
1628
+ toJSON: poisonToJSON
1629
+ };
1630
+ }
1631
+ if (accessToken.kind === "unauthenticated") {
1632
+ return makeUnauthenticatedState(config, accessToken.error);
1633
+ }
1634
+ return startRuntime(config, accessToken.accessToken);
1477
1635
  }
1478
1636
  export {
1479
- create
1637
+ start
1480
1638
  };
1481
1639
 
1482
- //# debugId=DE8A27A355B8A82664756E2164756E21
1640
+ //# debugId=9A3E7149C52454D064756E2164756E21