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.
- package/dist/flagmint.cjs.js +125 -20
- package/dist/flagmint.cjs.js.map +1 -1
- package/dist/flagmint.es.js +125 -20
- package/dist/flagmint.es.js.map +1 -1
- package/dist/flagmint.umd.js +125 -20
- package/dist/flagmint.umd.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/sdk/core/config-sync/evaluateSdkFlag.d.ts +24 -1
- package/dist/sdk/core/config-sync/index.d.ts +4 -2
- package/dist/sdk/core/config-sync/piiHash.d.ts +53 -0
- package/dist/sdk/core/config-sync/rulesStore.d.ts +3 -0
- package/dist/sdk/core/config-sync/types.d.ts +12 -2
- package/package.json +1 -1
package/dist/flagmint.es.js
CHANGED
|
@@ -39091,7 +39091,7 @@ class SseTransport {
|
|
|
39091
39091
|
this.connectPromise = new Promise((resolve, reject) => {
|
|
39092
39092
|
this.connectResolve = resolve;
|
|
39093
39093
|
this.connectReject = reject;
|
|
39094
|
-
const sdkVersion = "2.2.
|
|
39094
|
+
const sdkVersion = "2.2.2-rc.0";
|
|
39095
39095
|
const platform2 = typeof window !== "undefined" ? "browser" : "nodejs";
|
|
39096
39096
|
const wrapperName = this.configOptions?.wrapper?.name || "native-js";
|
|
39097
39097
|
const wrapperVersion = this.configOptions?.wrapper?.version || "none";
|
|
@@ -41777,7 +41777,7 @@ function expand2(hash3, prk, info, length = 32) {
|
|
|
41777
41777
|
const hkdf = (hash3, ikm, salt, info, length) => expand2(hash3, extract(hash3, ikm, salt), info, length);
|
|
41778
41778
|
const ASL_HKDF_INFO = "flagmint-asl-config-sync-mac-v1";
|
|
41779
41779
|
const ASL_KEY_AGREEMENT = "x25519-hkdf-sha256";
|
|
41780
|
-
const textEncoder$
|
|
41780
|
+
const textEncoder$2 = new TextEncoder();
|
|
41781
41781
|
function generateAslClientKeyPair() {
|
|
41782
41782
|
const privateKey = x25519.utils.randomSecretKey();
|
|
41783
41783
|
const publicKey = x25519.getPublicKey(privateKey);
|
|
@@ -41808,7 +41808,7 @@ function deriveAslMacKey(input) {
|
|
|
41808
41808
|
sha256,
|
|
41809
41809
|
shared,
|
|
41810
41810
|
salt,
|
|
41811
|
-
textEncoder$
|
|
41811
|
+
textEncoder$2.encode(ASL_HKDF_INFO),
|
|
41812
41812
|
32
|
|
41813
41813
|
);
|
|
41814
41814
|
return { configMacKey };
|
|
@@ -41818,7 +41818,7 @@ function wipeKeyMaterial(key2) {
|
|
|
41818
41818
|
return;
|
|
41819
41819
|
key2.fill(0);
|
|
41820
41820
|
}
|
|
41821
|
-
const textEncoder = new TextEncoder();
|
|
41821
|
+
const textEncoder$1 = new TextEncoder();
|
|
41822
41822
|
function canonicalizeForSigning(value) {
|
|
41823
41823
|
return JSON.stringify(sortValue(value));
|
|
41824
41824
|
}
|
|
@@ -41835,12 +41835,12 @@ function sortValue(value) {
|
|
|
41835
41835
|
return sorted;
|
|
41836
41836
|
}
|
|
41837
41837
|
function normalizeMacKey(secret2) {
|
|
41838
|
-
return typeof secret2 === "string" ? textEncoder.encode(secret2) : secret2;
|
|
41838
|
+
return typeof secret2 === "string" ? textEncoder$1.encode(secret2) : secret2;
|
|
41839
41839
|
}
|
|
41840
41840
|
function signConfigPayload(body, secret2) {
|
|
41841
41841
|
const { signature: _ignored, ...unsigned } = body;
|
|
41842
41842
|
const canonical = canonicalizeForSigning(unsigned);
|
|
41843
|
-
const mac = hmac2(sha256, normalizeMacKey(secret2), textEncoder.encode(canonical));
|
|
41843
|
+
const mac = hmac2(sha256, normalizeMacKey(secret2), textEncoder$1.encode(canonical));
|
|
41844
41844
|
return bytesToHex$1(mac);
|
|
41845
41845
|
}
|
|
41846
41846
|
function timingSafeEqualBytes(a, b) {
|
|
@@ -41862,13 +41862,93 @@ function verifyConfigPayloadSignature(body, secret2) {
|
|
|
41862
41862
|
} catch {
|
|
41863
41863
|
return false;
|
|
41864
41864
|
}
|
|
41865
|
-
const a = textEncoder.encode(body.signature);
|
|
41866
|
-
const b = textEncoder.encode(expected);
|
|
41865
|
+
const a = textEncoder$1.encode(body.signature);
|
|
41866
|
+
const b = textEncoder$1.encode(expected);
|
|
41867
41867
|
return timingSafeEqualBytes(a, b);
|
|
41868
41868
|
}
|
|
41869
41869
|
function isConfigPayloadExpired(expiresAt, now = Date.now()) {
|
|
41870
41870
|
return !Number.isFinite(expiresAt) || now >= expiresAt;
|
|
41871
41871
|
}
|
|
41872
|
+
const PII_VALUE_ENCODING = "hmac-v1";
|
|
41873
|
+
const textEncoder = new TextEncoder();
|
|
41874
|
+
const HASH_HEX_PATTERN = /^[0-9a-f]{64}$/;
|
|
41875
|
+
function normalizePiiString(value) {
|
|
41876
|
+
return value.trim().toLowerCase();
|
|
41877
|
+
}
|
|
41878
|
+
function hashPiiValue(value, salt) {
|
|
41879
|
+
const mac = hmac2(
|
|
41880
|
+
sha256,
|
|
41881
|
+
textEncoder.encode(salt),
|
|
41882
|
+
textEncoder.encode(normalizePiiString(value))
|
|
41883
|
+
);
|
|
41884
|
+
return bytesToHex$1(mac);
|
|
41885
|
+
}
|
|
41886
|
+
function isPiiAttribute(attribute, piiAttributes) {
|
|
41887
|
+
if (!attribute || piiAttributes.length === 0)
|
|
41888
|
+
return false;
|
|
41889
|
+
const attr = attribute.trim();
|
|
41890
|
+
if (!attr)
|
|
41891
|
+
return false;
|
|
41892
|
+
for (const key2 of piiAttributes) {
|
|
41893
|
+
if (!key2)
|
|
41894
|
+
continue;
|
|
41895
|
+
if (attr === key2)
|
|
41896
|
+
return true;
|
|
41897
|
+
if (attr.endsWith(`.${key2}`))
|
|
41898
|
+
return true;
|
|
41899
|
+
}
|
|
41900
|
+
return false;
|
|
41901
|
+
}
|
|
41902
|
+
function piiWireOptionsFromPayload(payload) {
|
|
41903
|
+
if (!payload)
|
|
41904
|
+
return null;
|
|
41905
|
+
const salt = typeof payload.piiSalt === "string" ? payload.piiSalt : "";
|
|
41906
|
+
if (!salt)
|
|
41907
|
+
return null;
|
|
41908
|
+
const encoding = typeof payload.piiValueEncoding === "string" ? payload.piiValueEncoding : PII_VALUE_ENCODING;
|
|
41909
|
+
if (encoding !== PII_VALUE_ENCODING)
|
|
41910
|
+
return null;
|
|
41911
|
+
const attrs = Array.isArray(payload.piiAttributes) ? payload.piiAttributes.filter((k) => typeof k === "string") : [];
|
|
41912
|
+
return {
|
|
41913
|
+
piiAttributes: attrs,
|
|
41914
|
+
piiSalt: salt,
|
|
41915
|
+
piiValueEncoding: PII_VALUE_ENCODING
|
|
41916
|
+
};
|
|
41917
|
+
}
|
|
41918
|
+
function applyPiiHashToFlatContext(context, options) {
|
|
41919
|
+
if (!options || !options.piiSalt || !options.piiAttributes.length || options.piiValueEncoding !== PII_VALUE_ENCODING) {
|
|
41920
|
+
return context;
|
|
41921
|
+
}
|
|
41922
|
+
let changed = false;
|
|
41923
|
+
const out = { ...context };
|
|
41924
|
+
for (const [key2, value] of Object.entries(context)) {
|
|
41925
|
+
if (!isPiiAttribute(key2, options.piiAttributes))
|
|
41926
|
+
continue;
|
|
41927
|
+
if (typeof value === "string") {
|
|
41928
|
+
if (HASH_HEX_PATTERN.test(value))
|
|
41929
|
+
continue;
|
|
41930
|
+
out[key2] = hashPiiValue(value, options.piiSalt);
|
|
41931
|
+
changed = true;
|
|
41932
|
+
continue;
|
|
41933
|
+
}
|
|
41934
|
+
if (Array.isArray(value)) {
|
|
41935
|
+
let arrayChanged = false;
|
|
41936
|
+
const next = value.map((entry) => {
|
|
41937
|
+
if (typeof entry !== "string")
|
|
41938
|
+
return entry;
|
|
41939
|
+
if (HASH_HEX_PATTERN.test(entry))
|
|
41940
|
+
return entry;
|
|
41941
|
+
arrayChanged = true;
|
|
41942
|
+
return hashPiiValue(entry, options.piiSalt);
|
|
41943
|
+
});
|
|
41944
|
+
if (arrayChanged) {
|
|
41945
|
+
out[key2] = next;
|
|
41946
|
+
changed = true;
|
|
41947
|
+
}
|
|
41948
|
+
}
|
|
41949
|
+
}
|
|
41950
|
+
return changed ? out : context;
|
|
41951
|
+
}
|
|
41872
41952
|
function createEmptyRulesState() {
|
|
41873
41953
|
return {
|
|
41874
41954
|
version: 0,
|
|
@@ -41876,7 +41956,8 @@ function createEmptyRulesState() {
|
|
|
41876
41956
|
flags: /* @__PURE__ */ new Map(),
|
|
41877
41957
|
segments: /* @__PURE__ */ new Map(),
|
|
41878
41958
|
ready: false,
|
|
41879
|
-
needsFullConfig: true
|
|
41959
|
+
needsFullConfig: true,
|
|
41960
|
+
piiWire: null
|
|
41880
41961
|
};
|
|
41881
41962
|
}
|
|
41882
41963
|
function cloneState(state) {
|
|
@@ -41886,7 +41967,12 @@ function cloneState(state) {
|
|
|
41886
41967
|
flags: new Map(state.flags),
|
|
41887
41968
|
segments: new Map(state.segments),
|
|
41888
41969
|
ready: state.ready,
|
|
41889
|
-
needsFullConfig: state.needsFullConfig
|
|
41970
|
+
needsFullConfig: state.needsFullConfig,
|
|
41971
|
+
piiWire: state.piiWire ? {
|
|
41972
|
+
piiAttributes: [...state.piiWire.piiAttributes],
|
|
41973
|
+
piiSalt: state.piiWire.piiSalt,
|
|
41974
|
+
piiValueEncoding: state.piiWire.piiValueEncoding
|
|
41975
|
+
} : null
|
|
41890
41976
|
};
|
|
41891
41977
|
}
|
|
41892
41978
|
function segmentsFromRecord(record) {
|
|
@@ -41919,7 +42005,8 @@ function hydrateFromFull(action) {
|
|
|
41919
42005
|
flags,
|
|
41920
42006
|
segments: segmentsFromRecord(action.segments),
|
|
41921
42007
|
ready: true,
|
|
41922
|
-
needsFullConfig: false
|
|
42008
|
+
needsFullConfig: false,
|
|
42009
|
+
piiWire: piiWireOptionsFromPayload(action)
|
|
41923
42010
|
};
|
|
41924
42011
|
}
|
|
41925
42012
|
function applyPatch(state, action) {
|
|
@@ -41931,13 +42018,15 @@ function applyPatch(state, action) {
|
|
|
41931
42018
|
if (flag?.key)
|
|
41932
42019
|
flags.set(flag.key, flag);
|
|
41933
42020
|
}
|
|
42021
|
+
const nextPii = piiWireOptionsFromPayload(action) ?? state.piiWire;
|
|
41934
42022
|
return {
|
|
41935
42023
|
version: action.toVersion,
|
|
41936
42024
|
expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : state.expiresAt,
|
|
41937
42025
|
flags,
|
|
41938
42026
|
segments: applySegmentUpserts(state.segments, action.segments),
|
|
41939
42027
|
ready: true,
|
|
41940
|
-
needsFullConfig: false
|
|
42028
|
+
needsFullConfig: false,
|
|
42029
|
+
piiWire: nextPii
|
|
41941
42030
|
};
|
|
41942
42031
|
}
|
|
41943
42032
|
function reduceRules(state, action, now = Date.now()) {
|
|
@@ -42114,11 +42203,17 @@ class RulesStore {
|
|
|
42114
42203
|
this.state.segments.forEach((segment, id) => {
|
|
42115
42204
|
segments[id] = segment;
|
|
42116
42205
|
});
|
|
42206
|
+
const pii = this.state.piiWire;
|
|
42117
42207
|
return {
|
|
42118
42208
|
version: this.state.version,
|
|
42119
42209
|
expiresAt: this.state.expiresAt,
|
|
42120
42210
|
flags: Array.from(this.state.flags.values()),
|
|
42121
|
-
segments
|
|
42211
|
+
segments,
|
|
42212
|
+
...pii ? {
|
|
42213
|
+
piiAttributes: [...pii.piiAttributes],
|
|
42214
|
+
piiSalt: pii.piiSalt,
|
|
42215
|
+
piiValueEncoding: pii.piiValueEncoding
|
|
42216
|
+
} : {}
|
|
42122
42217
|
};
|
|
42123
42218
|
}
|
|
42124
42219
|
hydrateFromSnapshot(snapshot, now = Date.now()) {
|
|
@@ -42134,7 +42229,8 @@ class RulesStore {
|
|
|
42134
42229
|
flags,
|
|
42135
42230
|
segments: segmentsFromRecord(snapshot.segments),
|
|
42136
42231
|
ready: !expired && flags.size > 0,
|
|
42137
|
-
needsFullConfig: expired || flags.size === 0
|
|
42232
|
+
needsFullConfig: expired || flags.size === 0,
|
|
42233
|
+
piiWire: piiWireOptionsFromPayload(snapshot)
|
|
42138
42234
|
};
|
|
42139
42235
|
}
|
|
42140
42236
|
}
|
|
@@ -42898,8 +42994,13 @@ function prepareContextForEvaluator(context) {
|
|
|
42898
42994
|
}
|
|
42899
42995
|
return context;
|
|
42900
42996
|
}
|
|
42901
|
-
function
|
|
42902
|
-
const
|
|
42997
|
+
function prepareContextForLocalEval(context, pii) {
|
|
42998
|
+
const prepared = prepareContextForEvaluator(context);
|
|
42999
|
+
const flat = flattenEvaluationContext(prepared);
|
|
43000
|
+
return applyPiiHashToFlatContext(flat, pii);
|
|
43001
|
+
}
|
|
43002
|
+
function evaluateSdkFlag(flag, context, segments, pii) {
|
|
43003
|
+
const evalContext = prepareContextForLocalEval(context, pii);
|
|
42903
43004
|
const variationsById = {};
|
|
42904
43005
|
for (const v of flag.variations || []) {
|
|
42905
43006
|
if (v?.id)
|
|
@@ -42959,7 +43060,7 @@ function evaluateSdkFlag(flag, context, segments) {
|
|
|
42959
43060
|
}
|
|
42960
43061
|
function evaluateAllSdkFlags(flags, context, segments, options) {
|
|
42961
43062
|
const list = flags instanceof Map ? Array.from(flags.values()) : flags;
|
|
42962
|
-
const prepared =
|
|
43063
|
+
const prepared = prepareContextForLocalEval(context, options?.pii);
|
|
42963
43064
|
const out = {};
|
|
42964
43065
|
for (const flag of list) {
|
|
42965
43066
|
if (!flag?.key)
|
|
@@ -42968,7 +43069,7 @@ function evaluateAllSdkFlags(flags, context, segments, options) {
|
|
|
42968
43069
|
out[flag.key] = coerceType(flag.default_value, flag.type);
|
|
42969
43070
|
continue;
|
|
42970
43071
|
}
|
|
42971
|
-
out[flag.key] = evaluateSdkFlag(flag, prepared, segments);
|
|
43072
|
+
out[flag.key] = evaluateSdkFlag(flag, prepared, segments, null);
|
|
42972
43073
|
}
|
|
42973
43074
|
return out;
|
|
42974
43075
|
}
|
|
@@ -43413,7 +43514,8 @@ class FlagClient {
|
|
|
43413
43514
|
value = evaluateSdkFlag(
|
|
43414
43515
|
flag,
|
|
43415
43516
|
this.context,
|
|
43416
|
-
this.rulesStore.getState().segments
|
|
43517
|
+
this.rulesStore.getState().segments,
|
|
43518
|
+
this.rulesStore.getState().piiWire
|
|
43417
43519
|
) ?? fallback;
|
|
43418
43520
|
}
|
|
43419
43521
|
} else {
|
|
@@ -43893,7 +43995,7 @@ class FlagClient {
|
|
|
43893
43995
|
state.flags,
|
|
43894
43996
|
context ?? this.context,
|
|
43895
43997
|
state.segments,
|
|
43896
|
-
{ failClosedDefaultsOnly: failClosed }
|
|
43998
|
+
{ failClosedDefaultsOnly: failClosed, pii: state.piiWire }
|
|
43897
43999
|
);
|
|
43898
44000
|
}
|
|
43899
44001
|
analyticsMapFromRulesStore() {
|
|
@@ -44023,6 +44125,7 @@ export {
|
|
|
44023
44125
|
LongPollingTransport,
|
|
44024
44126
|
RulesStore,
|
|
44025
44127
|
SseTransport,
|
|
44128
|
+
applyPiiHashToFlatContext,
|
|
44026
44129
|
applyRolloutStrategy,
|
|
44027
44130
|
cacheHelper_async as asyncCache,
|
|
44028
44131
|
canonicalizeForSigning,
|
|
@@ -44040,11 +44143,13 @@ export {
|
|
|
44040
44143
|
flattenEvaluationContext,
|
|
44041
44144
|
generateAslClientKeyPair,
|
|
44042
44145
|
hashPercent,
|
|
44146
|
+
hashPiiValue,
|
|
44043
44147
|
hashToPercentage,
|
|
44044
44148
|
isConfigPayloadExpired,
|
|
44045
44149
|
isInSegment,
|
|
44046
44150
|
performAslHandshake,
|
|
44047
44151
|
pickVariant,
|
|
44152
|
+
prepareContextForLocalEval,
|
|
44048
44153
|
reduceRules,
|
|
44049
44154
|
signConfigPayload,
|
|
44050
44155
|
stringHash,
|