flagmint-js-sdk 2.2.2 → 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 +1 -1
- package/dist/flagmint.cjs.js +109 -24
- package/dist/flagmint.cjs.js.map +1 -1
- package/dist/flagmint.es.js +109 -24
- package/dist/flagmint.es.js.map +1 -1
- package/dist/flagmint.umd.js +109 -24
- package/dist/flagmint.umd.js.map +1 -1
- package/dist/sdk/core/config-sync/index.d.ts +1 -1
- package/dist/sdk/core/config-sync/piiHash.d.ts +46 -0
- 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.es.js
CHANGED
|
@@ -38619,6 +38619,12 @@ function saveCachedFlags$1(apiKey, data) {
|
|
|
38619
38619
|
} catch {
|
|
38620
38620
|
}
|
|
38621
38621
|
}
|
|
38622
|
+
function clearCachedFlags(apiKey) {
|
|
38623
|
+
try {
|
|
38624
|
+
storage$1.removeItem?.(getFlagsKey$1(apiKey));
|
|
38625
|
+
} catch {
|
|
38626
|
+
}
|
|
38627
|
+
}
|
|
38622
38628
|
function loadCachedContext$1(apiKey) {
|
|
38623
38629
|
try {
|
|
38624
38630
|
const raw = storage$1.getItem(getContextKey$1(apiKey));
|
|
@@ -38657,6 +38663,7 @@ function clearCachedRulesSnapshot$1(apiKey) {
|
|
|
38657
38663
|
}
|
|
38658
38664
|
const cacheHelper = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
38659
38665
|
__proto__: null,
|
|
38666
|
+
clearCachedFlags,
|
|
38660
38667
|
clearCachedRulesSnapshot: clearCachedRulesSnapshot$1,
|
|
38661
38668
|
loadCachedContext: loadCachedContext$1,
|
|
38662
38669
|
loadCachedFlags: loadCachedFlags$1,
|
|
@@ -39091,7 +39098,7 @@ class SseTransport {
|
|
|
39091
39098
|
this.connectPromise = new Promise((resolve, reject) => {
|
|
39092
39099
|
this.connectResolve = resolve;
|
|
39093
39100
|
this.connectReject = reject;
|
|
39094
|
-
const sdkVersion = "2.2.
|
|
39101
|
+
const sdkVersion = "2.2.3-rc.0";
|
|
39095
39102
|
const platform2 = typeof window !== "undefined" ? "browser" : "nodejs";
|
|
39096
39103
|
const wrapperName = this.configOptions?.wrapper?.name || "native-js";
|
|
39097
39104
|
const wrapperVersion = this.configOptions?.wrapper?.version || "none";
|
|
@@ -41903,22 +41910,80 @@ function payloadHasExplicitPiiFields(payload) {
|
|
|
41903
41910
|
return false;
|
|
41904
41911
|
return payload.piiSalt !== void 0 || payload.piiAttributes !== void 0 || payload.piiValueEncoding !== void 0;
|
|
41905
41912
|
}
|
|
41913
|
+
function piiAttributeKeysFromPayload(payload) {
|
|
41914
|
+
if (!payload || !Array.isArray(payload.piiAttributes))
|
|
41915
|
+
return [];
|
|
41916
|
+
return payload.piiAttributes.filter((k) => typeof k === "string" && k.length > 0);
|
|
41917
|
+
}
|
|
41918
|
+
function hasMalformedPiiAttributes(payload) {
|
|
41919
|
+
if (!payload || payload.piiAttributes === void 0)
|
|
41920
|
+
return false;
|
|
41921
|
+
if (!Array.isArray(payload.piiAttributes))
|
|
41922
|
+
return true;
|
|
41923
|
+
return payload.piiAttributes.some(
|
|
41924
|
+
(entry) => typeof entry !== "string" || entry.length === 0
|
|
41925
|
+
);
|
|
41926
|
+
}
|
|
41927
|
+
function hasExplicitInvalidPiiEncoding(payload) {
|
|
41928
|
+
if (!payload || payload.piiValueEncoding === void 0)
|
|
41929
|
+
return false;
|
|
41930
|
+
return payload.piiValueEncoding !== PII_VALUE_ENCODING;
|
|
41931
|
+
}
|
|
41932
|
+
function payloadRequiresUsablePiiWire(payload) {
|
|
41933
|
+
if (!payload)
|
|
41934
|
+
return false;
|
|
41935
|
+
if (hasExplicitInvalidPiiEncoding(payload))
|
|
41936
|
+
return true;
|
|
41937
|
+
if (hasMalformedPiiAttributes(payload))
|
|
41938
|
+
return true;
|
|
41939
|
+
if (piiAttributeKeysFromPayload(payload).length > 0)
|
|
41940
|
+
return true;
|
|
41941
|
+
return false;
|
|
41942
|
+
}
|
|
41943
|
+
function isExplicitPiiRequirementCleared(payload) {
|
|
41944
|
+
if (!payload || payload.piiAttributes === void 0)
|
|
41945
|
+
return false;
|
|
41946
|
+
if (!Array.isArray(payload.piiAttributes))
|
|
41947
|
+
return false;
|
|
41948
|
+
if (payload.piiAttributes.length !== 0)
|
|
41949
|
+
return false;
|
|
41950
|
+
if (hasExplicitInvalidPiiEncoding(payload))
|
|
41951
|
+
return false;
|
|
41952
|
+
return true;
|
|
41953
|
+
}
|
|
41906
41954
|
function piiWireOptionsFromPayload(payload) {
|
|
41907
41955
|
if (!payload)
|
|
41908
41956
|
return null;
|
|
41957
|
+
if (hasExplicitInvalidPiiEncoding(payload))
|
|
41958
|
+
return null;
|
|
41959
|
+
if (hasMalformedPiiAttributes(payload))
|
|
41960
|
+
return null;
|
|
41909
41961
|
const salt = typeof payload.piiSalt === "string" ? payload.piiSalt : "";
|
|
41910
41962
|
if (!salt)
|
|
41911
41963
|
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") : [];
|
|
41964
|
+
const attrs = piiAttributeKeysFromPayload(payload);
|
|
41916
41965
|
return {
|
|
41917
41966
|
piiAttributes: attrs,
|
|
41918
41967
|
piiSalt: salt,
|
|
41919
41968
|
piiValueEncoding: PII_VALUE_ENCODING
|
|
41920
41969
|
};
|
|
41921
41970
|
}
|
|
41971
|
+
function isPiiWireBroken(payload, resolved, previousPriorHadPiiAttrs = false) {
|
|
41972
|
+
if (hasExplicitInvalidPiiEncoding(payload) || hasMalformedPiiAttributes(payload)) {
|
|
41973
|
+
return true;
|
|
41974
|
+
}
|
|
41975
|
+
if (resolved) {
|
|
41976
|
+
return false;
|
|
41977
|
+
}
|
|
41978
|
+
if (isExplicitPiiRequirementCleared(payload))
|
|
41979
|
+
return false;
|
|
41980
|
+
if (payloadRequiresUsablePiiWire(payload))
|
|
41981
|
+
return true;
|
|
41982
|
+
if (previousPriorHadPiiAttrs && payloadHasExplicitPiiFields(payload)) {
|
|
41983
|
+
return true;
|
|
41984
|
+
}
|
|
41985
|
+
return false;
|
|
41986
|
+
}
|
|
41922
41987
|
function resolvePiiWireForDelta(previous, action) {
|
|
41923
41988
|
if (!payloadHasExplicitPiiFields(action)) {
|
|
41924
41989
|
return previous;
|
|
@@ -41971,7 +42036,8 @@ function createEmptyRulesState() {
|
|
|
41971
42036
|
segments: /* @__PURE__ */ new Map(),
|
|
41972
42037
|
ready: false,
|
|
41973
42038
|
needsFullConfig: true,
|
|
41974
|
-
piiWire: null
|
|
42039
|
+
piiWire: null,
|
|
42040
|
+
piiWireBroken: false
|
|
41975
42041
|
};
|
|
41976
42042
|
}
|
|
41977
42043
|
function cloneState(state) {
|
|
@@ -41986,7 +42052,8 @@ function cloneState(state) {
|
|
|
41986
42052
|
piiAttributes: [...state.piiWire.piiAttributes],
|
|
41987
42053
|
piiSalt: state.piiWire.piiSalt,
|
|
41988
42054
|
piiValueEncoding: state.piiWire.piiValueEncoding
|
|
41989
|
-
} : null
|
|
42055
|
+
} : null,
|
|
42056
|
+
piiWireBroken: state.piiWireBroken
|
|
41990
42057
|
};
|
|
41991
42058
|
}
|
|
41992
42059
|
function segmentsFromRecord(record) {
|
|
@@ -42013,14 +42080,18 @@ function hydrateFromFull(action) {
|
|
|
42013
42080
|
if (flag?.key)
|
|
42014
42081
|
flags.set(flag.key, flag);
|
|
42015
42082
|
}
|
|
42083
|
+
const piiWire = piiWireOptionsFromPayload(action);
|
|
42084
|
+
const piiWireBroken = isPiiWireBroken(action, piiWire, false);
|
|
42016
42085
|
return {
|
|
42017
42086
|
version: action.version,
|
|
42018
42087
|
expiresAt: action.expiresAt,
|
|
42019
42088
|
flags,
|
|
42020
42089
|
segments: segmentsFromRecord(action.segments),
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
|
|
42090
|
+
// Usable rules, but PII metadata must be valid when hashing is required.
|
|
42091
|
+
ready: !piiWireBroken,
|
|
42092
|
+
needsFullConfig: piiWireBroken,
|
|
42093
|
+
piiWire,
|
|
42094
|
+
piiWireBroken
|
|
42024
42095
|
};
|
|
42025
42096
|
}
|
|
42026
42097
|
function applyPatch(state, action) {
|
|
@@ -42033,14 +42104,19 @@ function applyPatch(state, action) {
|
|
|
42033
42104
|
flags.set(flag.key, flag);
|
|
42034
42105
|
}
|
|
42035
42106
|
const nextPii = resolvePiiWireForDelta(state.piiWire, action);
|
|
42107
|
+
const priorHadPiiAttrs = (state.piiWire?.piiAttributes.length ?? 0) > 0 || state.piiWireBroken;
|
|
42108
|
+
const computedBroken = isPiiWireBroken(action, nextPii, priorHadPiiAttrs);
|
|
42109
|
+
const recoveredWithRequiredAttrs = !!nextPii && nextPii.piiAttributes.length > 0;
|
|
42110
|
+
const piiWireBroken = isExplicitPiiRequirementCleared(action) ? false : recoveredWithRequiredAttrs ? false : computedBroken || state.piiWireBroken;
|
|
42036
42111
|
return {
|
|
42037
42112
|
version: action.toVersion,
|
|
42038
42113
|
expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : state.expiresAt,
|
|
42039
42114
|
flags,
|
|
42040
42115
|
segments: applySegmentUpserts(state.segments, action.segments),
|
|
42041
|
-
ready:
|
|
42042
|
-
needsFullConfig:
|
|
42043
|
-
piiWire: nextPii
|
|
42116
|
+
ready: !piiWireBroken,
|
|
42117
|
+
needsFullConfig: piiWireBroken,
|
|
42118
|
+
piiWire: nextPii,
|
|
42119
|
+
piiWireBroken
|
|
42044
42120
|
};
|
|
42045
42121
|
}
|
|
42046
42122
|
function reduceRules(state, action, now = Date.now()) {
|
|
@@ -42060,8 +42136,8 @@ function reduceRules(state, action, now = Date.now()) {
|
|
|
42060
42136
|
...cloneState(state),
|
|
42061
42137
|
version: state.version,
|
|
42062
42138
|
expiresAt: action.expiresAt,
|
|
42063
|
-
ready:
|
|
42064
|
-
needsFullConfig: state.flags.size === 0 || versionMismatch ? true : state.needsFullConfig
|
|
42139
|
+
ready: !state.piiWireBroken,
|
|
42140
|
+
needsFullConfig: state.piiWireBroken || state.flags.size === 0 || versionMismatch ? true : state.needsFullConfig
|
|
42065
42141
|
}
|
|
42066
42142
|
};
|
|
42067
42143
|
}
|
|
@@ -42117,8 +42193,8 @@ function reduceRules(state, action, now = Date.now()) {
|
|
|
42117
42193
|
...current,
|
|
42118
42194
|
version: action.toVersion,
|
|
42119
42195
|
expiresAt: typeof action.expiresAt === "number" ? action.expiresAt : current.expiresAt,
|
|
42120
|
-
ready:
|
|
42121
|
-
needsFullConfig:
|
|
42196
|
+
ready: !current.piiWireBroken,
|
|
42197
|
+
needsFullConfig: current.piiWireBroken
|
|
42122
42198
|
}
|
|
42123
42199
|
};
|
|
42124
42200
|
}
|
|
@@ -42141,9 +42217,12 @@ class RulesStore {
|
|
|
42141
42217
|
return this.state;
|
|
42142
42218
|
}
|
|
42143
42219
|
/**
|
|
42144
|
-
* Fail-closed readiness: lease not expired
|
|
42220
|
+
* Fail-closed readiness: lease not expired, store marked ready, and PII
|
|
42221
|
+
* wire metadata usable when hashing is required.
|
|
42145
42222
|
*/
|
|
42146
42223
|
isReady(now = Date.now()) {
|
|
42224
|
+
if (this.state.piiWireBroken)
|
|
42225
|
+
return false;
|
|
42147
42226
|
if (!this.state.ready)
|
|
42148
42227
|
return false;
|
|
42149
42228
|
if (!this.state.expiresAt)
|
|
@@ -42227,7 +42306,9 @@ class RulesStore {
|
|
|
42227
42306
|
piiAttributes: [...pii.piiAttributes],
|
|
42228
42307
|
piiSalt: pii.piiSalt,
|
|
42229
42308
|
piiValueEncoding: pii.piiValueEncoding
|
|
42230
|
-
} : {}
|
|
42309
|
+
} : {},
|
|
42310
|
+
// Persist fail-closed even when piiWire is null (unusable salt/encoding).
|
|
42311
|
+
...this.state.piiWireBroken ? { piiWireBroken: true } : {}
|
|
42231
42312
|
};
|
|
42232
42313
|
}
|
|
42233
42314
|
hydrateFromSnapshot(snapshot, now = Date.now()) {
|
|
@@ -42237,14 +42318,17 @@ class RulesStore {
|
|
|
42237
42318
|
flags.set(flag.key, flag);
|
|
42238
42319
|
}
|
|
42239
42320
|
const expired = isConfigPayloadExpired(snapshot.expiresAt, now);
|
|
42321
|
+
const piiWire = piiWireOptionsFromPayload(snapshot);
|
|
42322
|
+
const piiWireBroken = snapshot.piiWireBroken === true || isPiiWireBroken(snapshot, piiWire, false);
|
|
42240
42323
|
this.state = {
|
|
42241
42324
|
version: snapshot.version,
|
|
42242
42325
|
expiresAt: snapshot.expiresAt,
|
|
42243
42326
|
flags,
|
|
42244
42327
|
segments: segmentsFromRecord(snapshot.segments),
|
|
42245
|
-
ready: !expired && flags.size > 0,
|
|
42246
|
-
needsFullConfig: expired || flags.size === 0,
|
|
42247
|
-
piiWire
|
|
42328
|
+
ready: !expired && flags.size > 0 && !piiWireBroken,
|
|
42329
|
+
needsFullConfig: expired || flags.size === 0 || piiWireBroken,
|
|
42330
|
+
piiWire,
|
|
42331
|
+
piiWireBroken
|
|
42248
42332
|
};
|
|
42249
42333
|
}
|
|
42250
42334
|
}
|
|
@@ -43215,9 +43299,10 @@ class FlagClient {
|
|
|
43215
43299
|
}
|
|
43216
43300
|
let hydratedRules = false;
|
|
43217
43301
|
if (this.configSync && this.rulesStore && this.enableOfflineCache) {
|
|
43302
|
+
clearCachedFlags(this.apiKey);
|
|
43218
43303
|
hydratedRules = await this.hydrateRulesFromCache();
|
|
43219
43304
|
}
|
|
43220
|
-
if (this.enableOfflineCache && !hydratedRules) {
|
|
43305
|
+
if (this.enableOfflineCache && !this.configSync && !hydratedRules) {
|
|
43221
43306
|
const cached = await Promise.resolve(
|
|
43222
43307
|
this.cacheAdapter.loadFlags(this.apiKey, this.cacheTTL)
|
|
43223
43308
|
);
|
|
@@ -43459,7 +43544,7 @@ class FlagClient {
|
|
|
43459
43544
|
*/
|
|
43460
43545
|
updateFlags(newFlags, fromShare = false) {
|
|
43461
43546
|
this.flags = newFlags;
|
|
43462
|
-
if (this.enableOfflineCache) {
|
|
43547
|
+
if (this.enableOfflineCache && !this.configSync) {
|
|
43463
43548
|
void Promise.resolve(
|
|
43464
43549
|
this.cacheAdapter.saveFlags(this.apiKey, newFlags)
|
|
43465
43550
|
);
|