flagmint-js-sdk 2.2.1 → 2.2.2

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.
@@ -39095,7 +39095,7 @@ var __publicField = (obj, key, value) => {
39095
39095
  this.connectPromise = new Promise((resolve, reject) => {
39096
39096
  this.connectResolve = resolve;
39097
39097
  this.connectReject = reject;
39098
- const sdkVersion = "2.2.1";
39098
+ const sdkVersion = "2.2.2";
39099
39099
  const platform2 = typeof window !== "undefined" ? "browser" : "nodejs";
39100
39100
  const wrapperName = this.configOptions?.wrapper?.name || "native-js";
39101
39101
  const wrapperVersion = this.configOptions?.wrapper?.version || "none";
@@ -41781,7 +41781,7 @@ var __publicField = (obj, key, value) => {
41781
41781
  const hkdf = (hash2, ikm, salt, info, length) => expand(hash2, extract(hash2, ikm, salt), info, length);
41782
41782
  const ASL_HKDF_INFO = "flagmint-asl-config-sync-mac-v1";
41783
41783
  const ASL_KEY_AGREEMENT = "x25519-hkdf-sha256";
41784
- const textEncoder$1 = new TextEncoder();
41784
+ const textEncoder$2 = new TextEncoder();
41785
41785
  function generateAslClientKeyPair() {
41786
41786
  const privateKey = x25519.utils.randomSecretKey();
41787
41787
  const publicKey = x25519.getPublicKey(privateKey);
@@ -41812,7 +41812,7 @@ var __publicField = (obj, key, value) => {
41812
41812
  sha256,
41813
41813
  shared,
41814
41814
  salt,
41815
- textEncoder$1.encode(ASL_HKDF_INFO),
41815
+ textEncoder$2.encode(ASL_HKDF_INFO),
41816
41816
  32
41817
41817
  );
41818
41818
  return { configMacKey };
@@ -41822,7 +41822,7 @@ var __publicField = (obj, key, value) => {
41822
41822
  return;
41823
41823
  key2.fill(0);
41824
41824
  }
41825
- const textEncoder = new TextEncoder();
41825
+ const textEncoder$1 = new TextEncoder();
41826
41826
  function canonicalizeForSigning(value) {
41827
41827
  return JSON.stringify(sortValue(value));
41828
41828
  }
@@ -41839,12 +41839,12 @@ var __publicField = (obj, key, value) => {
41839
41839
  return sorted;
41840
41840
  }
41841
41841
  function normalizeMacKey(secret) {
41842
- return typeof secret === "string" ? textEncoder.encode(secret) : secret;
41842
+ return typeof secret === "string" ? textEncoder$1.encode(secret) : secret;
41843
41843
  }
41844
41844
  function signConfigPayload(body, secret) {
41845
41845
  const { signature: _ignored, ...unsigned } = body;
41846
41846
  const canonical = canonicalizeForSigning(unsigned);
41847
- const mac = hmac(sha256, normalizeMacKey(secret), textEncoder.encode(canonical));
41847
+ const mac = hmac(sha256, normalizeMacKey(secret), textEncoder$1.encode(canonical));
41848
41848
  return bytesToHex$1(mac);
41849
41849
  }
41850
41850
  function timingSafeEqualBytes(a, b) {
@@ -41866,13 +41866,107 @@ var __publicField = (obj, key, value) => {
41866
41866
  } catch {
41867
41867
  return false;
41868
41868
  }
41869
- const a = textEncoder.encode(body.signature);
41870
- const b = textEncoder.encode(expected);
41869
+ const a = textEncoder$1.encode(body.signature);
41870
+ const b = textEncoder$1.encode(expected);
41871
41871
  return timingSafeEqualBytes(a, b);
41872
41872
  }
41873
41873
  function isConfigPayloadExpired(expiresAt, now = Date.now()) {
41874
41874
  return !Number.isFinite(expiresAt) || now >= expiresAt;
41875
41875
  }
41876
+ const PII_VALUE_ENCODING = "hmac-v1";
41877
+ const textEncoder = new TextEncoder();
41878
+ function normalizePiiString(value) {
41879
+ return value.trim().toLowerCase();
41880
+ }
41881
+ function hashPiiValue(value, salt) {
41882
+ const mac = hmac(
41883
+ sha256,
41884
+ textEncoder.encode(salt),
41885
+ textEncoder.encode(normalizePiiString(value))
41886
+ );
41887
+ return bytesToHex$1(mac);
41888
+ }
41889
+ function isPiiAttribute(attribute, piiAttributes) {
41890
+ if (!attribute || piiAttributes.length === 0)
41891
+ return false;
41892
+ const attr = attribute.trim();
41893
+ if (!attr)
41894
+ return false;
41895
+ for (const key2 of piiAttributes) {
41896
+ if (!key2)
41897
+ continue;
41898
+ if (attr === key2)
41899
+ return true;
41900
+ if (attr.endsWith(`.${key2}`))
41901
+ return true;
41902
+ }
41903
+ return false;
41904
+ }
41905
+ function payloadHasExplicitPiiFields(payload) {
41906
+ if (!payload)
41907
+ return false;
41908
+ return payload.piiSalt !== void 0 || payload.piiAttributes !== void 0 || payload.piiValueEncoding !== void 0;
41909
+ }
41910
+ function piiWireOptionsFromPayload(payload) {
41911
+ if (!payload)
41912
+ return null;
41913
+ const salt = typeof payload.piiSalt === "string" ? payload.piiSalt : "";
41914
+ if (!salt)
41915
+ return null;
41916
+ const encoding = typeof payload.piiValueEncoding === "string" ? payload.piiValueEncoding : PII_VALUE_ENCODING;
41917
+ if (encoding !== PII_VALUE_ENCODING)
41918
+ return null;
41919
+ const attrs = Array.isArray(payload.piiAttributes) ? payload.piiAttributes.filter((k) => typeof k === "string") : [];
41920
+ return {
41921
+ piiAttributes: attrs,
41922
+ piiSalt: salt,
41923
+ piiValueEncoding: PII_VALUE_ENCODING
41924
+ };
41925
+ }
41926
+ function resolvePiiWireForDelta(previous, action) {
41927
+ if (!payloadHasExplicitPiiFields(action)) {
41928
+ return previous;
41929
+ }
41930
+ const merged = {
41931
+ piiSalt: action.piiSalt !== void 0 ? action.piiSalt : previous?.piiSalt,
41932
+ piiAttributes: action.piiAttributes !== void 0 ? action.piiAttributes : previous?.piiAttributes,
41933
+ piiValueEncoding: action.piiValueEncoding !== void 0 ? action.piiValueEncoding : previous?.piiValueEncoding
41934
+ };
41935
+ return piiWireOptionsFromPayload(merged);
41936
+ }
41937
+ function applyPiiHashToFlatContext(context, options, mode) {
41938
+ if (!options || !options.piiSalt || !options.piiAttributes.length || options.piiValueEncoding !== PII_VALUE_ENCODING) {
41939
+ return context;
41940
+ }
41941
+ if (mode?.alreadyHashed) {
41942
+ return context;
41943
+ }
41944
+ let changed = false;
41945
+ const out = { ...context };
41946
+ for (const [key2, value] of Object.entries(context)) {
41947
+ if (!isPiiAttribute(key2, options.piiAttributes))
41948
+ continue;
41949
+ if (typeof value === "string") {
41950
+ out[key2] = hashPiiValue(value, options.piiSalt);
41951
+ changed = true;
41952
+ continue;
41953
+ }
41954
+ if (Array.isArray(value)) {
41955
+ let arrayChanged = false;
41956
+ const next = value.map((entry) => {
41957
+ if (typeof entry !== "string")
41958
+ return entry;
41959
+ arrayChanged = true;
41960
+ return hashPiiValue(entry, options.piiSalt);
41961
+ });
41962
+ if (arrayChanged) {
41963
+ out[key2] = next;
41964
+ changed = true;
41965
+ }
41966
+ }
41967
+ }
41968
+ return changed ? out : context;
41969
+ }
41876
41970
  function createEmptyRulesState() {
41877
41971
  return {
41878
41972
  version: 0,
@@ -41880,7 +41974,8 @@ var __publicField = (obj, key, value) => {
41880
41974
  flags: /* @__PURE__ */ new Map(),
41881
41975
  segments: /* @__PURE__ */ new Map(),
41882
41976
  ready: false,
41883
- needsFullConfig: true
41977
+ needsFullConfig: true,
41978
+ piiWire: null
41884
41979
  };
41885
41980
  }
41886
41981
  function cloneState(state) {
@@ -41890,7 +41985,12 @@ var __publicField = (obj, key, value) => {
41890
41985
  flags: new Map(state.flags),
41891
41986
  segments: new Map(state.segments),
41892
41987
  ready: state.ready,
41893
- needsFullConfig: state.needsFullConfig
41988
+ needsFullConfig: state.needsFullConfig,
41989
+ piiWire: state.piiWire ? {
41990
+ piiAttributes: [...state.piiWire.piiAttributes],
41991
+ piiSalt: state.piiWire.piiSalt,
41992
+ piiValueEncoding: state.piiWire.piiValueEncoding
41993
+ } : null
41894
41994
  };
41895
41995
  }
41896
41996
  function segmentsFromRecord(record) {
@@ -41923,7 +42023,8 @@ var __publicField = (obj, key, value) => {
41923
42023
  flags,
41924
42024
  segments: segmentsFromRecord(action.segments),
41925
42025
  ready: true,
41926
- needsFullConfig: false
42026
+ needsFullConfig: false,
42027
+ piiWire: piiWireOptionsFromPayload(action)
41927
42028
  };
41928
42029
  }
41929
42030
  function applyPatch(state, action) {
@@ -41935,13 +42036,15 @@ var __publicField = (obj, key, value) => {
41935
42036
  if (flag?.key)
41936
42037
  flags.set(flag.key, flag);
41937
42038
  }
42039
+ const nextPii = resolvePiiWireForDelta(state.piiWire, action);
41938
42040
  return {
41939
42041
  version: action.toVersion,
41940
42042
  expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : state.expiresAt,
41941
42043
  flags,
41942
42044
  segments: applySegmentUpserts(state.segments, action.segments),
41943
42045
  ready: true,
41944
- needsFullConfig: false
42046
+ needsFullConfig: false,
42047
+ piiWire: nextPii
41945
42048
  };
41946
42049
  }
41947
42050
  function reduceRules(state, action, now = Date.now()) {
@@ -42118,11 +42221,17 @@ var __publicField = (obj, key, value) => {
42118
42221
  this.state.segments.forEach((segment, id) => {
42119
42222
  segments[id] = segment;
42120
42223
  });
42224
+ const pii = this.state.piiWire;
42121
42225
  return {
42122
42226
  version: this.state.version,
42123
42227
  expiresAt: this.state.expiresAt,
42124
42228
  flags: Array.from(this.state.flags.values()),
42125
- segments
42229
+ segments,
42230
+ ...pii ? {
42231
+ piiAttributes: [...pii.piiAttributes],
42232
+ piiSalt: pii.piiSalt,
42233
+ piiValueEncoding: pii.piiValueEncoding
42234
+ } : {}
42126
42235
  };
42127
42236
  }
42128
42237
  hydrateFromSnapshot(snapshot, now = Date.now()) {
@@ -42138,7 +42247,8 @@ var __publicField = (obj, key, value) => {
42138
42247
  flags,
42139
42248
  segments: segmentsFromRecord(snapshot.segments),
42140
42249
  ready: !expired && flags.size > 0,
42141
- needsFullConfig: expired || flags.size === 0
42250
+ needsFullConfig: expired || flags.size === 0,
42251
+ piiWire: piiWireOptionsFromPayload(snapshot)
42142
42252
  };
42143
42253
  }
42144
42254
  }
@@ -42340,7 +42450,7 @@ var __publicField = (obj, key, value) => {
42340
42450
  function toComparableString(value) {
42341
42451
  if (value === null || value === void 0)
42342
42452
  return "";
42343
- return String(value);
42453
+ return String(value).trim().toLowerCase();
42344
42454
  }
42345
42455
  function toComparableArray(value) {
42346
42456
  if (Array.isArray(value)) {
@@ -42902,8 +43012,13 @@ var __publicField = (obj, key, value) => {
42902
43012
  }
42903
43013
  return context;
42904
43014
  }
42905
- function evaluateSdkFlag(flag, context, segments) {
42906
- const evalContext = prepareContextForEvaluator(context);
43015
+ function prepareContextForLocalEval(context, pii) {
43016
+ const prepared = prepareContextForEvaluator(context);
43017
+ const flat = flattenEvaluationContext(prepared);
43018
+ return applyPiiHashToFlatContext(flat, pii);
43019
+ }
43020
+ function evaluateSdkFlag(flag, context, segments, pii) {
43021
+ const evalContext = prepareContextForLocalEval(context, pii);
42907
43022
  const variationsById = {};
42908
43023
  for (const v of flag.variations || []) {
42909
43024
  if (v?.id)
@@ -42963,7 +43078,7 @@ var __publicField = (obj, key, value) => {
42963
43078
  }
42964
43079
  function evaluateAllSdkFlags(flags, context, segments, options) {
42965
43080
  const list = flags instanceof Map ? Array.from(flags.values()) : flags;
42966
- const prepared = prepareContextForEvaluator(context);
43081
+ const prepared = prepareContextForLocalEval(context, options?.pii);
42967
43082
  const out = {};
42968
43083
  for (const flag of list) {
42969
43084
  if (!flag?.key)
@@ -42972,7 +43087,7 @@ var __publicField = (obj, key, value) => {
42972
43087
  out[flag.key] = coerceType(flag.default_value, flag.type);
42973
43088
  continue;
42974
43089
  }
42975
- out[flag.key] = evaluateSdkFlag(flag, prepared, segments);
43090
+ out[flag.key] = evaluateSdkFlag(flag, prepared, segments, null);
42976
43091
  }
42977
43092
  return out;
42978
43093
  }
@@ -43417,7 +43532,8 @@ var __publicField = (obj, key, value) => {
43417
43532
  value = evaluateSdkFlag(
43418
43533
  flag,
43419
43534
  this.context,
43420
- this.rulesStore.getState().segments
43535
+ this.rulesStore.getState().segments,
43536
+ this.rulesStore.getState().piiWire
43421
43537
  ) ?? fallback;
43422
43538
  }
43423
43539
  } else {
@@ -43897,7 +44013,7 @@ var __publicField = (obj, key, value) => {
43897
44013
  state.flags,
43898
44014
  context ?? this.context,
43899
44015
  state.segments,
43900
- { failClosedDefaultsOnly: failClosed }
44016
+ { failClosedDefaultsOnly: failClosed, pii: state.piiWire }
43901
44017
  );
43902
44018
  }
43903
44019
  analyticsMapFromRulesStore() {
@@ -44026,6 +44142,7 @@ var __publicField = (obj, key, value) => {
44026
44142
  exports2.LongPollingTransport = LongPollingTransport;
44027
44143
  exports2.RulesStore = RulesStore;
44028
44144
  exports2.SseTransport = SseTransport;
44145
+ exports2.applyPiiHashToFlatContext = applyPiiHashToFlatContext;
44029
44146
  exports2.applyRolloutStrategy = applyRolloutStrategy;
44030
44147
  exports2.asyncCache = cacheHelper_async;
44031
44148
  exports2.canonicalizeForSigning = canonicalizeForSigning;
@@ -44043,11 +44160,13 @@ var __publicField = (obj, key, value) => {
44043
44160
  exports2.flattenEvaluationContext = flattenEvaluationContext;
44044
44161
  exports2.generateAslClientKeyPair = generateAslClientKeyPair;
44045
44162
  exports2.hashPercent = hashPercent;
44163
+ exports2.hashPiiValue = hashPiiValue;
44046
44164
  exports2.hashToPercentage = hashToPercentage;
44047
44165
  exports2.isConfigPayloadExpired = isConfigPayloadExpired;
44048
44166
  exports2.isInSegment = isInSegment;
44049
44167
  exports2.performAslHandshake = performAslHandshake;
44050
44168
  exports2.pickVariant = pickVariant;
44169
+ exports2.prepareContextForLocalEval = prepareContextForLocalEval;
44051
44170
  exports2.reduceRules = reduceRules;
44052
44171
  exports2.signConfigPayload = signConfigPayload;
44053
44172
  exports2.stringHash = stringHash;