@workos-inc/node 8.10.0 → 8.11.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.
@@ -1,3 +1,4 @@
1
+ let node_events = require("node:events");
1
2
  //#region src/common/crypto/crypto-provider.ts
2
3
  /**
3
4
  * Interface encapsulating the various crypto computations used by the library,
@@ -2794,7 +2795,7 @@ let _josePromise;
2794
2795
  * @returns Promise that resolves to the jose module
2795
2796
  */
2796
2797
  function getJose() {
2797
- return _josePromise ??= Promise.resolve().then(() => require("./webapi-Dk3R7830.cjs"));
2798
+ return _josePromise ??= Promise.resolve().then(() => require("./webapi-N7c2LUJd.cjs"));
2798
2799
  }
2799
2800
  //#endregion
2800
2801
  //#region src/user-management/session.ts
@@ -3720,6 +3721,236 @@ var FGA = class {
3720
3721
  }
3721
3722
  };
3722
3723
  //#endregion
3724
+ //#region src/feature-flags/in-memory-store.ts
3725
+ var InMemoryStore = class {
3726
+ flags = {};
3727
+ swap(newFlags) {
3728
+ this.flags = { ...newFlags };
3729
+ }
3730
+ get(slug) {
3731
+ return this.flags[slug];
3732
+ }
3733
+ getAll() {
3734
+ return { ...this.flags };
3735
+ }
3736
+ get size() {
3737
+ return Object.keys(this.flags).length;
3738
+ }
3739
+ };
3740
+ //#endregion
3741
+ //#region src/feature-flags/evaluator.ts
3742
+ var Evaluator = class {
3743
+ constructor(store) {
3744
+ this.store = store;
3745
+ }
3746
+ isEnabled(flagKey, context = {}, defaultValue = false) {
3747
+ const entry = this.store.get(flagKey);
3748
+ if (!entry) return defaultValue;
3749
+ if (!entry.enabled) return false;
3750
+ if (context.userId) {
3751
+ const userTarget = entry.targets.users.find((t) => t.id === context.userId);
3752
+ if (userTarget) return userTarget.enabled;
3753
+ }
3754
+ if (context.organizationId) {
3755
+ const orgTarget = entry.targets.organizations.find((t) => t.id === context.organizationId);
3756
+ if (orgTarget) return orgTarget.enabled;
3757
+ }
3758
+ return entry.default_value;
3759
+ }
3760
+ getAllFlags(context = {}) {
3761
+ const flags = this.store.getAll();
3762
+ const result = {};
3763
+ for (const slug of Object.keys(flags)) result[slug] = this.isEnabled(slug, context);
3764
+ return result;
3765
+ }
3766
+ };
3767
+ //#endregion
3768
+ //#region src/feature-flags/runtime-client.ts
3769
+ const DEFAULT_POLLING_INTERVAL_MS = 3e4;
3770
+ const MIN_POLLING_INTERVAL_MS = 5e3;
3771
+ const MIN_DELAY_MS = 1e3;
3772
+ const DEFAULT_REQUEST_TIMEOUT_MS = 1e4;
3773
+ const JITTER_FACTOR = .1;
3774
+ const INITIAL_RETRY_MS = 1e3;
3775
+ const MAX_RETRY_MS = 6e4;
3776
+ const BACKOFF_MULTIPLIER = 2;
3777
+ var FeatureFlagsRuntimeClient = class extends node_events.EventEmitter {
3778
+ store;
3779
+ evaluator;
3780
+ pollingIntervalMs;
3781
+ requestTimeoutMs;
3782
+ logger;
3783
+ closed = false;
3784
+ initialized = false;
3785
+ consecutiveErrors = 0;
3786
+ pollTimer = null;
3787
+ pollAbortController = null;
3788
+ readyResolve = null;
3789
+ readyReject = null;
3790
+ readyPromise;
3791
+ stats = {
3792
+ pollCount: 0,
3793
+ pollErrorCount: 0,
3794
+ lastPollAt: null,
3795
+ lastSuccessfulPollAt: null,
3796
+ cacheAge: null,
3797
+ flagCount: 0
3798
+ };
3799
+ constructor(workos, options = {}) {
3800
+ super();
3801
+ this.workos = workos;
3802
+ this.pollingIntervalMs = Math.max(MIN_POLLING_INTERVAL_MS, options.pollingIntervalMs ?? DEFAULT_POLLING_INTERVAL_MS);
3803
+ this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
3804
+ this.logger = options.logger;
3805
+ this.store = new InMemoryStore();
3806
+ this.evaluator = new Evaluator(this.store);
3807
+ this.readyPromise = new Promise((resolve, reject) => {
3808
+ this.readyResolve = resolve;
3809
+ this.readyReject = reject;
3810
+ });
3811
+ this.readyPromise.catch(() => {});
3812
+ if (options.bootstrapFlags) {
3813
+ this.store.swap(options.bootstrapFlags);
3814
+ this.stats.flagCount = this.store.size;
3815
+ this.resolveReady();
3816
+ }
3817
+ setTimeout(() => this.poll(), 0);
3818
+ }
3819
+ async waitUntilReady(options) {
3820
+ if (!options?.timeoutMs) return this.readyPromise;
3821
+ let timeoutId;
3822
+ const timeoutPromise = new Promise((_, reject) => {
3823
+ timeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error("waitUntilReady timed out")), options.timeoutMs);
3824
+ });
3825
+ timeoutPromise.catch(() => {});
3826
+ return Promise.race([this.readyPromise, timeoutPromise]).finally(() => {
3827
+ clearTimeout(timeoutId);
3828
+ });
3829
+ }
3830
+ close() {
3831
+ this.closed = true;
3832
+ this.pollAbortController?.abort();
3833
+ if (this.pollTimer) {
3834
+ clearTimeout(this.pollTimer);
3835
+ this.pollTimer = null;
3836
+ }
3837
+ this.removeAllListeners();
3838
+ }
3839
+ isEnabled(flagKey, context, defaultValue) {
3840
+ return this.evaluator.isEnabled(flagKey, context, defaultValue);
3841
+ }
3842
+ getAllFlags(context) {
3843
+ return this.evaluator.getAllFlags(context);
3844
+ }
3845
+ getFlag(flagKey) {
3846
+ return this.store.get(flagKey);
3847
+ }
3848
+ getStats() {
3849
+ return {
3850
+ ...this.stats,
3851
+ cacheAge: this.stats.lastSuccessfulPollAt ? Date.now() - this.stats.lastSuccessfulPollAt.getTime() : null
3852
+ };
3853
+ }
3854
+ resolveReady() {
3855
+ if (this.readyResolve) {
3856
+ this.readyResolve();
3857
+ this.readyResolve = null;
3858
+ }
3859
+ }
3860
+ async poll() {
3861
+ if (this.closed) return;
3862
+ const previousFlags = this.store.getAll();
3863
+ try {
3864
+ this.stats.pollCount++;
3865
+ this.stats.lastPollAt = /* @__PURE__ */ new Date();
3866
+ const data = await this.fetchWithTimeout();
3867
+ this.store.swap(data);
3868
+ this.stats.lastSuccessfulPollAt = /* @__PURE__ */ new Date();
3869
+ this.stats.flagCount = this.store.size;
3870
+ this.consecutiveErrors = 0;
3871
+ if (this.initialized) this.emitChanges(previousFlags, data);
3872
+ this.initialized = true;
3873
+ this.resolveReady();
3874
+ this.logger?.debug("Poll successful", { flagCount: this.store.size });
3875
+ } catch (error) {
3876
+ if (this.closed) return;
3877
+ this.consecutiveErrors++;
3878
+ this.stats.pollErrorCount++;
3879
+ this.emit("error", error);
3880
+ this.logger?.error("Poll failed", error);
3881
+ if (error instanceof UnauthorizedException) {
3882
+ this.emit("failed", error);
3883
+ if (!this.initialized && this.readyReject) {
3884
+ this.readyReject(error);
3885
+ this.readyReject = null;
3886
+ }
3887
+ return;
3888
+ }
3889
+ }
3890
+ this.scheduleNextPoll();
3891
+ }
3892
+ async fetchWithTimeout() {
3893
+ this.pollAbortController = new AbortController();
3894
+ const { signal } = this.pollAbortController;
3895
+ let timeoutId;
3896
+ const fetchPromise = this.workos.get("/sdk/feature-flags").then(({ data }) => data);
3897
+ const timeoutPromise = new Promise((_, reject) => {
3898
+ timeoutId = setTimeout(() => {
3899
+ this.pollAbortController?.abort();
3900
+ reject(/* @__PURE__ */ new Error("Request timed out"));
3901
+ }, this.requestTimeoutMs);
3902
+ });
3903
+ const abortPromise = new Promise((_, reject) => {
3904
+ if (signal.aborted) {
3905
+ reject(/* @__PURE__ */ new Error("Poll aborted"));
3906
+ return;
3907
+ }
3908
+ signal.addEventListener("abort", () => reject(/* @__PURE__ */ new Error("Poll aborted")), { once: true });
3909
+ });
3910
+ return Promise.race([
3911
+ fetchPromise,
3912
+ timeoutPromise,
3913
+ abortPromise
3914
+ ]).finally(() => {
3915
+ clearTimeout(timeoutId);
3916
+ });
3917
+ }
3918
+ scheduleNextPoll() {
3919
+ if (this.closed) return;
3920
+ let baseDelay = this.pollingIntervalMs;
3921
+ if (this.consecutiveErrors > 0) {
3922
+ const backoff = Math.min(INITIAL_RETRY_MS * Math.pow(BACKOFF_MULTIPLIER, this.consecutiveErrors - 1), MAX_RETRY_MS);
3923
+ baseDelay = Math.max(baseDelay, backoff);
3924
+ }
3925
+ const jitter = 1 + (Math.random() * 2 - 1) * JITTER_FACTOR;
3926
+ const delay = Math.max(MIN_DELAY_MS, baseDelay * jitter);
3927
+ this.pollTimer = setTimeout(() => this.poll(), delay);
3928
+ }
3929
+ emitChanges(previous, current) {
3930
+ if (!previous || !current) return;
3931
+ const allKeys = new Set([...Object.keys(previous), ...Object.keys(current)]);
3932
+ for (const key of allKeys) {
3933
+ const prev = previous[key];
3934
+ const curr = current[key];
3935
+ if (this.hasEntryChanged(prev, curr)) this.emit("change", {
3936
+ key,
3937
+ previous: prev ?? null,
3938
+ current: curr ?? null
3939
+ });
3940
+ }
3941
+ }
3942
+ hasEntryChanged(a, b) {
3943
+ if (!a || !b) return a !== b;
3944
+ if (a.enabled !== b.enabled || a.default_value !== b.default_value) return true;
3945
+ const targetsChanged = (xs, ys) => {
3946
+ if (xs.length !== ys.length) return true;
3947
+ const map = new Map(ys.map((t) => [t.id, t.enabled]));
3948
+ return xs.some((t) => map.get(t.id) !== t.enabled);
3949
+ };
3950
+ return targetsChanged(a.targets.users, b.targets.users) || targetsChanged(a.targets.organizations, b.targets.organizations);
3951
+ }
3952
+ };
3953
+ //#endregion
3723
3954
  //#region src/feature-flags/feature-flags.ts
