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