flagmint-js-sdk 2.2.2-rc.0 → 2.2.3-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/README.md +2 -2
- package/dist/flagmint.cjs.js +131 -32
- package/dist/flagmint.cjs.js.map +1 -1
- package/dist/flagmint.es.js +131 -32
- package/dist/flagmint.es.js.map +1 -1
- package/dist/flagmint.umd.js +131 -32
- package/dist/flagmint.umd.js.map +1 -1
- package/dist/sdk/core/config-sync/index.d.ts +2 -2
- package/dist/sdk/core/config-sync/piiHash.d.ts +86 -6
- package/dist/sdk/core/config-sync/rulesStore.d.ts +7 -1
- package/dist/sdk/core/config-sync/types.d.ts +5 -0
- package/dist/sdk/core/helpers/cacheHelper.d.ts +7 -0
- package/package.json +1 -1
package/dist/flagmint.umd.js
CHANGED
|
@@ -38623,6 +38623,12 @@ var __publicField = (obj, key, value) => {
|
|
|
38623
38623
|
} catch {
|
|
38624
38624
|
}
|
|
38625
38625
|
}
|
|
38626
|
+
function clearCachedFlags(apiKey) {
|
|
38627
|
+
try {
|
|
38628
|
+
storage$1.removeItem?.(getFlagsKey$1(apiKey));
|
|
38629
|
+
} catch {
|
|
38630
|
+
}
|
|
38631
|
+
}
|
|
38626
38632
|
function loadCachedContext$1(apiKey) {
|
|
38627
38633
|
try {
|
|
38628
38634
|
const raw = storage$1.getItem(getContextKey$1(apiKey));
|
|
@@ -38661,6 +38667,7 @@ var __publicField = (obj, key, value) => {
|
|
|
38661
38667
|
}
|
|
38662
38668
|
const cacheHelper = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
38663
38669
|
__proto__: null,
|
|
38670
|
+
clearCachedFlags,
|
|
38664
38671
|
clearCachedRulesSnapshot: clearCachedRulesSnapshot$1,
|
|
38665
38672
|
loadCachedContext: loadCachedContext$1,
|
|
38666
38673
|
loadCachedFlags: loadCachedFlags$1,
|
|
@@ -39095,7 +39102,7 @@ var __publicField = (obj, key, value) => {
|
|
|
39095
39102
|
this.connectPromise = new Promise((resolve, reject) => {
|
|
39096
39103
|
this.connectResolve = resolve;
|
|
39097
39104
|
this.connectReject = reject;
|
|
39098
|
-
const sdkVersion = "2.2.
|
|
39105
|
+
const sdkVersion = "2.2.3-rc.0";
|
|
39099
39106
|
const platform2 = typeof window !== "undefined" ? "browser" : "nodejs";
|
|
39100
39107
|
const wrapperName = this.configOptions?.wrapper?.name || "native-js";
|
|
39101
39108
|
const wrapperVersion = this.configOptions?.wrapper?.version || "none";
|
|
@@ -41875,7 +41882,6 @@ var __publicField = (obj, key, value) => {
|
|
|
41875
41882
|
}
|
|
41876
41883
|
const PII_VALUE_ENCODING = "hmac-v1";
|
|
41877
41884
|
const textEncoder = new TextEncoder();
|
|
41878
|
-
const HASH_HEX_PATTERN = /^[0-9a-f]{64}$/;
|
|
41879
41885
|
function normalizePiiString(value) {
|
|
41880
41886
|
return value.trim().toLowerCase();
|
|
41881
41887
|
}
|
|
@@ -41903,34 +41909,109 @@ var __publicField = (obj, key, value) => {
|
|
|
41903
41909
|
}
|
|
41904
41910
|
return false;
|
|
41905
41911
|
}
|
|
41912
|
+
function payloadHasExplicitPiiFields(payload) {
|
|
41913
|
+
if (!payload)
|
|
41914
|
+
return false;
|
|
41915
|
+
return payload.piiSalt !== void 0 || payload.piiAttributes !== void 0 || payload.piiValueEncoding !== void 0;
|
|
41916
|
+
}
|
|
41917
|
+
function piiAttributeKeysFromPayload(payload) {
|
|
41918
|
+
if (!payload || !Array.isArray(payload.piiAttributes))
|
|
41919
|
+
return [];
|
|
41920
|
+
return payload.piiAttributes.filter((k) => typeof k === "string" && k.length > 0);
|
|
41921
|
+
}
|
|
41922
|
+
function hasMalformedPiiAttributes(payload) {
|
|
41923
|
+
if (!payload || payload.piiAttributes === void 0)
|
|
41924
|
+
return false;
|
|
41925
|
+
if (!Array.isArray(payload.piiAttributes))
|
|
41926
|
+
return true;
|
|
41927
|
+
return payload.piiAttributes.some(
|
|
41928
|
+
(entry) => typeof entry !== "string" || entry.length === 0
|
|
41929
|
+
);
|
|
41930
|
+
}
|
|
41931
|
+
function hasExplicitInvalidPiiEncoding(payload) {
|
|
41932
|
+
if (!payload || payload.piiValueEncoding === void 0)
|
|
41933
|
+
return false;
|
|
41934
|
+
return payload.piiValueEncoding !== PII_VALUE_ENCODING;
|
|
41935
|
+
}
|
|
41936
|
+
function payloadRequiresUsablePiiWire(payload) {
|
|
41937
|
+
if (!payload)
|
|
41938
|
+
return false;
|
|
41939
|
+
if (hasExplicitInvalidPiiEncoding(payload))
|
|
41940
|
+
return true;
|
|
41941
|
+
if (hasMalformedPiiAttributes(payload))
|
|
41942
|
+
return true;
|
|
41943
|
+
if (piiAttributeKeysFromPayload(payload).length > 0)
|
|
41944
|
+
return true;
|
|
41945
|
+
return false;
|
|
41946
|
+
}
|
|
41947
|
+
function isExplicitPiiRequirementCleared(payload) {
|
|
41948
|
+
if (!payload || payload.piiAttributes === void 0)
|
|
41949
|
+
return false;
|
|
41950
|
+
if (!Array.isArray(payload.piiAttributes))
|
|
41951
|
+
return false;
|
|
41952
|
+
if (payload.piiAttributes.length !== 0)
|
|
41953
|
+
return false;
|
|
41954
|
+
if (hasExplicitInvalidPiiEncoding(payload))
|
|
41955
|
+
return false;
|
|
41956
|
+
return true;
|
|
41957
|
+
}
|
|
41906
41958
|
function piiWireOptionsFromPayload(payload) {
|
|
41907
41959
|
if (!payload)
|
|
41908
41960
|
return null;
|
|
41961
|
+
if (hasExplicitInvalidPiiEncoding(payload))
|
|
41962
|
+
return null;
|
|
41963
|
+
if (hasMalformedPiiAttributes(payload))
|
|
41964
|
+
return null;
|
|
41909
41965
|
const salt = typeof payload.piiSalt === "string" ? payload.piiSalt : "";
|
|
41910
41966
|
if (!salt)
|
|
41911
41967
|
return null;
|
|
41912
|
-
const
|
|
41913
|
-
if (encoding !== PII_VALUE_ENCODING)
|
|
41914
|
-
return null;
|
|
41915
|
-
const attrs = Array.isArray(payload.piiAttributes) ? payload.piiAttributes.filter((k) => typeof k === "string") : [];
|
|
41968
|
+
const attrs = piiAttributeKeysFromPayload(payload);
|
|
41916
41969
|
return {
|
|
41917
41970
|
piiAttributes: attrs,
|
|
41918
41971
|
piiSalt: salt,
|
|
41919
41972
|
piiValueEncoding: PII_VALUE_ENCODING
|
|
41920
41973
|
};
|
|
41921
41974
|
}
|
|
41922
|
-
function
|
|
41975
|
+
function isPiiWireBroken(payload, resolved, previousPriorHadPiiAttrs = false) {
|
|
41976
|
+
if (hasExplicitInvalidPiiEncoding(payload) || hasMalformedPiiAttributes(payload)) {
|
|
41977
|
+
return true;
|
|
41978
|
+
}
|
|
41979
|
+
if (resolved) {
|
|
41980
|
+
return false;
|
|
41981
|
+
}
|
|
41982
|
+
if (isExplicitPiiRequirementCleared(payload))
|
|
41983
|
+
return false;
|
|
41984
|
+
if (payloadRequiresUsablePiiWire(payload))
|
|
41985
|
+
return true;
|
|
41986
|
+
if (previousPriorHadPiiAttrs && payloadHasExplicitPiiFields(payload)) {
|
|
41987
|
+
return true;
|
|
41988
|
+
}
|
|
41989
|
+
return false;
|
|
41990
|
+
}
|
|
41991
|
+
function resolvePiiWireForDelta(previous, action) {
|
|
41992
|
+
if (!payloadHasExplicitPiiFields(action)) {
|
|
41993
|
+
return previous;
|
|
41994
|
+
}
|
|
41995
|
+
const merged = {
|
|
41996
|
+
piiSalt: action.piiSalt !== void 0 ? action.piiSalt : previous?.piiSalt,
|
|
41997
|
+
piiAttributes: action.piiAttributes !== void 0 ? action.piiAttributes : previous?.piiAttributes,
|
|
41998
|
+
piiValueEncoding: action.piiValueEncoding !== void 0 ? action.piiValueEncoding : previous?.piiValueEncoding
|
|
41999
|
+
};
|
|
42000
|
+
return piiWireOptionsFromPayload(merged);
|
|
42001
|
+
}
|
|
42002
|
+
function applyPiiHashToFlatContext(context, options, mode) {
|
|
41923
42003
|
if (!options || !options.piiSalt || !options.piiAttributes.length || options.piiValueEncoding !== PII_VALUE_ENCODING) {
|
|
41924
42004
|
return context;
|
|
41925
42005
|
}
|
|
42006
|
+
if (mode?.alreadyHashed) {
|
|
42007
|
+
return context;
|
|
42008
|
+
}
|
|
41926
42009
|
let changed = false;
|
|
41927
42010
|
const out = { ...context };
|
|
41928
42011
|
for (const [key2, value] of Object.entries(context)) {
|
|
41929
42012
|
if (!isPiiAttribute(key2, options.piiAttributes))
|
|
41930
42013
|
continue;
|
|
41931
42014
|
if (typeof value === "string") {
|
|
41932
|
-
if (HASH_HEX_PATTERN.test(value))
|
|
41933
|
-
continue;
|
|
41934
42015
|
out[key2] = hashPiiValue(value, options.piiSalt);
|
|
41935
42016
|
changed = true;
|
|
41936
42017
|
continue;
|
|
@@ -41940,8 +42021,6 @@ var __publicField = (obj, key, value) => {
|
|
|
41940
42021
|
const next = value.map((entry) => {
|
|
41941
42022
|
if (typeof entry !== "string")
|
|
41942
42023
|
return entry;
|
|
41943
|
-
if (HASH_HEX_PATTERN.test(entry))
|
|
41944
|
-
return entry;
|
|
41945
42024
|
arrayChanged = true;
|
|
41946
42025
|
return hashPiiValue(entry, options.piiSalt);
|
|
41947
42026
|
});
|
|
@@ -41961,7 +42040,8 @@ var __publicField = (obj, key, value) => {
|
|
|
41961
42040
|
segments: /* @__PURE__ */ new Map(),
|
|
41962
42041
|
ready: false,
|
|
41963
42042
|
needsFullConfig: true,
|
|
41964
|
-
piiWire: null
|
|
42043
|
+
piiWire: null,
|
|
42044
|
+
piiWireBroken: false
|
|
41965
42045
|
};
|
|
41966
42046
|
}
|
|
41967
42047
|
function cloneState(state) {
|
|
@@ -41976,7 +42056,8 @@ var __publicField = (obj, key, value) => {
|
|
|
41976
42056
|
piiAttributes: [...state.piiWire.piiAttributes],
|
|
41977
42057
|
piiSalt: state.piiWire.piiSalt,
|
|
41978
42058
|
piiValueEncoding: state.piiWire.piiValueEncoding
|
|
41979
|
-
} : null
|
|
42059
|
+
} : null,
|
|
42060
|
+
piiWireBroken: state.piiWireBroken
|
|
41980
42061
|
};
|
|
41981
42062
|
}
|
|
41982
42063
|
function segmentsFromRecord(record) {
|
|
@@ -42003,14 +42084,18 @@ var __publicField = (obj, key, value) => {
|
|
|
42003
42084
|
if (flag?.key)
|
|
42004
42085
|
flags.set(flag.key, flag);
|
|
42005
42086
|
}
|
|
42087
|
+
const piiWire = piiWireOptionsFromPayload(action);
|
|
42088
|
+
const piiWireBroken = isPiiWireBroken(action, piiWire, false);
|
|
42006
42089
|
return {
|
|
42007
42090
|
version: action.version,
|
|
42008
42091
|
expiresAt: action.expiresAt,
|
|
42009
42092
|
flags,
|
|
42010
42093
|
segments: segmentsFromRecord(action.segments),
|
|
42011
|
-
|
|
42012
|
-
|
|
42013
|
-
|
|
42094
|
+
// Usable rules, but PII metadata must be valid when hashing is required.
|
|
42095
|
+
ready: !piiWireBroken,
|
|
42096
|
+
needsFullConfig: piiWireBroken,
|
|
42097
|
+
piiWire,
|
|
42098
|
+
piiWireBroken
|
|
42014
42099
|
};
|
|
42015
42100
|
}
|
|
42016
42101
|
function applyPatch(state, action) {
|
|
@@ -42022,15 +42107,20 @@ var __publicField = (obj, key, value) => {
|
|
|
42022
42107
|
if (flag?.key)
|
|
42023
42108
|
flags.set(flag.key, flag);
|
|
42024
42109
|
}
|
|
42025
|
-
const nextPii =
|
|
42110
|
+
const nextPii = resolvePiiWireForDelta(state.piiWire, action);
|
|
42111
|
+
const priorHadPiiAttrs = (state.piiWire?.piiAttributes.length ?? 0) > 0 || state.piiWireBroken;
|
|
42112
|
+
const computedBroken = isPiiWireBroken(action, nextPii, priorHadPiiAttrs);
|
|
42113
|
+
const recoveredWithRequiredAttrs = !!nextPii && nextPii.piiAttributes.length > 0;
|
|
42114
|
+
const piiWireBroken = isExplicitPiiRequirementCleared(action) ? false : recoveredWithRequiredAttrs ? false : computedBroken || state.piiWireBroken;
|
|
42026
42115
|
return {
|
|
42027
42116
|
version: action.toVersion,
|
|
42028
42117
|
expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : state.expiresAt,
|
|
42029
42118
|
flags,
|
|
42030
42119
|
segments: applySegmentUpserts(state.segments, action.segments),
|
|
42031
|
-
ready:
|
|
42032
|
-
needsFullConfig:
|
|
42033
|
-
piiWire: nextPii
|
|
42120
|
+
ready: !piiWireBroken,
|
|
42121
|
+
needsFullConfig: piiWireBroken,
|
|
42122
|
+
piiWire: nextPii,
|
|
42123
|
+
piiWireBroken
|
|
42034
42124
|
};
|
|
42035
42125
|
}
|
|
42036
42126
|
function reduceRules(state, action, now = Date.now()) {
|
|
@@ -42050,8 +42140,8 @@ var __publicField = (obj, key, value) => {
|
|
|
42050
42140
|
...cloneState(state),
|
|
42051
42141
|
version: state.version,
|
|
42052
42142
|
expiresAt: action.expiresAt,
|
|
42053
|
-
ready:
|
|
42054
|
-
needsFullConfig: state.flags.size === 0 || versionMismatch ? true : state.needsFullConfig
|
|
42143
|
+
ready: !state.piiWireBroken,
|
|
42144
|
+
needsFullConfig: state.piiWireBroken || state.flags.size === 0 || versionMismatch ? true : state.needsFullConfig
|
|
42055
42145
|
}
|
|
42056
42146
|
};
|
|
42057
42147
|
}
|
|
@@ -42107,8 +42197,8 @@ var __publicField = (obj, key, value) => {
|
|
|
42107
42197
|
...current,
|
|
42108
42198
|
version: action.toVersion,
|
|
42109
42199
|
expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : current.expiresAt,
|
|
42110
|
-
ready:
|
|
42111
|
-
needsFullConfig:
|
|
42200
|
+
ready: !current.piiWireBroken,
|
|
42201
|
+
needsFullConfig: current.piiWireBroken
|
|
42112
42202
|
}
|
|
42113
42203
|
};
|
|
42114
42204
|
}
|
|
@@ -42131,9 +42221,12 @@ var __publicField = (obj, key, value) => {
|
|
|
42131
42221
|
return this.state;
|
|
42132
42222
|
}
|
|
42133
42223
|
/**
|
|
42134
|
-
* Fail-closed readiness: lease not expired
|
|
42224
|
+
* Fail-closed readiness: lease not expired, store marked ready, and PII
|
|
42225
|
+
* wire metadata usable when hashing is required.
|
|
42135
42226
|
*/
|
|
42136
42227
|
isReady(now = Date.now()) {
|
|
42228
|
+
if (this.state.piiWireBroken)
|
|
42229
|
+
return false;
|
|
42137
42230
|
if (!this.state.ready)
|
|
42138
42231
|
return false;
|
|
42139
42232
|
if (!this.state.expiresAt)
|
|
@@ -42217,7 +42310,9 @@ var __publicField = (obj, key, value) => {
|
|
|
42217
42310
|
piiAttributes: [...pii.piiAttributes],
|
|
42218
42311
|
piiSalt: pii.piiSalt,
|
|
42219
42312
|
piiValueEncoding: pii.piiValueEncoding
|
|
42220
|
-
} : {}
|
|
42313
|
+
} : {},
|
|
42314
|
+
// Persist fail-closed even when piiWire is null (unusable salt/encoding).
|
|
42315
|
+
...this.state.piiWireBroken ? { piiWireBroken: true } : {}
|
|
42221
42316
|
};
|
|
42222
42317
|
}
|
|
42223
42318
|
hydrateFromSnapshot(snapshot, now = Date.now()) {
|
|
@@ -42227,14 +42322,17 @@ var __publicField = (obj, key, value) => {
|
|
|
42227
42322
|
flags.set(flag.key, flag);
|
|
42228
42323
|
}
|
|
42229
42324
|
const expired = isConfigPayloadExpired(snapshot.expiresAt, now);
|
|
42325
|
+
const piiWire = piiWireOptionsFromPayload(snapshot);
|
|
42326
|
+
const piiWireBroken = snapshot.piiWireBroken === true || isPiiWireBroken(snapshot, piiWire, false);
|
|
42230
42327
|
this.state = {
|
|
42231
42328
|
version: snapshot.version,
|
|
42232
42329
|
expiresAt: snapshot.expiresAt,
|
|
42233
42330
|
flags,
|
|
42234
42331
|
segments: segmentsFromRecord(snapshot.segments),
|
|
42235
|
-
ready: !expired && flags.size > 0,
|
|
42236
|
-
needsFullConfig: expired || flags.size === 0,
|
|
42237
|
-
piiWire
|
|
42332
|
+
ready: !expired && flags.size > 0 && !piiWireBroken,
|
|
42333
|
+
needsFullConfig: expired || flags.size === 0 || piiWireBroken,
|
|
42334
|
+
piiWire,
|
|
42335
|
+
piiWireBroken
|
|
42238
42336
|
};
|
|
42239
42337
|
}
|
|
42240
42338
|
}
|
|
@@ -42436,7 +42534,7 @@ var __publicField = (obj, key, value) => {
|
|
|
42436
42534
|
function toComparableString(value) {
|
|
42437
42535
|
if (value === null || value === void 0)
|
|
42438
42536
|
return "";
|
|
42439
|
-
return String(value);
|
|
42537
|
+
return String(value).trim().toLowerCase();
|
|
42440
42538
|
}
|
|
42441
42539
|
function toComparableArray(value) {
|
|
42442
42540
|
if (Array.isArray(value)) {
|
|
@@ -43205,9 +43303,10 @@ var __publicField = (obj, key, value) => {
|
|
|
43205
43303
|
}
|
|
43206
43304
|
let hydratedRules = false;
|
|
43207
43305
|
if (this.configSync && this.rulesStore && this.enableOfflineCache) {
|
|
43306
|
+
clearCachedFlags(this.apiKey);
|
|
43208
43307
|
hydratedRules = await this.hydrateRulesFromCache();
|
|
43209
43308
|
}
|
|
43210
|
-
if (this.enableOfflineCache && !hydratedRules) {
|
|
43309
|
+
if (this.enableOfflineCache && !this.configSync && !hydratedRules) {
|
|
43211
43310
|
const cached = await Promise.resolve(
|
|
43212
43311
|
this.cacheAdapter.loadFlags(this.apiKey, this.cacheTTL)
|
|
43213
43312
|
);
|
|
@@ -43449,7 +43548,7 @@ var __publicField = (obj, key, value) => {
|
|
|
43449
43548
|
*/
|
|
43450
43549
|
updateFlags(newFlags, fromShare = false) {
|
|
43451
43550
|
this.flags = newFlags;
|
|
43452
|
-
if (this.enableOfflineCache) {
|
|
43551
|
+
if (this.enableOfflineCache && !this.configSync) {
|
|
43453
43552
|
void Promise.resolve(
|
|
43454
43553
|
this.cacheAdapter.saveFlags(this.apiKey, newFlags)
|
|
43455
43554
|
);
|