3724
3955
  var FeatureFlags = class {
3725
3956
  constructor(workos) {
@@ -3748,6 +3979,9 @@ var FeatureFlags = class {
3748
3979
  const { slug, targetId } = options;
3749
3980
  await this.workos.delete(`/feature-flags/${slug}/targets/${targetId}`);
3750
3981
  }
3982
+ createRuntimeClient(options) {
3983
+ return new FeatureFlagsRuntimeClient(this.workos, options);
3984
+ }
3751
3985
  };
3752
3986
  //#endregion
3753
3987
  //#region src/widgets/interfaces/get-token.ts
@@ -4442,7 +4676,7 @@ function extractBunVersionFromUserAgent() {
4442
4676
  }
4443
4677
  //#endregion
4444
4678
  //#region package.json
4445
- var version = "8.10.0";
4679
+ var version = "8.11.0";
4446
4680
  //#endregion
4447
4681
  //#region src/workos.ts
4448
4682
  const DEFAULT_HOSTNAME = "api.workos.com";
@@ -4880,6 +5114,12 @@ Object.defineProperty(exports, "DomainDataState", {
4880
5114
  return DomainDataState;
4881
5115
  }
4882
5116
  });
5117
+ Object.defineProperty(exports, "FeatureFlagsRuntimeClient", {
5118
+ enumerable: true,
5119
+ get: function() {
5120
+ return FeatureFlagsRuntimeClient;
5121
+ }
5122
+ });
4883
5123
  Object.defineProperty(exports, "FetchHttpClient", {
4884
5124
  enumerable: true,
4885
5125
  get: function() {
@@ -5007,4 +5247,4 @@ Object.defineProperty(exports, "serializeRevokeSessionOptions", {
5007
5247
  }
5008
5248
  });
5009
5249
 
5010
- //# sourceMappingURL=factory-DwdIHLNE.cjs.map
5250
+ //# sourceMappingURL=factory-CFeJhRhj.cjs.map