@bytescale/sdk 3.18.0 → 3.19.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.
@@ -2430,50 +2430,53 @@ var ServiceWorkerUtils = /*#__PURE__*/function () {
2430
2430
  ServiceWorkerUtils_classCallCheck(this, ServiceWorkerUtils);
2431
2431
  }
2432
2432
  ServiceWorkerUtils_createClass(ServiceWorkerUtils, [{
2433
- key: "registerServiceWorkerIfSupported",
2434
- value:
2435
- /**
2436
- * Idempotent.
2437
- *
2438
- * Only returns once the service worker has been activated.
2439
- *
2440
- * We don't need to unregister it: we just need to clear the config when auth ends.
2441
- */
2442
- function registerServiceWorkerIfSupported(serviceWorkerScript, configFieldName, fallbackMessage) {
2433
+ key: "canUseServiceWorkers",
2434
+ value: function canUseServiceWorkers() {
2435
+ return "serviceWorker" in navigator;
2436
+ }
2437
+ }, {
2438
+ key: "sendMessage",
2439
+ value: function sendMessage(message, config, serviceWorkerScriptFieldName) {
2443
2440
  try {
2444
2441
  var _this2 = this;
2445
- if (serviceWorkerScript === undefined) {
2446
- return undefined;
2447
- }
2448
- if (!("serviceWorker" in navigator)) {
2449
- ConsoleUtils.warn("Service workers not supported by browser. ".concat(fallbackMessage));
2450
- return undefined;
2451
- }
2442
+ return ServiceWorkerUtils_await(config.serviceWorkerScope !== undefined ? _this2.getActiveServiceWorkerElseRegister(config, message) : _this2.registerServiceWorkerIfSupported(config.serviceWorkerScript, message, serviceWorkerScriptFieldName), function (result) {
2443
+ if (!result.messageSent) {
2444
+ result.serviceWorker.postMessage(message);
2445
+ }
2446
+ return result.config;
2447
+ });
2448
+ } catch (e) {
2449
+ return Promise.reject(e);
2450
+ }
2451
+ }
2452
+ }, {
2453
+ key: "registerServiceWorkerIfSupported",
2454
+ value: function registerServiceWorkerIfSupported(serviceWorkerScript, init, serviceWorkerScriptFieldName) {
2455
+ try {
2456
+ var _this4 = this;
2452
2457
  if (!serviceWorkerScript.startsWith("/")) {
2453
- throw new Error("The '".concat(configFieldName, "' field must start with a '/' and reference a script at the root of your website."));
2458
+ throw new Error("The '".concat(serviceWorkerScriptFieldName, "' field must start with a '/' and reference a script at the root of your website."));
2454
2459
  }
2455
2460
  var forwardSlashCount = serviceWorkerScript.split("/").length - 1;
2456
2461
  if (forwardSlashCount > 1) {
2457
- ConsoleUtils.warn("The '".concat(configFieldName, "' field should be a root script (e.g. '/script.js'). The Bytescale SDK can only authorize requests originating from webpages that are at the same level as the script or below."));
2462
+ ConsoleUtils.warn("The '".concat(serviceWorkerScriptFieldName, "' field should be a root script (e.g. '/script.js'). The Bytescale SDK can only authorize requests originating from webpages that are at the same level as the script or below."));
2458
2463
  }
2459
- return ServiceWorkerUtils_await(_this2.registerAuthServiceWorker(serviceWorkerScript), function (_this$registerAuthSer) {
2460
- return _this$registerAuthSer.config;
2461
- });
2464
+ return ServiceWorkerUtils_await(_this4.registerAuthServiceWorker(serviceWorkerScript, init));
2462
2465
  } catch (e) {
2463
2466
  return Promise.reject(e);
2464
2467
  }
2465
2468
  }
2466
2469
  }, {
2467
2470
  key: "getActiveServiceWorkerElseRegister",
2468
- value: function getActiveServiceWorkerElseRegister(_ref) {
2469
- var serviceWorkerScope = _ref.serviceWorkerScope,
2470
- serviceWorkerScript = _ref.serviceWorkerScript;
2471
+ value: function getActiveServiceWorkerElseRegister(config, init) {
2471
2472
  try {
2472
- var _this4 = this;
2473
- return ServiceWorkerUtils_await(_this4.getActiveServiceWorker(serviceWorkerScope), function (serviceWorker) {
2474
- return serviceWorker !== undefined ? serviceWorker : ServiceWorkerUtils_await(_this4.registerAuthServiceWorker(serviceWorkerScript), function (_this3$registerAuthSe) {
2475
- return _this3$registerAuthSe.serviceWorker;
2476
- });
2473
+ var _this6 = this;
2474
+ return ServiceWorkerUtils_await(_this6.getActiveServiceWorker(config.serviceWorkerScope), function (serviceWorker) {
2475
+ return serviceWorker !== undefined ? {
2476
+ serviceWorker: serviceWorker,
2477
+ messageSent: false,
2478
+ config: config
2479
+ } : ServiceWorkerUtils_await(_this6.registerAuthServiceWorker(config.serviceWorkerScript, init));
2477
2480
  });
2478
2481
  } catch (e) {
2479
2482
  return Promise.reject(e);
@@ -2488,35 +2491,24 @@ var ServiceWorkerUtils = /*#__PURE__*/function () {
2488
2491
  */
2489
2492
  }, {
2490
2493
  key: "registerAuthServiceWorker",
2491
- value: function registerAuthServiceWorker(serviceWorkerScript) {
2494
+ value: function registerAuthServiceWorker(serviceWorkerScript, init) {
2492
2495
  try {
2496
+ var _this8 = this;
2493
2497
  return ServiceWorkerUtils_catch(function () {
2494
2498
  return ServiceWorkerUtils_await(navigator.serviceWorker.register(serviceWorkerScript), function (registration) {
2495
- return registration.active !== null ? {
2496
- serviceWorker: registration.active,
2497
- config: {
2498
- serviceWorkerScript: serviceWorkerScript,
2499
- serviceWorkerScope: registration.scope
2500
- }
2501
- } : ServiceWorkerUtils_await(new Promise(function (resolve) {
2502
- registration.addEventListener("updatefound", function () {
2503
- var newWorker = registration.installing;
2504
- if (newWorker !== null) {
2505
- newWorker.addEventListener("statechange", function () {
2506
- if (newWorker.state === "activated") {
2507
- resolve({
2508
- config: {
2509
- serviceWorkerScript: serviceWorkerScript,
2510
- serviceWorkerScope: registration.scope
2511
- },
2512
- serviceWorker: newWorker
2513
- });
2514
- }
2515
- });
2499
+ return ServiceWorkerUtils_await(_this8.waitForActiveServiceWorker(registration, init), function (_ref) {
2500
+ var serviceWorker = _ref.serviceWorker,
2501
+ messageSent = _ref.messageSent;
2502
+ return {
2503
+ serviceWorker: serviceWorker,
2504
+ messageSent: messageSent,
2505
+ config: {
2506
+ serviceWorkerScript: serviceWorkerScript,
2507
+ serviceWorkerScope: registration.scope
2516
2508
  }
2517
- });
2518
- }));
2519
- }); // Occurs when: (service worker is already registered AND there's been no code changes) OR (service worker was not previously registered).
2509
+ };
2510
+ });
2511
+ });
2520
2512
  }, function (e) {
2521
2513
  throw new Error("Failed to install Bytescale Service Worker (SW). ".concat(e.name, ": ").concat(e.message));
2522
2514
  });
@@ -2524,6 +2516,51 @@ var ServiceWorkerUtils = /*#__PURE__*/function () {
2524
2516
  return Promise.reject(e);
2525
2517
  }
2526
2518
  }
2519
+ }, {
2520
+ key: "waitForActiveServiceWorker",
2521
+ value: function waitForActiveServiceWorker(registration, init) {
2522
+ try {
2523
+ // If the service worker is already active, return it.
2524
+ if (registration.active !== null) {
2525
+ return {
2526
+ serviceWorker: registration.active,
2527
+ messageSent: false
2528
+ };
2529
+ }
2530
+ // Service worker has not finished installing, which means we've just started installing a new one, so send the INIT
2531
+ // message to it, as it will be waiting for it to complete its install phase.
2532
+ var messageSent;
2533
+ if (registration.installing !== null) {
2534
+ messageSent = true;
2535
+ registration.installing.postMessage(init);
2536
+ } else {
2537
+ messageSent = false;
2538
+ }
2539
+ // Wait for the service worker to become active.
2540
+ return ServiceWorkerUtils_await(new Promise(function (resolve, reject) {
2541
+ var _a, _b;
2542
+ var serviceWorker = (_b = (_a = registration.installing) !== null && _a !== void 0 ? _a : registration.waiting) !== null && _b !== void 0 ? _b : undefined;
2543
+ if (serviceWorker !== undefined) {
2544
+ var stateChangeHandler = function stateChangeHandler(e) {
2545
+ var sw = e.target;
2546
+ if (sw.state === "activated") {
2547
+ serviceWorker.removeEventListener("statechange", stateChangeHandler);
2548
+ resolve({
2549
+ messageSent: messageSent,
2550
+ serviceWorker: sw
2551
+ });
2552
+ }
2553
+ };
2554
+ serviceWorker.addEventListener("statechange", stateChangeHandler);
2555
+ } else {
2556
+ // If there's no installing or waiting service worker, reject.
2557
+ reject(new Error("No service worker is installing or waiting."));
2558
+ }
2559
+ }));
2560
+ } catch (e) {
2561
+ return Promise.reject(e);
2562
+ }
2563
+ }
2527
2564
  }, {
2528
2565
  key: "getActiveServiceWorker",
2529
2566
  value: function getActiveServiceWorker(serviceWorkerScope) {
@@ -2582,6 +2619,19 @@ function AuthManagerBrowser_async(f) {
2582
2619
  }
2583
2620
  };
2584
2621
  }
2622
+ function AuthManagerBrowser_invokeIgnored(body) {
2623
+ var result = body();
2624
+ if (result && result.then) {
2625
+ return result.then(AuthManagerBrowser_empty);
2626
+ }
2627
+ }
2628
+ function AuthManagerBrowser_invoke(body, then) {
2629
+ var result = body();
2630
+ if (result && result.then) {
2631
+ return result.then(then);
2632
+ }
2633
+ return then(result);
2634
+ }
2585
2635
  function AuthManagerBrowser_catch(body, recover) {
2586
2636
  try {
2587
2637
  var result = body();
@@ -2626,6 +2676,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2626
2676
  function AuthManagerImpl(serviceWorkerUtils) {
2627
2677
  AuthManagerBrowser_classCallCheck(this, AuthManagerImpl);
2628
2678
  this.serviceWorkerUtils = serviceWorkerUtils;
2679
+ this.serviceWorkerScriptFieldName = "serviceWorkerScript";
2629
2680
  this.contentType = "content-type";
2630
2681
  this.contentTypeJson = "application/json";
2631
2682
  this.contentTypeText = "text/plain";
@@ -2650,18 +2701,18 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2650
2701
  if (_this2.isAuthSessionActive()) {
2651
2702
  throw new Error("Auth session already active. Please call 'await endAuthSession()' and then call 'await beginAuthSession(...)' to start a new auth session.");
2652
2703
  }
2653
- var serviceWorkerScriptField = "serviceWorkerScript";
2654
- return AuthManagerBrowser_await(_this2.serviceWorkerUtils.registerServiceWorkerIfSupported(params.serviceWorkerScript, serviceWorkerScriptField, "Falling back to Bytescale CDN cookies for auth. These are third-party cookies, which some modern browsers block."), function (_this2$serviceWorkerU) {
2655
- var newSession = {
2656
- accessToken: undefined,
2657
- accessTokenRefreshHandle: undefined,
2658
- params: params,
2659
- isActive: true,
2660
- authServiceWorker: _this2$serviceWorkerU
2661
- };
2662
- AuthSessionState.setSession(newSession);
2663
- return newSession;
2664
- });
2704
+ var newSession = {
2705
+ accessToken: undefined,
2706
+ accessTokenRefreshHandle: undefined,
2707
+ params: params,
2708
+ isActive: true,
2709
+ authServiceWorker: params.serviceWorkerScript !== undefined && _this2.serviceWorkerUtils.canUseServiceWorkers() ? {
2710
+ serviceWorkerScript: params.serviceWorkerScript,
2711
+ serviceWorkerScope: undefined
2712
+ } : undefined
2713
+ };
2714
+ AuthSessionState.setSession(newSession);
2715
+ return newSession;
2665
2716
  })), function (session) {
2666
2717
  // IMPORTANT: must be called outside the above, else re-entrant deadlock will occur.
2667
2718
  return AuthManagerBrowser_awaitIgnored(_this2.refreshAccessToken(session));
@@ -2686,7 +2737,15 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2686
2737
  clearTimeout(session.accessTokenRefreshHandle);
2687
2738
  }
2688
2739
  return AuthManagerBrowser_await(_this4.deleteAccessToken(session.params), function () {
2689
- return AuthManagerBrowser_awaitIgnored(_this4.setServiceWorkerConfig(session, [])); // Prevent service worker from authorizing subsequent requests.
2740
+ return AuthManagerBrowser_invokeIgnored(function () {
2741
+ if (session.authServiceWorker !== undefined) {
2742
+ // Prevent service worker from authorizing subsequent requests.
2743
+ return AuthManagerBrowser_awaitIgnored(_this4.serviceWorkerUtils.sendMessage({
2744
+ type: "SET_BYTESCALE_AUTH_CONFIG",
2745
+ config: []
2746
+ }, session.authServiceWorker, _this4.serviceWorkerScriptFieldName));
2747
+ }
2748
+ });
2690
2749
  });
2691
2750
  })));
2692
2751
  } catch (e) {
@@ -2713,16 +2772,23 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2713
2772
  // confusion for us in the future (i.e. we may question "do we need to use both together? was there a reason?").
2714
2773
  // Also: if the user has omitted "allowedOrigins" from their JWT, then service worker-based auth is more secure
2715
2774
  // than cookie-based auth, which is another reason to prevent these cookies from being set unless required.
2716
- var setCookie = !_this6.isUsingServiceWorker(session);
2775
+ var setCookie = session.authServiceWorker === undefined;
2717
2776
  return AuthManagerBrowser_await(_this6.setAccessToken(session.params, jwt, setCookie), function (setTokenResult) {
2718
- return AuthManagerBrowser_await(_this6.setServiceWorkerConfig(session, [{
2719
- headers: [{
2720
- key: "Authorization",
2721
- value: "Bearer ".concat(jwt)
2722
- }],
2723
- expires: Date.now() + setTokenResult.ttlSeconds * 1000,
2724
- urlPrefix: "".concat(_this6.getCdnUrl(session.params), "/").concat(session.params.accountId, "/")
2725
- }]), function () {
2777
+ return AuthManagerBrowser_invoke(function () {
2778
+ if (session.authServiceWorker !== undefined) {
2779
+ return AuthManagerBrowser_awaitIgnored(_this6.serviceWorkerUtils.sendMessage({
2780
+ type: "SET_BYTESCALE_AUTH_CONFIG",
2781
+ config: [{
2782
+ headers: [{
2783
+ key: "Authorization",
2784
+ value: "Bearer ".concat(jwt)
2785
+ }],
2786
+ expires: Date.now() + setTokenResult.ttlSeconds * 1000,
2787
+ urlPrefix: "".concat(_this6.getCdnUrl(session.params), "/").concat(session.params.accountId, "/")
2788
+ }]
2789
+ }, session.authServiceWorker, _this6.serviceWorkerScriptFieldName));
2790
+ }
2791
+ }, function () {
2726
2792
  var desiredTtl = setTokenResult.ttlSeconds - _this6.refreshBeforeExpirySeconds;
2727
2793
  timeout = Math.max(desiredTtl, _this6.minJwtTtlSeconds);
2728
2794
  if (desiredTtl !== timeout) {
@@ -2754,32 +2820,6 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2754
2820
  return Promise.reject(e);
2755
2821
  }
2756
2822
  }
2757
- }, {
2758
- key: "isUsingServiceWorker",
2759
- value: function isUsingServiceWorker(session) {
2760
- return session.authServiceWorker !== undefined;
2761
- }
2762
- }, {
2763
- key: "setServiceWorkerConfig",
2764
- value: function setServiceWorkerConfig(session, config) {
2765
- try {
2766
- var _this8 = this;
2767
- if (session.authServiceWorker === undefined) {
2768
- return undefined;
2769
- }
2770
- // We re-fetch the latest active worker, as another tab may have registered a new one, and then the tab may be closed,
2771
- // leaving us as the only open tab but with an old and ineffective service worker reference.
2772
- return AuthManagerBrowser_await(_this8.serviceWorkerUtils.getActiveServiceWorkerElseRegister(session.authServiceWorker), function (serviceWorker) {
2773
- var message = {
2774
- type: "SET_BYTESCALE_AUTH_CONFIG",
2775
- config: config
2776
- };
2777
- serviceWorker.postMessage(message);
2778
- });
2779
- } catch (e) {
2780
- return Promise.reject(e);
2781
- }
2782
- }
2783
2823
  }, {
2784
2824
  key: "getAccessTokenUrl",
2785
2825
  value: function getAccessTokenUrl(params, setCookie) {
@@ -2795,9 +2835,9 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2795
2835
  key: "deleteAccessToken",
2796
2836
  value: function deleteAccessToken(params) {
2797
2837
  try {
2798
- var _this10 = this;
2838
+ var _this8 = this;
2799
2839
  var _a;
2800
- return AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this10.getAccessTokenUrl(params, true), {
2840
+ return AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this8.getAccessTokenUrl(params, true), {
2801
2841
  method: "DELETE",
2802
2842
  credentials: "include",
2803
2843
  headers: {}
@@ -2813,15 +2853,15 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2813
2853
  key: "setAccessToken",
2814
2854
  value: function setAccessToken(params, jwt, setCookie) {
2815
2855
  try {
2816
- var _this12 = this;
2856
+ var _this10 = this;
2817
2857
  var _a;
2818
2858
  var request = {
2819
2859
  accessToken: jwt
2820
2860
  };
2821
- return AuthManagerBrowser_await(BaseAPI.fetch(_this12.getAccessTokenUrl(params, setCookie), {
2861
+ return AuthManagerBrowser_await(BaseAPI.fetch(_this10.getAccessTokenUrl(params, setCookie), {
2822
2862
  method: "PUT",
2823
2863
  credentials: "include",
2824
- headers: AuthManagerBrowser_defineProperty({}, _this12.contentType, _this12.contentTypeJson),
2864
+ headers: AuthManagerBrowser_defineProperty({}, _this10.contentType, _this10.contentTypeJson),
2825
2865
  body: JSON.stringify(request)
2826
2866
  }, {
2827
2867
  isBytescaleApi: true,
@@ -2837,10 +2877,10 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2837
2877
  key: "getAccessToken",
2838
2878
  value: function getAccessToken(params, headers) {
2839
2879
  try {
2840
- var _this14 = this;
2880
+ var _this12 = this;
2841
2881
  var _a, _b;
2842
2882
  var endpointName = "Your auth API endpoint";
2843
- var requiredContentType = _this14.contentTypeText;
2883
+ var requiredContentType = _this12.contentTypeText;
2844
2884
  return AuthManagerBrowser_await(BaseAPI.fetch(params.authUrl, {
2845
2885
  method: "GET",
2846
2886
  headers: headers
@@ -2848,10 +2888,10 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2848
2888
  isBytescaleApi: false,
2849
2889
  fetchApi: (_a = params.options) === null || _a === void 0 ? void 0 : _a.fetchApi
2850
2890
  }), function (result) {
2851
- var actualContentType = (_b = result.headers.get(_this14.contentType)) !== null && _b !== void 0 ? _b : "";
2891
+ var actualContentType = (_b = result.headers.get(_this12.contentType)) !== null && _b !== void 0 ? _b : "";
2852
2892
  // Support content types like "text/plain; charset=utf-8" and "text/plain"
2853
2893
  if (actualContentType.split(";")[0] !== requiredContentType) {
2854
- throw new Error("".concat(endpointName, " returned \"").concat(actualContentType, "\" for the ").concat(_this14.contentType, " response header, but the Bytescale SDK requires \"").concat(requiredContentType, "\"."));
2894
+ throw new Error("".concat(endpointName, " returned \"").concat(actualContentType, "\" for the ").concat(_this12.contentType, " response header, but the Bytescale SDK requires \"").concat(requiredContentType, "\"."));
2855
2895
  }
2856
2896
  return AuthManagerBrowser_await(result.text(), function (jwt) {
2857
2897
  if (jwt.length === 0) {
@@ -2415,50 +2415,53 @@ var ServiceWorkerUtils = /*#__PURE__*/function () {
2415
2415
  ServiceWorkerUtils_classCallCheck(this, ServiceWorkerUtils);
2416
2416
  }
2417
2417
  ServiceWorkerUtils_createClass(ServiceWorkerUtils, [{
2418
- key: "registerServiceWorkerIfSupported",
2419
- value:
2420
- /**
2421
- * Idempotent.
2422
- *
2423
- * Only returns once the service worker has been activated.
2424
- *
2425
- * We don't need to unregister it: we just need to clear the config when auth ends.
2426
- */
2427
- function registerServiceWorkerIfSupported(serviceWorkerScript, configFieldName, fallbackMessage) {
2418
+ key: "canUseServiceWorkers",
2419
+ value: function canUseServiceWorkers() {
2420
+ return "serviceWorker" in navigator;
2421
+ }
2422
+ }, {
2423
+ key: "sendMessage",
2424
+ value: function sendMessage(message, config, serviceWorkerScriptFieldName) {
2428
2425
  try {
2429
2426
  var _this2 = this;
2430
- if (serviceWorkerScript === undefined) {
2431
- return undefined;
2432
- }
2433
- if (!("serviceWorker" in navigator)) {
2434
- ConsoleUtils.warn("Service workers not supported by browser. ".concat(fallbackMessage));
2435
- return undefined;
2436
- }
2427
+ return ServiceWorkerUtils_await(config.serviceWorkerScope !== undefined ? _this2.getActiveServiceWorkerElseRegister(config, message) : _this2.registerServiceWorkerIfSupported(config.serviceWorkerScript, message, serviceWorkerScriptFieldName), function (result) {
2428
+ if (!result.messageSent) {
2429
+ result.serviceWorker.postMessage(message);
2430
+ }
2431
+ return result.config;
2432
+ });
2433
+ } catch (e) {
2434
+ return Promise.reject(e);
2435
+ }
2436
+ }
2437
+ }, {
2438
+ key: "registerServiceWorkerIfSupported",
2439
+ value: function registerServiceWorkerIfSupported(serviceWorkerScript, init, serviceWorkerScriptFieldName) {
2440
+ try {
2441
+ var _this4 = this;
2437
2442
  if (!serviceWorkerScript.startsWith("/")) {
2438
- throw new Error("The '".concat(configFieldName, "' field must start with a '/' and reference a script at the root of your website."));
2443
+ throw new Error("The '".concat(serviceWorkerScriptFieldName, "' field must start with a '/' and reference a script at the root of your website."));
2439
2444
  }
2440
2445
  var forwardSlashCount = serviceWorkerScript.split("/").length - 1;
2441
2446
  if (forwardSlashCount > 1) {
2442
- ConsoleUtils.warn("The '".concat(configFieldName, "' field should be a root script (e.g. '/script.js'). The Bytescale SDK can only authorize requests originating from webpages that are at the same level as the script or below."));
2447
+ ConsoleUtils.warn("The '".concat(serviceWorkerScriptFieldName, "' field should be a root script (e.g. '/script.js'). The Bytescale SDK can only authorize requests originating from webpages that are at the same level as the script or below."));
2443
2448
  }
2444
- return ServiceWorkerUtils_await(_this2.registerAuthServiceWorker(serviceWorkerScript), function (_this$registerAuthSer) {
2445
- return _this$registerAuthSer.config;
2446
- });
2449
+ return ServiceWorkerUtils_await(_this4.registerAuthServiceWorker(serviceWorkerScript, init));
2447
2450
  } catch (e) {
2448
2451
  return Promise.reject(e);
2449
2452
  }
2450
2453
  }
2451
2454
  }, {
2452
2455
  key: "getActiveServiceWorkerElseRegister",
2453
- value: function getActiveServiceWorkerElseRegister(_ref) {
2454
- var serviceWorkerScope = _ref.serviceWorkerScope,
2455
- serviceWorkerScript = _ref.serviceWorkerScript;
2456
+ value: function getActiveServiceWorkerElseRegister(config, init) {
2456
2457
  try {
2457
- var _this4 = this;
2458
- return ServiceWorkerUtils_await(_this4.getActiveServiceWorker(serviceWorkerScope), function (serviceWorker) {
2459
- return serviceWorker !== undefined ? serviceWorker : ServiceWorkerUtils_await(_this4.registerAuthServiceWorker(serviceWorkerScript), function (_this3$registerAuthSe) {
2460
- return _this3$registerAuthSe.serviceWorker;
2461
- });
2458
+ var _this6 = this;
2459
+ return ServiceWorkerUtils_await(_this6.getActiveServiceWorker(config.serviceWorkerScope), function (serviceWorker) {
2460
+ return serviceWorker !== undefined ? {
2461
+ serviceWorker: serviceWorker,
2462
+ messageSent: false,
2463
+ config: config
2464
+ } : ServiceWorkerUtils_await(_this6.registerAuthServiceWorker(config.serviceWorkerScript, init));
2462
2465
  });
2463
2466
  } catch (e) {
2464
2467
  return Promise.reject(e);
@@ -2473,35 +2476,24 @@ var ServiceWorkerUtils = /*#__PURE__*/function () {
2473
2476
  */
2474
2477
  }, {
2475
2478
  key: "registerAuthServiceWorker",
2476
- value: function registerAuthServiceWorker(serviceWorkerScript) {
2479
+ value: function registerAuthServiceWorker(serviceWorkerScript, init) {
2477
2480
  try {
2481
+ var _this8 = this;
2478
2482
  return ServiceWorkerUtils_catch(function () {
2479
2483
  return ServiceWorkerUtils_await(navigator.serviceWorker.register(serviceWorkerScript), function (registration) {
2480
- return registration.active !== null ? {
2481
- serviceWorker: registration.active,
2482
- config: {
2483
- serviceWorkerScript: serviceWorkerScript,
2484
- serviceWorkerScope: registration.scope
2485
- }
2486
- } : ServiceWorkerUtils_await(new Promise(function (resolve) {
2487
- registration.addEventListener("updatefound", function () {
2488
- var newWorker = registration.installing;
2489
- if (newWorker !== null) {
2490
- newWorker.addEventListener("statechange", function () {
2491
- if (newWorker.state === "activated") {
2492
- resolve({
2493
- config: {
2494
- serviceWorkerScript: serviceWorkerScript,
2495
- serviceWorkerScope: registration.scope
2496
- },
2497
- serviceWorker: newWorker
2498
- });
2499
- }
2500
- });
2484
+ return ServiceWorkerUtils_await(_this8.waitForActiveServiceWorker(registration, init), function (_ref) {
2485
+ var serviceWorker = _ref.serviceWorker,
2486
+ messageSent = _ref.messageSent;
2487
+ return {
2488
+ serviceWorker: serviceWorker,
2489
+ messageSent: messageSent,
2490
+ config: {
2491
+ serviceWorkerScript: serviceWorkerScript,
2492
+ serviceWorkerScope: registration.scope
2501
2493
  }
2502
- });
2503
- }));
2504
- }); // Occurs when: (service worker is already registered AND there's been no code changes) OR (service worker was not previously registered).
2494
+ };
2495
+ });
2496
+ });
2505
2497
  }, function (e) {
2506
2498
  throw new Error("Failed to install Bytescale Service Worker (SW). ".concat(e.name, ": ").concat(e.message));
2507
2499
  });
@@ -2509,6 +2501,51 @@ var ServiceWorkerUtils = /*#__PURE__*/function () {
2509
2501
  return Promise.reject(e);
2510
2502
  }
2511
2503
  }
2504
+ }, {
2505
+ key: "waitForActiveServiceWorker",
2506
+ value: function waitForActiveServiceWorker(registration, init) {
2507
+ try {
2508
+ // If the service worker is already active, return it.
2509
+ if (registration.active !== null) {
2510
+ return {
2511
+ serviceWorker: registration.active,
2512
+ messageSent: false
2513
+ };
2514
+ }
2515
+ // Service worker has not finished installing, which means we've just started installing a new one, so send the INIT
2516
+ // message to it, as it will be waiting for it to complete its install phase.
2517
+ var messageSent;
2518
+ if (registration.installing !== null) {
2519
+ messageSent = true;
2520
+ registration.installing.postMessage(init);
2521
+ } else {
2522
+ messageSent = false;
2523
+ }
2524
+ // Wait for the service worker to become active.
2525
+ return ServiceWorkerUtils_await(new Promise(function (resolve, reject) {
2526
+ var _a, _b;
2527
+ var serviceWorker = (_b = (_a = registration.installing) !== null && _a !== void 0 ? _a : registration.waiting) !== null && _b !== void 0 ? _b : undefined;
2528
+ if (serviceWorker !== undefined) {
2529
+ var stateChangeHandler = function stateChangeHandler(e) {
2530
+ var sw = e.target;
2531
+ if (sw.state === "activated") {
2532
+ serviceWorker.removeEventListener("statechange", stateChangeHandler);
2533
+ resolve({
2534
+ messageSent: messageSent,
2535
+ serviceWorker: sw
2536
+ });
2537
+ }
2538
+ };
2539
+ serviceWorker.addEventListener("statechange", stateChangeHandler);
2540
+ } else {
2541
+ // If there's no installing or waiting service worker, reject.
2542
+ reject(new Error("No service worker is installing or waiting."));
2543
+ }
2544
+ }));
2545
+ } catch (e) {
2546
+ return Promise.reject(e);
2547
+ }
2548
+ }
2512
2549
  }, {
2513
2550
  key: "getActiveServiceWorker",
2514
2551
  value: function getActiveServiceWorker(serviceWorkerScope) {
@@ -2567,6 +2604,19 @@ function AuthManagerBrowser_async(f) {
2567
2604
  }
2568
2605
  };
2569
2606
  }
2607
+ function AuthManagerBrowser_invokeIgnored(body) {
2608
+ var result = body();
2609
+ if (result && result.then) {
2610
+ return result.then(AuthManagerBrowser_empty);
2611
+ }
2612
+ }
2613
+ function AuthManagerBrowser_invoke(body, then) {
2614
+ var result = body();
2615
+ if (result && result.then) {
2616
+ return result.then(then);
2617
+ }
2618
+ return then(result);
2619
+ }
2570
2620
  function AuthManagerBrowser_catch(body, recover) {
2571
2621
  try {
2572
2622
  var result = body();
@@ -2611,6 +2661,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2611
2661
  function AuthManagerImpl(serviceWorkerUtils) {
2612
2662
  AuthManagerBrowser_classCallCheck(this, AuthManagerImpl);
2613
2663
  this.serviceWorkerUtils = serviceWorkerUtils;
2664
+ this.serviceWorkerScriptFieldName = "serviceWorkerScript";
2614
2665
  this.contentType = "content-type";
2615
2666
  this.contentTypeJson = "application/json";
2616
2667
  this.contentTypeText = "text/plain";
@@ -2635,18 +2686,18 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2635
2686
  if (_this2.isAuthSessionActive()) {
2636
2687
  throw new Error("Auth session already active. Please call 'await endAuthSession()' and then call 'await beginAuthSession(...)' to start a new auth session.");
2637
2688
  }
2638
- var serviceWorkerScriptField = "serviceWorkerScript";
2639
- return AuthManagerBrowser_await(_this2.serviceWorkerUtils.registerServiceWorkerIfSupported(params.serviceWorkerScript, serviceWorkerScriptField, "Falling back to Bytescale CDN cookies for auth. These are third-party cookies, which some modern browsers block."), function (_this2$serviceWorkerU) {
2640
- var newSession = {
2641
- accessToken: undefined,
2642
- accessTokenRefreshHandle: undefined,
2643
- params: params,
2644
- isActive: true,
2645
- authServiceWorker: _this2$serviceWorkerU
2646
- };
2647
- AuthSessionState.setSession(newSession);
2648
- return newSession;
2649
- });
2689
+ var newSession = {
2690
+ accessToken: undefined,
2691
+ accessTokenRefreshHandle: undefined,
2692
+ params: params,
2693
+ isActive: true,
2694
+ authServiceWorker: params.serviceWorkerScript !== undefined && _this2.serviceWorkerUtils.canUseServiceWorkers() ? {
2695
+ serviceWorkerScript: params.serviceWorkerScript,
2696
+ serviceWorkerScope: undefined
2697
+ } : undefined
2698
+ };
2699
+ AuthSessionState.setSession(newSession);
2700
+ return newSession;
2650
2701
  })), function (session) {
2651
2702
  // IMPORTANT: must be called outside the above, else re-entrant deadlock will occur.
2652
2703
  return AuthManagerBrowser_awaitIgnored(_this2.refreshAccessToken(session));
@@ -2671,7 +2722,15 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2671
2722
  clearTimeout(session.accessTokenRefreshHandle);
2672
2723
  }
2673
2724
  return AuthManagerBrowser_await(_this4.deleteAccessToken(session.params), function () {
2674
- return AuthManagerBrowser_awaitIgnored(_this4.setServiceWorkerConfig(session, [])); // Prevent service worker from authorizing subsequent requests.
2725
+ return AuthManagerBrowser_invokeIgnored(function () {
2726
+ if (session.authServiceWorker !== undefined) {
2727
+ // Prevent service worker from authorizing subsequent requests.
2728
+ return AuthManagerBrowser_awaitIgnored(_this4.serviceWorkerUtils.sendMessage({
2729
+ type: "SET_BYTESCALE_AUTH_CONFIG",
2730
+ config: []
2731
+ }, session.authServiceWorker, _this4.serviceWorkerScriptFieldName));
2732
+ }
2733
+ });
2675
2734
  });
2676
2735
  })));
2677
2736
  } catch (e) {
@@ -2698,16 +2757,23 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2698
2757
  // confusion for us in the future (i.e. we may question "do we need to use both together? was there a reason?").
2699
2758
  // Also: if the user has omitted "allowedOrigins" from their JWT, then service worker-based auth is more secure
2700
2759
  // than cookie-based auth, which is another reason to prevent these cookies from being set unless required.
2701
- var setCookie = !_this6.isUsingServiceWorker(session);
2760
+ var setCookie = session.authServiceWorker === undefined;
2702
2761
  return AuthManagerBrowser_await(_this6.setAccessToken(session.params, jwt, setCookie), function (setTokenResult) {
2703
- return AuthManagerBrowser_await(_this6.setServiceWorkerConfig(session, [{
2704
- headers: [{
2705
- key: "Authorization",
2706
- value: "Bearer ".concat(jwt)
2707
- }],
2708
- expires: Date.now() + setTokenResult.ttlSeconds * 1000,
2709
- urlPrefix: "".concat(_this6.getCdnUrl(session.params), "/").concat(session.params.accountId, "/")
2710
- }]), function () {
2762
+ return AuthManagerBrowser_invoke(function () {
2763
+ if (session.authServiceWorker !== undefined) {
2764
+ return AuthManagerBrowser_awaitIgnored(_this6.serviceWorkerUtils.sendMessage({
2765
+ type: "SET_BYTESCALE_AUTH_CONFIG",
2766
+ config: [{
2767
+ headers: [{
2768
+ key: "Authorization",
2769
+ value: "Bearer ".concat(jwt)
2770
+ }],
2771
+ expires: Date.now() + setTokenResult.ttlSeconds * 1000,
2772
+ urlPrefix: "".concat(_this6.getCdnUrl(session.params), "/").concat(session.params.accountId, "/")
2773
+ }]
2774
+ }, session.authServiceWorker, _this6.serviceWorkerScriptFieldName));
2775
+ }
2776
+ }, function () {
2711
2777
  var desiredTtl = setTokenResult.ttlSeconds - _this6.refreshBeforeExpirySeconds;
2712
2778
  timeout = Math.max(desiredTtl, _this6.minJwtTtlSeconds);
2713
2779
  if (desiredTtl !== timeout) {
@@ -2739,32 +2805,6 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2739
2805
  return Promise.reject(e);
2740
2806
  }
2741
2807
  }
2742
- }, {
2743
- key: "isUsingServiceWorker",
2744
- value: function isUsingServiceWorker(session) {
2745
- return session.authServiceWorker !== undefined;
2746
- }
2747
- }, {
2748
- key: "setServiceWorkerConfig",
2749
- value: function setServiceWorkerConfig(session, config) {
2750
- try {
2751
- var _this8 = this;
2752
- if (session.authServiceWorker === undefined) {
2753
- return undefined;
2754
- }
2755
- // We re-fetch the latest active worker, as another tab may have registered a new one, and then the tab may be closed,
2756
- // leaving us as the only open tab but with an old and ineffective service worker reference.
2757
- return AuthManagerBrowser_await(_this8.serviceWorkerUtils.getActiveServiceWorkerElseRegister(session.authServiceWorker), function (serviceWorker) {
2758
- var message = {
2759
- type: "SET_BYTESCALE_AUTH_CONFIG",
2760
- config: config
2761
- };
2762
- serviceWorker.postMessage(message);
2763
- });
2764
- } catch (e) {
2765
- return Promise.reject(e);
2766
- }
2767
- }
2768
2808
  }, {
2769
2809
  key: "getAccessTokenUrl",
2770
2810
  value: function getAccessTokenUrl(params, setCookie) {
@@ -2780,9 +2820,9 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2780
2820
  key: "deleteAccessToken",
2781
2821
  value: function deleteAccessToken(params) {
2782
2822
  try {
2783
- var _this10 = this;
2823
+ var _this8 = this;
2784
2824
  var _a;
2785
- return AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this10.getAccessTokenUrl(params, true), {
2825
+ return AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this8.getAccessTokenUrl(params, true), {
2786
2826
  method: "DELETE",
2787
2827
  credentials: "include",
2788
2828
  headers: {}
@@ -2798,15 +2838,15 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2798
2838
  key: "setAccessToken",
2799
2839
  value: function setAccessToken(params, jwt, setCookie) {
2800
2840
  try {
2801
- var _this12 = this;
2841
+ var _this10 = this;
2802
2842
  var _a;
2803
2843
  var request = {
2804
2844
  accessToken: jwt
2805
2845
  };
2806
- return AuthManagerBrowser_await(BaseAPI.fetch(_this12.getAccessTokenUrl(params, setCookie), {
2846
+ return AuthManagerBrowser_await(BaseAPI.fetch(_this10.getAccessTokenUrl(params, setCookie), {
2807
2847
  method: "PUT",
2808
2848
  credentials: "include",
2809
- headers: AuthManagerBrowser_defineProperty({}, _this12.contentType, _this12.contentTypeJson),
2849
+ headers: AuthManagerBrowser_defineProperty({}, _this10.contentType, _this10.contentTypeJson),
2810
2850
  body: JSON.stringify(request)
2811
2851
  }, {
2812
2852
  isBytescaleApi: true,
@@ -2822,10 +2862,10 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2822
2862
  key: "getAccessToken",
2823
2863
  value: function getAccessToken(params, headers) {
2824
2864
  try {
2825
- var _this14 = this;
2865
+ var _this12 = this;
2826
2866
  var _a, _b;
2827
2867
  var endpointName = "Your auth API endpoint";
2828
- var requiredContentType = _this14.contentTypeText;
2868
+ var requiredContentType = _this12.contentTypeText;
2829
2869
  return AuthManagerBrowser_await(BaseAPI.fetch(params.authUrl, {
2830
2870
  method: "GET",
2831
2871
  headers: headers
@@ -2833,10 +2873,10 @@ var AuthManagerImpl = /*#__PURE__*/function () {
2833
2873
  isBytescaleApi: false,
2834
2874
  fetchApi: (_a = params.options) === null || _a === void 0 ? void 0 : _a.fetchApi
2835
2875
  }), function (result) {
2836
- var actualContentType = (_b = result.headers.get(_this14.contentType)) !== null && _b !== void 0 ? _b : "";
2876
+ var actualContentType = (_b = result.headers.get(_this12.contentType)) !== null && _b !== void 0 ? _b : "";
2837
2877
  // Support content types like "text/plain; charset=utf-8" and "text/plain"
2838
2878
  if (actualContentType.split(";")[0] !== requiredContentType) {
2839
- throw new Error("".concat(endpointName, " returned \"").concat(actualContentType, "\" for the ").concat(_this14.contentType, " response header, but the Bytescale SDK requires \"").concat(requiredContentType, "\"."));
2879
+ throw new Error("".concat(endpointName, " returned \"").concat(actualContentType, "\" for the ").concat(_this12.contentType, " response header, but the Bytescale SDK requires \"").concat(requiredContentType, "\"."));
2840
2880
  }
2841
2881
  return AuthManagerBrowser_await(result.text(), function (jwt) {
2842
2882
  if (jwt.length === 0) {
@@ -1,14 +1,9 @@
1
- import { ServiceWorkerConfig } from "./model/ServiceWorkerConfig";
2
- export declare class ServiceWorkerUtils {
3
- /**
4
- * Idempotent.
5
- *
6
- * Only returns once the service worker has been activated.
7
- *
8
- * We don't need to unregister it: we just need to clear the config when auth ends.
9
- */
10
- registerServiceWorkerIfSupported(serviceWorkerScript: string | undefined, configFieldName: string, fallbackMessage: string): Promise<ServiceWorkerConfig | undefined>;
11
- getActiveServiceWorkerElseRegister({ serviceWorkerScope, serviceWorkerScript }: ServiceWorkerConfig): Promise<ServiceWorker>;
1
+ import { ServiceWorkerConfig, ServiceWorkerConfigInitialized } from "./model/ServiceWorkerConfig";
2
+ export declare class ServiceWorkerUtils<TMessage> {
3
+ canUseServiceWorkers(): boolean;
4
+ sendMessage(message: TMessage, config: ServiceWorkerConfig, serviceWorkerScriptFieldName: string): Promise<ServiceWorkerConfigInitialized>;
5
+ private registerServiceWorkerIfSupported;
6
+ private getActiveServiceWorkerElseRegister;
12
7
  /**
13
8
  * Idempotent.
14
9
  *
@@ -17,5 +12,6 @@ export declare class ServiceWorkerUtils {
17
12
  * We don't need to unregister it: we just need to clear the config when auth ends.
18
13
  */
19
14
  private registerAuthServiceWorker;
15
+ private waitForActiveServiceWorker;
20
16
  private getActiveServiceWorker;
21
17
  }
@@ -1,4 +1,9 @@
1
- export interface ServiceWorkerConfig {
1
+ export declare type ServiceWorkerConfig = ServiceWorkerConfigUninitialized | ServiceWorkerConfigInitialized;
2
+ export interface ServiceWorkerConfigUninitialized {
3
+ serviceWorkerScope: undefined;
4
+ serviceWorkerScript: string;
5
+ }
6
+ export interface ServiceWorkerConfigInitialized {
2
7
  serviceWorkerScope: string;
3
8
  serviceWorkerScript: string;
4
9
  }
@@ -0,0 +1,6 @@
1
+ import { ServiceWorkerConfigInitialized } from "./ServiceWorkerConfig";
2
+ export interface ServiceWorkerInitStatus {
3
+ config: ServiceWorkerConfigInitialized;
4
+ messageSent: boolean;
5
+ serviceWorker: ServiceWorker;
6
+ }
@@ -1,8 +1,10 @@
1
1
  import { AuthManagerInterface, BeginAuthSessionParams } from "../../private/model/AuthManagerInterface";
2
+ import { AuthSwSetConfigDto } from "../../private/dtos/AuthSwSetConfigDto";
2
3
  import { ServiceWorkerUtils } from "../../private/ServiceWorkerUtils";
3
4
  declare class AuthManagerImpl implements AuthManagerInterface {
4
5
  private readonly serviceWorkerUtils;
5
6
  private readonly authSessionMutex;
7
+ private readonly serviceWorkerScriptFieldName;
6
8
  private readonly contentType;
7
9
  private readonly contentTypeJson;
8
10
  private readonly contentTypeText;
@@ -10,13 +12,11 @@ declare class AuthManagerImpl implements AuthManagerInterface {
10
12
  private readonly maxJwtTtlSeconds;
11
13
  private readonly retryAuthAfterErrorSeconds;
12
14
  private readonly refreshBeforeExpirySeconds;
13
- constructor(serviceWorkerUtils: ServiceWorkerUtils);
15
+ constructor(serviceWorkerUtils: ServiceWorkerUtils<AuthSwSetConfigDto>);
14
16
  isAuthSessionActive(): boolean;
15
17
  beginAuthSession(params: BeginAuthSessionParams): Promise<void>;
16
18
  endAuthSession(): Promise<void>;
17
19
  private refreshAccessToken;
18
- private isUsingServiceWorker;
19
- private setServiceWorkerConfig;
20
20
  private getAccessTokenUrl;
21
21
  private getCdnUrl;
22
22
  private deleteAccessToken;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytescale/sdk",
3
- "version": "3.18.0",
3
+ "version": "3.19.0",
4
4
  "description": "Bytescale JavaScript SDK",
5
5
  "author": "Bytescale <hello@bytescale.com> (https://www.bytescale.com)",
6
6
  "license": "MIT",