flagmint-js-sdk 2.2.1 → 2.2.2-rc.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.
@@ -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-rc.0";
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,93 @@ 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
+ const HASH_HEX_PATTERN = /^[0-9a-f]{64}$/;
41879
+ function normalizePiiString(value) {
41880
+ return value.trim().toLowerCase();
41881
+ }
41882
+ function hashPiiValue(value, salt) {
41883
+ const mac = hmac(
41884
+ sha256,
41885
+ textEncoder.encode(salt),
41886
+ textEncoder.encode(normalizePiiString(value))
41887
+ );
41888
+ return bytesToHex$1(mac);
41889
+ }
41890
+ function isPiiAttribute(attribute, piiAttributes) {
41891
+ if (!attribute || piiAttributes.length === 0)
41892
+ return false;
41893
+ const attr = attribute.trim();
41894
+ if (!attr)
41895
+ return false;
41896
+ for (const key2 of piiAttributes) {
41897
+ if (!key2)
41898
+ continue;
41899
+ if (attr === key2)
41900
+ return true;
41901
+ if (attr.endsWith(`.${key2}`))
41902
+ return true;
41903
+ }
41904
+ return false;
41905
+ }
41906
+ function piiWireOptionsFromPayload(payload) {
41907
+ if (!payload)
41908
+ return null;
41909
+ const salt = typeof payload.piiSalt === "string" ? payload.piiSalt : "";
41910
+ if (!salt)
41911
+ return null;
41912
+ const encoding = typeof payload.piiValueEncoding === "string" ? payload.piiValueEncoding : PII_VALUE_ENCODING;
41913
+ if (encoding !== PII_VALUE_ENCODING)
41914
+ return null;
41915
+ const attrs = Array.isArray(payload.piiAttributes) ? payload.piiAttributes.filter((k) => typeof k === "string") : [];
41916
+ return {
41917
+ piiAttributes: attrs,
41918
+ piiSalt: salt,
41919
+ piiValueEncoding: PII_VALUE_ENCODING
41920
+ };
41921
+ }
41922
+ function applyPiiHashToFlatContext(context, options) {
41923
+ if (!options || !options.piiSalt || !options.piiAttributes.length || options.piiValueEncoding !== PII_VALUE_ENCODING) {
41924
+ return context;
41925
+ }
41926
+ let changed = false;
41927
+ const out = { ...context };
41928
+ for (const [key2, value] of Object.entries(context)) {
41929
+ if (!isPiiAttribute(key2, options.piiAttributes))
41930
+ continue;
41931
+ if (typeof value === "string") {
41932
+ if (HASH_HEX_PATTERN.test(value))
41933
+ continue;
41934
+ out[key2] = hashPiiValue(value, options.piiSalt);
41935
+ changed = true;
41936
+ continue;
41937
+ }
41938
+ if (Array.isArray(value)) {
41939
+ let arrayChanged = false;
41940
+ const next = value.map((entry) => {
41941
+ if (typeof entry !== "string")
41942
+ return entry;
41943
+ if (HASH_HEX_PATTERN.test(entry))
41944
+ return entry;
41945
+ arrayChanged = true;
41946
+ return hashPiiValue(entry, options.piiSalt);
41947
+ });
41948
+ if (arrayChanged) {
41949
+ out[key2] = next;
41950
+ changed = true;
41951
+ }
41952
+ }
41953
+ }
41954
+ return changed ? out : context;
41955
+ }
41876
41956
  function createEmptyRulesState() {
41877
41957
  return {
41878
41958
  version: 0,
@@ -41880,7 +41960,8 @@ var __publicField = (obj, key, value) => {
41880
41960
  flags: /* @__PURE__ */ new Map(),
41881
41961
  segments: /* @__PURE__ */ new Map(),
41882
41962
  ready: false,
41883
- needsFullConfig: true
41963
+ needsFullConfig: true,
41964
+ piiWire: null
41884
41965
  };
41885
41966
  }
41886
41967
  function cloneState(state) {
@@ -41890,7 +41971,12 @@ var __publicField = (obj, key, value) => {
41890
41971
  flags: new Map(state.flags),
41891
41972
  segments: new Map(state.segments),
41892
41973
  ready: state.ready,
41893
- needsFullConfig: state.needsFullConfig
41974
+ needsFullConfig: state.needsFullConfig,
41975
+ piiWire: state.piiWire ? {
41976
+ piiAttributes: [...state.piiWire.piiAttributes],
41977
+ piiSalt: state.piiWire.piiSalt,
41978
+ piiValueEncoding: state.piiWire.piiValueEncoding
41979
+ } : null
41894
41980
  };
41895
41981
  }
41896
41982
  function segmentsFromRecord(record) {
@@ -41923,7 +42009,8 @@ var __publicField = (obj, key, value) => {
41923
42009
  flags,
41924
42010
  segments: segmentsFromRecord(action.segments),
41925
42011
  ready: true,
41926
- needsFullConfig: false
42012
+ needsFullConfig: false,
42013
+ piiWire: piiWireOptionsFromPayload(action)
41927
42014
  };
41928
42015
  }
41929
42016
  function applyPatch(state, action) {
@@ -41935,13 +42022,15 @@ var __publicField = (obj, key, value) => {
41935
42022
  if (flag?.key)
41936
42023
  flags.set(flag.key, flag);
41937
42024
  }
42025
+ const nextPii = piiWireOptionsFromPayload(action) ?? state.piiWire;
41938
42026
  return {
41939
42027
  version: action.toVersion,
41940
42028
  expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : state.expiresAt,
41941
42029
  flags,
41942
42030
  segments: applySegmentUpserts(state.segments, action.segments),
41943
42031
  ready: true,
41944
- needsFullConfig: false
42032
+ needsFullConfig: false,
42033
+ piiWire: nextPii
41945
42034
  };
41946
42035
  }
41947
42036
  function reduceRules(state, action, now = Date.now()) {
@@ -42118,11 +42207,17 @@ var __publicField = (obj, key, value) => {
42118
42207
  this.state.segments.forEach((segment, id) => {
42119
42208
  segments[id] = segment;
42120
42209
  });
42210
+ const pii = this.state.piiWire;
42121
42211
  return {
42122
42212
  version: this.state.version,
42123
42213
  expiresAt: this.state.expiresAt,
42124
42214
  flags: Array.from(this.state.flags.values()),
42125
- segments
42215
+ segments,
42216
+ ...pii ? {
42217
+ piiAttributes: [...pii.piiAttributes],
42218
+ piiSalt: pii.piiSalt,
42219
+ piiValueEncoding: pii.piiValueEncoding
42220
+ } : {}
42126
42221
  };
42127
42222
  }
42128
42223
  hydrateFromSnapshot(snapshot, now = Date.now()) {
@@ -42138,7 +42233,8 @@ var __publicField = (obj, key, value) => {
42138
42233
  flags,
42139
42234
  segments: segmentsFromRecord(snapshot.segments),
42140
42235
  ready: !expired && flags.size > 0,
42141
- needsFullConfig: expired || flags.size === 0
42236
+ needsFullConfig: expired || flags.size === 0,
42237
+ piiWire: piiWireOptionsFromPayload(snapshot)
42142
42238
  };
42143
42239
  }
42144
42240
  }
@@ -42902,8 +42998,13 @@ var __publicField = (obj, key, value) => {
42902
42998
  }
42903
42999
  return context;
42904
43000
  }
