@workos-inc/node 10.10.0 → 10.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.
@@ -1242,7 +1242,8 @@ var Actions = class {
1242
1242
  tolerance
1243
1243
  };
1244
1244
  await this.verifyHeader(options);
1245
- return deserializeAction(typeof payload === "string" || isBinaryPayload(payload) ? JSON.parse(decodePayloadToString(payload)) : payload);
1245
+ const parsed = typeof payload === "string" || isBinaryPayload(payload) ? JSON.parse(decodePayloadToString(payload)) : payload;
1246
+ return deserializeAction(parsed);
1246
1247
  }
1247
1248
  };
1248
1249
  //#endregion
@@ -2057,7 +2058,8 @@ var Webhooks = class {
2057
2058
  tolerance
2058
2059
  };
2059
2060
  await this.verifyHeader(options);
2060
- return deserializeEvent(this.parseVerifiedPayload(payload));
2061
+ const webhookPayload = this.parseVerifiedPayload(payload);
2062
+ return deserializeEvent(webhookPayload);
2061
2063
  }
2062
2064
  parseVerifiedPayload(payload) {
2063
2065
  if (typeof payload === "object" && !isBinaryPayload(payload)) return payload;
@@ -2130,7 +2132,7 @@ let _josePromise;
2130
2132
  * @returns Promise that resolves to the jose module
2131
2133
  */
2132
2134
  function getJose() {
2133
- return _josePromise ??= Promise.resolve().then(() => require("./webapi-BzGFatFp.cjs"));
2135
+ return _josePromise ??= Promise.resolve().then(() => require("./webapi-D3QZrB15.cjs"));
2134
2136
  }
2135
2137
  //#endregion
2136
2138
  //#region src/agents/serializers/agent-registration.serializer.ts
@@ -2348,7 +2350,7 @@ var Agents = class {
2348
2350
  const { clientId } = this.workos;
2349
2351
  if (!clientId) throw new Error("Missing client ID. Did you provide it when initializing WorkOS?");
2350
2352
  const { createRemoteJWKSet } = await getJose();
2351
- this._jwks ??= createRemoteJWKSet(new URL(`${this.workos.baseURL}/sso/jwks/${clientId}`), { cooldownDuration: 1e3 * 60 * 5 });
2353
+ this._jwks ??= createRemoteJWKSet(new URL(`${this.workos.baseURL}/sso/jwks/${clientId}`), { cooldownDuration: 3e5 });
2352
2354
  return this._jwks;
2353
2355
  }
2354
2356
  };
