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.
- package/README.md +1 -1
- package/dist/flagmint.cjs.js +140 -21
- package/dist/flagmint.cjs.js.map +1 -1
- package/dist/flagmint.es.js +140 -21
- package/dist/flagmint.es.js.map +1 -1
- package/dist/flagmint.umd.js +140 -21
- 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 +87 -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.umd.js
CHANGED
|
@@ -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.
|
|
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$
|
|
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$
|
|
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
|
|
42906
|
-
const
|
|
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 =
|
|
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;
|