42905
- function evaluateSdkFlag(flag, context, segments) {
42906
- const evalContext = prepareContextForEvaluator(context);
43001
+ function prepareContextForLocalEval(context, pii) {
43002
+ const prepared = prepareContextForEvaluator(context);
43003
+ const flat = flattenEvaluationContext(prepared);
43004
+ return applyPiiHashToFlatContext(flat, pii);
43005
+ }
43006
+ function evaluateSdkFlag(flag, context, segments, pii) {
43007
+ const evalContext = prepareContextForLocalEval(context, pii);
42907
43008
  const variationsById = {};
42908
43009
  for (const v of flag.variations || []) {
42909
43010
  if (v?.id)
@@ -42963,7 +43064,7 @@ var __publicField = (obj, key, value) => {
42963
43064
  }
42964
43065
  function evaluateAllSdkFlags(flags, context, segments, options) {
42965
43066
  const list = flags instanceof Map ? Array.from(flags.values()) : flags;
42966
- const prepared = prepareContextForEvaluator(context);
43067
+ const prepared = prepareContextForLocalEval(context, options?.pii);
42967
43068
  const out = {};
42968
43069
  for (const flag of list) {
42969
43070
  if (!flag?.key)
@@ -42972,7 +43073,7 @@ var __publicField = (obj, key, value) => {
42972
43073
  out[flag.key] = coerceType(flag.default_value, flag.type);
42973
43074
  continue;
42974
43075
  }
42975
- out[flag.key] = evaluateSdkFlag(flag, prepared, segments);
43076
+ out[flag.key] = evaluateSdkFlag(flag, prepared, segments, null);
42976
43077
  }
42977
43078
  return out;
42978
43079
  }
@@ -43417,7 +43518,8 @@ var __publicField = (obj, key, value) => {
43417
43518
  value = evaluateSdkFlag(
43418
43519
  flag,
43419
43520
  this.context,
43420
- this.rulesStore.getState().segments
43521
+ this.rulesStore.getState().segments,
43522
+ this.rulesStore.getState().piiWire
43421
43523
  ) ?? fallback;
43422
43524
  }
43423
43525
  } else {
@@ -43897,7 +43999,7 @@ var __publicField = (obj, key, value) => {
43897
43999
  state.flags,
43898
44000
  context ?? this.context,
43899
44001
  state.segments,
43900
- { failClosedDefaultsOnly: failClosed }
44002
+ { failClosedDefaultsOnly: failClosed, pii: state.piiWire }
43901
44003
  );
43902
44004
  }
43903
44005
  analyticsMapFromRulesStore() {
@@ -44026,6 +44128,7 @@ var __publicField = (obj, key, value) => {
44026
44128
  exports2.LongPollingTransport = LongPollingTransport;
44027
44129
  exports2.RulesStore = RulesStore;
44028
44130
  exports2.SseTransport = SseTransport;
44131
+ exports2.applyPiiHashToFlatContext = applyPiiHashToFlatContext;
44029
44132
  exports2.applyRolloutStrategy = applyRolloutStrategy;
44030
44133
  exports2.asyncCache = cacheHelper_async;
44031
44134
  exports2.canonicalizeForSigning = canonicalizeForSigning;
@@ -44043,11 +44146,13 @@ var __publicField = (obj, key, value) => {
44043
44146
  exports2.flattenEvaluationContext = flattenEvaluationContext;
44044
44147
  exports2.generateAslClientKeyPair = generateAslClientKeyPair;
44045
44148
  exports2.hashPercent = hashPercent;
44149
+ exports2.hashPiiValue = hashPiiValue;
44046
44150
  exports2.hashToPercentage = hashToPercentage;
44047
44151
  exports2.isConfigPayloadExpired = isConfigPayloadExpired;
44048
44152
  exports2.isInSegment = isInSegment;
44049
44153
  exports2.performAslHandshake = performAslHandshake;
44050
44154
  exports2.pickVariant = pickVariant;
44155
+ exports2.prepareContextForLocalEval = prepareContextForLocalEval;
44051
44156
  exports2.reduceRules = reduceRules;
44052
44157
  exports2.signConfigPayload = signConfigPayload;
44053
44158
  exports2.stringHash = stringHash;