@@ -5037,7 +5039,7 @@ var UserManagement = class {
5037
5039
  async getJWKS() {
5038
5040
  const { createRemoteJWKSet } = await getJose();
5039
5041
  if (!this.clientId) return;
5040
- this._jwks ??= createRemoteJWKSet(new URL(this.getJwksUrl(this.clientId)), { cooldownDuration: 1e3 * 60 * 5 });
5042
+ this._jwks ??= createRemoteJWKSet(new URL(this.getJwksUrl(this.clientId)), { cooldownDuration: 3e5 });
5041
5043
  return this._jwks;
5042
5044
  }
5043
5045
  /**
@@ -5947,31 +5949,91 @@ var InMemoryStore = class {
5947
5949
  };
5948
5950
  //#endregion
5949
5951
  //#region src/feature-flags/evaluator.ts
5952
+ const TARGET_TYPE_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
5953
+ const TARGET_ID_PATTERN = /^[A-Za-z0-9._:-]{1,255}$/;
5954
+ const LEGACY_KEY_TO_TARGET_TYPE = /* @__PURE__ */ new Map([["userId", "user"], ["organizationId", "organization"]]);
5955
+ const isEvaluationResource = (value) => typeof value === "object" && value !== null && "id" in value && typeof value.id === "string";
5950
5956
  var Evaluator = class {
5951
5957
  store;
5952
- constructor(store) {
5958
+ logger;
5959
+ constructor(store, logger) {
5953
5960
  this.store = store;
5961
+ this.logger = logger;
5954
5962
  }
5955
5963
  isEnabled(flagKey, context = {}, defaultValue = false) {
5956
- const entry = this.store.get(flagKey);
5957
- if (!entry) return defaultValue;
5958
- if (!entry.enabled) return false;
5959
- if (context.userId) {
5960
- const userTarget = entry.targets.users.find((t) => t.id === context.userId);
5961
- if (userTarget) return userTarget.enabled;
5962
- }
5963
- if (context.organizationId) {
5964
- const orgTarget = entry.targets.organizations.find((t) => t.id === context.organizationId);
5965
- if (orgTarget) return orgTarget.enabled;
5966
- }
5967
- return entry.default_value;
5964
+ return this.evaluate(this.store.get(flagKey), this.normalizeContext(context), defaultValue);
5968
5965
  }
5969
5966
  getAllFlags(context = {}) {
5967
+ const normalizedContext = this.normalizeContext(context);
5970
5968
  const flags = this.store.getAll();
5971
5969
  const result = {};
5972
- for (const slug of Object.keys(flags)) result[slug] = this.isEnabled(slug, context);
5970
+ for (const slug of Object.keys(flags)) result[slug] = this.evaluate(flags[slug], normalizedContext, false);
5973
5971
  return result;
5974
5972
  }
5973
+ evaluate(entry, normalizedContext, defaultValue) {
5974
+ if (!entry) return defaultValue;
5975
+ if (!entry.enabled) return false;
5976
+ for (const [targetType, targetId] of normalizedContext) if (this.hasEnabledTarget(entry, targetType, targetId)) return true;
5977
+ return entry.default_value;
5978
+ }
5979
+ /**
5980
+ * Reduces either context form to target type → ID pairs. Evaluation must
5981
+ * never throw in application code, so every invalid piece of context
5982
+ * degrades to "matches no targets" with a logged warning instead of an
5983
+ * error.
5984
+ */
5985
+ normalizeContext(context) {
5986
+ const normalized = /* @__PURE__ */ new Map();
5987
+ const record = context;
5988
+ const legacyEntries = [];
5989
+ const typedKeys = [];
5990
+ for (const [key, value] of Object.entries(record)) {
5991
+ if (value === void 0 || value === null) continue;
5992
+ const legacyTargetType = LEGACY_KEY_TO_TARGET_TYPE.get(key);
5993
+ if (legacyTargetType) {
5994
+ if (typeof value === "string" && value !== "") legacyEntries.push([legacyTargetType, value]);
5995
+ continue;
5996
+ }
5997
+ typedKeys.push(key);
5998
+ }
5999
+ const resourceShapedKeys = typedKeys.filter((key) => typeof record[key] === "object");
6000
+ if (legacyEntries.length > 0 && resourceShapedKeys.length > 0) {
6001
+ this.logger?.warn("Evaluation context mixes legacy keys (userId/organizationId) with typed target keys; no targets will match", { keys: Object.keys(record) });
6002
+ return normalized;
6003
+ }
6004
+ if (legacyEntries.length > 0) {
6005
+ for (const [targetType, targetId] of legacyEntries) normalized.set(targetType, targetId);
6006
+ return normalized;
6007
+ }
6008
+ for (const key of typedKeys) {
6009
+ if (!TARGET_TYPE_PATTERN.test(key)) {
6010
+ this.logger?.warn(`Ignoring invalid target type in evaluation context: ${key}`);
6011
+ continue;
6012
+ }
6013
+ const value = record[key];
6014
+ if (!isEvaluationResource(value)) {
6015
+ this.logger?.warn(`Ignoring target type with a missing or invalid resource id in evaluation context: ${key}`);
6016
+ continue;
6017
+ }
6018
+ const { id } = value;
6019
+ if (!TARGET_ID_PATTERN.test(id) || id === "." || id === "..") {
6020
+ this.logger?.warn(`Ignoring invalid target id in evaluation context for type: ${key}`);
6021
+ continue;
6022
+ }
6023
+ normalized.set(key, id);
6024
+ }
6025
+ return normalized;
6026
+ }
6027
+ /**
6028
+ * A target participates in evaluation only while its `enabled` is true. A
6029
+ * `false` value is reserved for future disabled overrides and is treated
6030
+ * as if the target were absent.
6031
+ */
6032
+ hasEnabledTarget(entry, targetType, targetId) {
6033
+ if (targetType === "user") return entry.targets.users.some((t) => t.id === targetId && t.enabled);
6034
+ if (targetType === "organization") return entry.targets.organizations.some((t) => t.id === targetId && t.enabled);
6035
+ return (entry.targets.custom_targets ?? []).some((t) => t.type === targetType && t.id === targetId && t.enabled);
6036
+ }
5975
6037
  };
5976
6038
  //#endregion
5977
6039
  //#region src/feature-flags/runtime-client.ts
@@ -6013,7 +6075,7 @@ var FeatureFlagsRuntimeClient = class extends EventEmitter {
6013
6075
  this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
6014
6076
  this.logger = options.logger;
6015
6077
  this.store = new InMemoryStore();
6016
- this.evaluator = new Evaluator(this.store);
6078
+ this.evaluator = new Evaluator(this.store, this.logger);
6017
6079
  this.readyPromise = new Promise((resolve, reject) => {
6018
6080
  this.readyResolve = resolve;
6019
6081
  this.readyReject = reject;
@@ -6158,7 +6220,12 @@ var FeatureFlagsRuntimeClient = class extends EventEmitter {
6158
6220
  const map = new Map(ys.map((t) => [t.id, t.enabled]));
6159
6221
  return xs.some((t) => map.get(t.id) !== t.enabled);
6160
6222
  };
6161
- return targetsChanged(a.targets.users, b.targets.users) || targetsChanged(a.targets.organizations, b.targets.organizations);
6223
+ const customTargetsChanged = (xs, ys) => {
6224
+ if (xs.length !== ys.length) return true;
6225
+ const map = new Map(ys.map((t) => [`${t.type}:${t.id}`, t.enabled]));
6226
+ return xs.some((t) => map.get(`${t.type}:${t.id}`) !== t.enabled);
6227
+ };
6228
+ return targetsChanged(a.targets.users, b.targets.users) || targetsChanged(a.targets.organizations, b.targets.organizations) || customTargetsChanged(a.targets.custom_targets ?? [], b.targets.custom_targets ?? []);
6162
6229
  }
6163
6230
  };
6164
6231
  //#endregion
@@ -8071,7 +8138,7 @@ var Vault = class {
8071
8138
  };
8072
8139
  //#endregion
8073
8140
  //#region package.json
8074
- var version = "10.10.0";
8141
+ var version = "10.11.0";
8075
8142
  //#endregion
8076
8143
  //#region src/workos.ts
8077
8144
  const DEFAULT_HOSTNAME = "api.workos.com";
@@ -8608,4 +8675,4 @@ Object.defineProperty(exports, "serializeRevokeSessionOptions", {
8608
8675
  }
8609
8676
  });
8610
8677
 
8611
- //# sourceMappingURL=factory-CrK6SPfn.cjs.map
8678
+ //# sourceMappingURL=factory-JdOhqH28.cjs.map