pulse-updates 1.0.15 → 1.0.17
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/lib/commonjs/config.js +92 -10
- package/lib/commonjs/config.js.map +1 -1
- package/lib/module/config.js +87 -10
- package/lib/module/config.js.map +1 -1
- package/lib/typescript/config.d.ts +26 -0
- package/lib/typescript/config.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/publish.mjs +91 -33
- package/src/config.ts +103 -6
package/lib/commonjs/config.js
CHANGED
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.activateConfig = activateConfig;
|
|
6
7
|
exports.configureConfig = configureConfig;
|
|
7
8
|
exports.fetchConfig = fetchConfig;
|
|
8
9
|
exports.getAllConfig = getAllConfig;
|
|
9
10
|
exports.getConfigBoolean = getConfigBoolean;
|
|
10
11
|
exports.getConfigInfo = getConfigInfo;
|
|
12
|
+
exports.getConfigJson = getConfigJson;
|
|
13
|
+
exports.getConfigKeys = getConfigKeys;
|
|
11
14
|
exports.getConfigNumber = getConfigNumber;
|
|
15
|
+
exports.getConfigSource = getConfigSource;
|
|
12
16
|
exports.getConfigString = getConfigString;
|
|
13
17
|
exports.getConfigValue = getConfigValue;
|
|
18
|
+
exports.hasPendingConfig = hasPendingConfig;
|
|
14
19
|
exports.onConfigChange = onConfigChange;
|
|
15
20
|
exports.resetConfigForTests = resetConfigForTests;
|
|
16
21
|
exports.setConfigDefaults = setConfigDefaults;
|
|
@@ -52,6 +57,7 @@ let values = {};
|
|
|
52
57
|
let etag = null;
|
|
53
58
|
let fetchedAt = 0;
|
|
54
59
|
let source = 'defaults';
|
|
60
|
+
let pending = null;
|
|
55
61
|
let inFlight = null;
|
|
56
62
|
let pollTimer = null;
|
|
57
63
|
const listeners = new Set();
|
|
@@ -94,6 +100,10 @@ async function fetchConfig() {
|
|
|
94
100
|
if (!options) return false;
|
|
95
101
|
// Collapse concurrent calls (launch + resume can land together) onto one request.
|
|
96
102
|
if (inFlight) return inFlight;
|
|
103
|
+
const minInterval = options.minimumFetchIntervalMs ?? 0;
|
|
104
|
+
if (minInterval > 0 && fetchedAt > 0 && Date.now() - fetchedAt < minInterval) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
97
107
|
inFlight = (async () => {
|
|
98
108
|
const opts = options;
|
|
99
109
|
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
@@ -107,18 +117,19 @@ async function fetchConfig() {
|
|
|
107
117
|
if (response.status === 304) return false;
|
|
108
118
|
if (!response.ok) throw new Error(`Pulse config HTTP ${response.status}`);
|
|
109
119
|
const payload = await response.json();
|
|
110
|
-
const nextValues = payload?.values
|
|
111
|
-
values
|
|
120
|
+
const nextValues = payload?.values;
|
|
121
|
+
// A payload without a values object is a broken response, not "no keys": adopting
|
|
122
|
+
// it would blank every flag at once.
|
|
123
|
+
if (!nextValues || typeof nextValues !== 'object' || Array.isArray(nextValues)) {
|
|
124
|
+
throw new Error('Pulse config: malformed payload');
|
|
125
|
+
}
|
|
112
126
|
etag = response.headers?.get?.('etag') ?? null;
|
|
113
127
|
fetchedAt = Date.now();
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
});
|
|
120
|
-
notify();
|
|
121
|
-
return true;
|
|
128
|
+
if (opts.activateOnFetch === false) {
|
|
129
|
+
pending = nextValues;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
return applyValues(nextValues, opts);
|
|
122
133
|
} catch (error) {
|
|
123
134
|
// A failed refresh must never clear what we have: the whole point of the cache
|
|
124
135
|
// is that an unreachable server degrades to the last good config.
|
|
@@ -132,6 +143,22 @@ async function fetchConfig() {
|
|
|
132
143
|
return inFlight;
|
|
133
144
|
}
|
|
134
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Swap in the values from the last fetch made with activateOnFetch: false.
|
|
148
|
+
* Returns true when something actually changed.
|
|
149
|
+
*/
|
|
150
|
+
function activateConfig() {
|
|
151
|
+
if (!pending || !options) return false;
|
|
152
|
+
const next = pending;
|
|
153
|
+
pending = null;
|
|
154
|
+
return applyValues(next, options);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Whether a fetched-but-not-yet-applied payload is waiting. */
|
|
158
|
+
function hasPendingConfig() {
|
|
159
|
+
return pending !== null;
|
|
160
|
+
}
|
|
161
|
+
|
|
135
162
|
/**
|
|
136
163
|
* Fetch on launch, on every return to the foreground, and on a timer.
|
|
137
164
|
* Returns a function that stops both.
|
|
@@ -151,6 +178,35 @@ function startConfigAutoRefresh(appState) {
|
|
|
151
178
|
stopPolling();
|
|
152
179
|
};
|
|
153
180
|
}
|
|
181
|
+
function applyValues(next, opts) {
|
|
182
|
+
const changed = !shallowEqual(values, next);
|
|
183
|
+
values = next;
|
|
184
|
+
source = 'remote';
|
|
185
|
+
writeCache(opts.storage, {
|
|
186
|
+
values,
|
|
187
|
+
etag,
|
|
188
|
+
fetchedAt
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Listeners drive re-renders and gate re-evaluation: firing them for an identical
|
|
192
|
+
// payload is pure churn, and the 200-with-same-content case is common enough
|
|
193
|
+
// (a proxy that drops the ETag) to be worth checking.
|
|
194
|
+
if (changed) notify();
|
|
195
|
+
return changed;
|
|
196
|
+
}
|
|
197
|
+
function shallowEqual(a, b) {
|
|
198
|
+
const aKeys = Object.keys(a);
|
|
199
|
+
const bKeys = Object.keys(b);
|
|
200
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
201
|
+
return aKeys.every(k => {
|
|
202
|
+
const av = a[k];
|
|
203
|
+
const bv = b[k];
|
|
204
|
+
if (av !== null && bv !== null && typeof av === 'object' && typeof bv === 'object') {
|
|
205
|
+
return JSON.stringify(av) === JSON.stringify(bv);
|
|
206
|
+
}
|
|
207
|
+
return av === bv;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
154
210
|
function stopPolling() {
|
|
155
211
|
if (pollTimer) {
|
|
156
212
|
clearInterval(pollTimer);
|
|
@@ -199,6 +255,31 @@ function getAllConfig() {
|
|
|
199
255
|
...values
|
|
200
256
|
};
|
|
201
257
|
}
|
|
258
|
+
|
|
259
|
+
/** Parsed object/array value, or the default. Null when neither is usable. */
|
|
260
|
+
function getConfigJson(key) {
|
|
261
|
+
const value = getConfigValue(key);
|
|
262
|
+
if (value === null || value === undefined) return null;
|
|
263
|
+
if (typeof value === 'object') return value;
|
|
264
|
+
if (typeof value === 'string') {
|
|
265
|
+
try {
|
|
266
|
+
return JSON.parse(value);
|
|
267
|
+
} catch {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Where this key's value came from — the answer to "why is this flag off?". */
|
|
275
|
+
function getConfigSource(key) {
|
|
276
|
+
if (Object.prototype.hasOwnProperty.call(values, key) && values[key] !== null) return 'remote';
|
|
277
|
+
if (Object.prototype.hasOwnProperty.call(defaults, key)) return 'default';
|
|
278
|
+
return 'missing';
|
|
279
|
+
}
|
|
280
|
+
function getConfigKeys() {
|
|
281
|
+
return Object.keys(getAllConfig()).sort();
|
|
282
|
+
}
|
|
202
283
|
function onConfigChange(listener) {
|
|
203
284
|
listeners.add(listener);
|
|
204
285
|
return () => listeners.delete(listener);
|
|
@@ -223,6 +304,7 @@ function resetConfigForTests() {
|
|
|
223
304
|
fetchedAt = 0;
|
|
224
305
|
source = 'defaults';
|
|
225
306
|
inFlight = null;
|
|
307
|
+
pending = null;
|
|
226
308
|
listeners.clear();
|
|
227
309
|
stopPolling();
|
|
228
310
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["STORAGE_KEY","DEFAULT_POLL_MS","DEFAULT_TIMEOUT_MS","options","defaults","values","etag","fetchedAt","source","inFlight","pollTimer","listeners","Set","configureConfig","opts","cached","readCache","storage","setConfigDefaults","more","fetchConfig","controller","AbortController","timer","setTimeout","abort","timeoutMs","response","fetch","url","method","headers","buildHeaders","signal","status","ok","Error","payload","json","nextValues","get","Date","now","writeCache","notify","error","onError","clearTimeout","startConfigAutoRefresh","appState","subscription","addEventListener","state","interval","pollIntervalMs","stopPolling","setInterval","remove","clearInterval","getConfigValue","key","Object","prototype","hasOwnProperty","call","fallback","undefined","getConfigBoolean","value","toLowerCase","getConfigNumber","parsed","Number","isNaN","getConfigString","String","getAllConfig","onConfigChange","listener","add","delete","getConfigInfo","keyCount","keys","length","resetConfigForTests","clear","currentEtag","ctx","getContext","Accept","platform","appVersion","osVersion","language","deviceId","userAttributes","JSON","stringify","raw","getString","parse","set","snapshot","forEach"],"sourceRoot":"../../src","sources":["config.ts"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA;AACA;AACA;AACA;AACA;;AAiCA,MAAMA,WAAW,GAAG,iBAAiB;AACrC,MAAMC,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI;AACrC,MAAMC,kBAAkB,GAAG,MAAM;AAEjC,IAAIC,OAA6B,GAAG,IAAI;AACxC,IAAIC,QAAqC,GAAG,CAAC,CAAC;AAC9C,IAAIC,MAAmC,GAAG,CAAC,CAAC;AAC5C,IAAIC,IAAmB,GAAG,IAAI;AAC9B,IAAIC,SAAS,GAAG,CAAC;AACjB,IAAIC,MAAuC,GAAG,UAAU;AACxD,IAAIC,QAAiC,GAAG,IAAI;AAC5C,IAAIC,SAAgD,GAAG,IAAI;AAC3D,MAAMC,SAAS,GAAG,IAAIC,GAAG,CAAgD,CAAC;;AAE1E;AACA;AACA;AACA;AACA;AACO,SAASC,eAAeA,CAACC,IAAmB,EAAQ;EACzDX,OAAO,GAAGW,IAAI;EACdV,QAAQ,GAAG;IAAE,IAAIU,IAAI,CAACV,QAAQ,IAAI,CAAC,CAAC;EAAE,CAAC;EAEvC,MAAMW,MAAM,GAAGC,SAAS,CAACF,IAAI,CAACG,OAAO,CAAC;EACtC,IAAIF,MAAM,EAAE;IACVV,MAAM,GAAGU,MAAM,CAACV,MAAM;IACtBC,IAAI,GAAGS,MAAM,CAACT,IAAI;IAClBC,SAAS,GAAGQ,MAAM,CAACR,SAAS;IAC5BC,MAAM,GAAG,OAAO;EAClB;AACF;;AAEA;AACO,SAASU,iBAAiBA,CAACC,IAAiC,EAAQ;EACzEf,QAAQ,GAAG;IAAE,GAAGA,QAAQ;IAAE,GAAGe;EAAK,CAAC;AACrC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAeC,WAAWA,CAAA,EAAqB;EACpD,IAAI,CAACjB,OAAO,EAAE,OAAO,KAAK;EAC1B;EACA,IAAIM,QAAQ,EAAE,OAAOA,QAAQ;EAE7BA,QAAQ,GAAG,CAAC,YAAY;IACtB,MAAMK,IAAI,GAAGX,OAAQ;IACrB,MAAMkB,UAAU,GAAG,OAAOC,eAAe,KAAK,WAAW,GAAG,IAAIA,eAAe,CAAC,CAAC,GAAG,IAAI;IACxF,MAAMC,KAAK,GAAGF,UAAU,GACpBG,UAAU,CAAC,MAAMH,UAAU,CAACI,KAAK,CAAC,CAAC,EAAEX,IAAI,CAACY,SAAS,IAAIxB,kBAAkB,CAAC,GAC1E,IAAI;IAER,IAAI;MACF,MAAMyB,QAAQ,GAAG,MAAMC,KAAK,CAACd,IAAI,CAACe,GAAG,EAAE;QACrCC,MAAM,EAAE,KAAK;QACbC,OAAO,EAAEC,YAAY,CAAClB,IAAI,EAAER,IAAI,CAAC;QACjC2B,MAAM,EAAEZ,UAAU,EAAEY;MACtB,CAAC,CAAC;MAEF,IAAIN,QAAQ,CAACO,MAAM,KAAK,GAAG,EAAE,OAAO,KAAK;MACzC,IAAI,CAACP,QAAQ,CAACQ,EAAE,EAAE,MAAM,IAAIC,KAAK,CAAC,qBAAqBT,QAAQ,CAACO,MAAM,EAAE,CAAC;MAEzE,MAAMG,OAAO,GAAG,MAAMV,QAAQ,CAACW,IAAI,CAAC,CAAC;MACrC,MAAMC,UAAU,GAAIF,OAAO,EAAEhC,MAAM,IAAI,CAAC,CAAiC;MAEzEA,MAAM,GAAGkC,UAAU;MACnBjC,IAAI,GAAGqB,QAAQ,CAACI,OAAO,EAAES,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI;MAC9CjC,SAAS,GAAGkC,IAAI,CAACC,GAAG,CAAC,CAAC;MACtBlC,MAAM,GAAG,QAAQ;MAEjBmC,UAAU,CAAC7B,IAAI,CAACG,OAAO,EAAE;QAAEZ,MAAM;QAAEC,IAAI;QAAEC;MAAU,CAAC,CAAC;MACrDqC,MAAM,CAAC,CAAC;MACR,OAAO,IAAI;IACb,CAAC,CAAC,OAAOC,KAAK,EAAE;MACd;MACA;MACA/B,IAAI,CAACgC,OAAO,GAAGD,KAAK,CAAC;MACrB,OAAO,KAAK;IACd,CAAC,SAAS;MACR,IAAItB,KAAK,EAAEwB,YAAY,CAACxB,KAAK,CAAC;MAC9Bd,QAAQ,GAAG,IAAI;IACjB;EACF,CAAC,EAAE,CAAC;EAEJ,OAAOA,QAAQ;AACjB;;AAEA;AACA;AACA;AACA;AACO,SAASuC,sBAAsBA,CAACC,QAEtC,EAAc;EACb,KAAK7B,WAAW,CAAC,CAAC;EAElB,MAAM8B,YAAY,GAAGD,QAAQ,EAAEE,gBAAgB,CAAC,QAAQ,EAAGC,KAAK,IAAK;IACnE,IAAIA,KAAK,KAAK,QAAQ,EAAE,KAAKhC,WAAW,CAAC,CAAC;EAC5C,CAAC,CAAC;EAEF,MAAMiC,QAAQ,GAAGlD,OAAO,EAAEmD,cAAc,IAAIrD,eAAe;EAC3D,IAAIoD,QAAQ,GAAG,CAAC,EAAE;IAChBE,WAAW,CAAC,CAAC;IACb7C,SAAS,GAAG8C,WAAW,CAAC,MAAM,KAAKpC,WAAW,CAAC,CAAC,EAAEiC,QAAQ,CAAC;EAC7D;EAEA,OAAO,MAAM;IACXH,YAAY,EAAEO,MAAM,CAAC,CAAC;IACtBF,WAAW,CAAC,CAAC;EACf,CAAC;AACH;AAEA,SAASA,WAAWA,CAAA,EAAS;EAC3B,IAAI7C,SAAS,EAAE;IACbgD,aAAa,CAAChD,SAAS,CAAC;IACxBA,SAAS,GAAG,IAAI;EAClB;AACF;;AAEA;;AAEA;AACO,SAASiD,cAAcA,CAACC,GAAW,EAAe;EACvD,IAAIC,MAAM,CAACC,SAAS,CAACC,cAAc,CAACC,IAAI,CAAC3D,MAAM,EAAEuD,GAAG,CAAC,IAAIvD,MAAM,CAACuD,GAAG,CAAC,KAAK,IAAI,EAAE;IAC7E,OAAOvD,MAAM,CAACuD,GAAG,CAAC;EACpB;EACA,MAAMK,QAAQ,GAAG7D,QAAQ,CAACwD,GAAG,CAAC;EAC9B,OAAOK,QAAQ,KAAKC,SAAS,GAAG,IAAI,GAAGD,QAAQ;AACjD;AAEO,SAASE,gBAAgBA,CAACP,GAAW,EAAW;EACrD,MAAMQ,KAAK,GAAGT,cAAc,CAACC,GAAG,CAAC;EACjC,IAAI,OAAOQ,KAAK,KAAK,SAAS,EAAE,OAAOA,KAAK;EAC5C;EACA,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK,CAACC,WAAW,CAAC,CAAC,KAAK,MAAM;EACpE,IAAI,OAAOD,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK,KAAK,CAAC;EACjD,OAAO,KAAK;AACd;AAEO,SAASE,eAAeA,CAACV,GAAW,EAAU;EACnD,MAAMQ,KAAK,GAAGT,cAAc,CAACC,GAAG,CAAC;EACjC,IAAI,OAAOQ,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE;IAC7B,MAAMG,MAAM,GAAGC,MAAM,CAACJ,KAAK,CAAC;IAC5B,IAAI,CAACI,MAAM,CAACC,KAAK,CAACF,MAAM,CAAC,EAAE,OAAOA,MAAM;EAC1C;EACA,OAAO,CAAC;AACV;AAEO,SAASG,eAAeA,CAACd,GAAW,EAAU;EACnD,MAAMQ,KAAK,GAAGT,cAAc,CAACC,GAAG,CAAC;EACjC,IAAI,OAAOQ,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAIA,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKF,SAAS,EAAE,OAAO,EAAE;EACpD,OAAOS,MAAM,CAACP,KAAK,CAAC;AACtB;;AAEA;AACO,SAASQ,YAAYA,CAAA,EAAgC;EAC1D,OAAO;IAAE,GAAGxE,QAAQ;IAAE,GAAGC;EAAO,CAAC;AACnC;AAEO,SAASwE,cAAcA,CAACC,QAAuD,EAAc;EAClGnE,SAAS,CAACoE,GAAG,CAACD,QAAQ,CAAC;EACvB,OAAO,MAAMnE,SAAS,CAACqE,MAAM,CAACF,QAAQ,CAAC;AACzC;;AAEA;AACO,SAASG,aAAaA,CAAA,EAK3B;EACA,OAAO;IAAEzE,MAAM;IAAED,SAAS;IAAED,IAAI;IAAE4E,QAAQ,EAAErB,MAAM,CAACsB,IAAI,CAACP,YAAY,CAAC,CAAC,CAAC,CAACQ;EAAO,CAAC;AAClF;;AAEA;AACO,SAASC,mBAAmBA,CAAA,EAAS;EAC1ClF,OAAO,GAAG,IAAI;EACdC,QAAQ,GAAG,CAAC,CAAC;EACbC,MAAM,GAAG,CAAC,CAAC;EACXC,IAAI,GAAG,IAAI;EACXC,SAAS,GAAG,CAAC;EACbC,MAAM,GAAG,UAAU;EACnBC,QAAQ,GAAG,IAAI;EACfE,SAAS,CAAC2E,KAAK,CAAC,CAAC;EACjB/B,WAAW,CAAC,CAAC;AACf;;AAEA;;AAEA,SAASvB,YAAYA,CAAClB,IAAmB,EAAEyE,WAA0B,EAA0B;EAC7F,MAAMC,GAAG,GAAG1E,IAAI,CAAC2E,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC;EACrC,MAAM1D,OAA+B,GAAG;IAAE2D,MAAM,EAAE;EAAmB,CAAC;EAEtE,IAAIF,GAAG,CAACG,QAAQ,EAAE5D,OAAO,CAAC,kBAAkB,CAAC,GAAGyD,GAAG,CAACG,QAAQ;EAC5D,IAAIH,GAAG,CAACI,UAAU,EAAE7D,OAAO,CAAC,qBAAqB,CAAC,GAAGyD,GAAG,CAACI,UAAU;EACnE,IAAIJ,GAAG,CAACK,SAAS,EAAE9D,OAAO,CAAC,oBAAoB,CAAC,GAAGyD,GAAG,CAACK,SAAS;EAChE,IAAIL,GAAG,CAACM,QAAQ,EAAE/D,OAAO,CAAC,kBAAkB,CAAC,GAAGyD,GAAG,CAACM,QAAQ;EAC5D,IAAIN,GAAG,CAACO,QAAQ,EAAEhE,OAAO,CAAC,iBAAiB,CAAC,GAAGyD,GAAG,CAACO,QAAQ;EAC3D,IAAIP,GAAG,CAACQ,cAAc,IAAInC,MAAM,CAACsB,IAAI,CAACK,GAAG,CAACQ,cAAc,CAAC,CAACZ,MAAM,GAAG,CAAC,EAAE;IACpErD,OAAO,CAAC,yBAAyB,CAAC,GAAGkE,IAAI,CAACC,SAAS,CAACV,GAAG,CAACQ,cAAc,CAAC;EACzE;EACA;EACA;;EAEA,IAAIT,WAAW,EAAExD,OAAO,CAAC,eAAe,CAAC,GAAGwD,WAAW;EACvD,OAAOxD,OAAO;AAChB;AAEA,SAASf,SAASA,CAACC,OAAuB,EAAwB;EAChE,IAAI,CAACA,OAAO,EAAE,OAAO,IAAI;EACzB,IAAI;IACF,MAAMkF,GAAG,GAAGlF,OAAO,CAACmF,SAAS,CAACpG,WAAW,CAAC;IAC1C,IAAI,CAACmG,GAAG,EAAE,OAAO,IAAI;IACrB,MAAM5B,MAAM,GAAG0B,IAAI,CAACI,KAAK,CAACF,GAAG,CAAkB;IAC/C,IAAI,CAAC5B,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAI,CAACA,MAAM,CAAClE,MAAM,EAAE,OAAO,IAAI;IACxE,OAAOkE,MAAM;EACf,CAAC,CAAC,MAAM;IACN;IACA,OAAO,IAAI;EACb;AACF;AAEA,SAAS5B,UAAUA,CAAC1B,OAAkC,EAAEoB,OAAsB,EAAQ;EACpF,IAAI,CAACpB,OAAO,EAAE;EACd,IAAI;IACFA,OAAO,CAACqF,GAAG,CAACtG,WAAW,EAAEiG,IAAI,CAACC,SAAS,CAAC7D,OAAO,CAAC,CAAC;EACnD,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;AAEA,SAASO,MAAMA,CAAA,EAAS;EACtB,MAAM2D,QAAQ,GAAG3B,YAAY,CAAC,CAAC;EAC/BjE,SAAS,CAAC6F,OAAO,CAAE1B,QAAQ,IAAK;IAC9B,IAAI;MACFA,QAAQ,CAACyB,QAAQ,CAAC;IACpB,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ,CAAC,CAAC;AACJ","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["STORAGE_KEY","DEFAULT_POLL_MS","DEFAULT_TIMEOUT_MS","options","defaults","values","etag","fetchedAt","source","pending","inFlight","pollTimer","listeners","Set","configureConfig","opts","cached","readCache","storage","setConfigDefaults","more","fetchConfig","minInterval","minimumFetchIntervalMs","Date","now","controller","AbortController","timer","setTimeout","abort","timeoutMs","response","fetch","url","method","headers","buildHeaders","signal","status","ok","Error","payload","json","nextValues","Array","isArray","get","activateOnFetch","applyValues","error","onError","clearTimeout","activateConfig","next","hasPendingConfig","startConfigAutoRefresh","appState","subscription","addEventListener","state","interval","pollIntervalMs","stopPolling","setInterval","remove","changed","shallowEqual","writeCache","notify","a","b","aKeys","Object","keys","bKeys","length","every","k","av","bv","JSON","stringify","clearInterval","getConfigValue","key","prototype","hasOwnProperty","call","fallback","undefined","getConfigBoolean","value","toLowerCase","getConfigNumber","parsed","Number","isNaN","getConfigString","String","getAllConfig","getConfigJson","parse","getConfigSource","getConfigKeys","sort","onConfigChange","listener","add","delete","getConfigInfo","keyCount","resetConfigForTests","clear","currentEtag","ctx","getContext","Accept","platform","appVersion","osVersion","language","deviceId","userAttributes","raw","getString","set","snapshot","forEach"],"sourceRoot":"../../src","sources":["config.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/config.js
CHANGED
|
@@ -35,6 +35,7 @@ let values = {};
|
|
|
35
35
|
let etag = null;
|
|
36
36
|
let fetchedAt = 0;
|
|
37
37
|
let source = 'defaults';
|
|
38
|
+
let pending = null;
|
|
38
39
|
let inFlight = null;
|
|
39
40
|
let pollTimer = null;
|
|
40
41
|
const listeners = new Set();
|
|
@@ -77,6 +78,10 @@ export async function fetchConfig() {
|
|
|
77
78
|
if (!options) return false;
|
|
78
79
|
// Collapse concurrent calls (launch + resume can land together) onto one request.
|
|
79
80
|
if (inFlight) return inFlight;
|
|
81
|
+
const minInterval = options.minimumFetchIntervalMs ?? 0;
|
|
82
|
+
if (minInterval > 0 && fetchedAt > 0 && Date.now() - fetchedAt < minInterval) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
80
85
|
inFlight = (async () => {
|
|
81
86
|
const opts = options;
|
|
82
87
|
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
@@ -90,18 +95,19 @@ export async function fetchConfig() {
|
|
|
90
95
|
if (response.status === 304) return false;
|
|
91
96
|
if (!response.ok) throw new Error(`Pulse config HTTP ${response.status}`);
|
|
92
97
|
const payload = await response.json();
|
|
93
|
-
const nextValues = payload?.values
|
|
94
|
-
values
|
|
98
|
+
const nextValues = payload?.values;
|
|
99
|
+
// A payload without a values object is a broken response, not "no keys": adopting
|
|
100
|
+
// it would blank every flag at once.
|
|
101
|
+
if (!nextValues || typeof nextValues !== 'object' || Array.isArray(nextValues)) {
|
|
102
|
+
throw new Error('Pulse config: malformed payload');
|
|
103
|
+
}
|
|
95
104
|
etag = response.headers?.get?.('etag') ?? null;
|
|
96
105
|
fetchedAt = Date.now();
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
});
|
|
103
|
-
notify();
|
|
104
|
-
return true;
|
|
106
|
+
if (opts.activateOnFetch === false) {
|
|
107
|
+
pending = nextValues;
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return applyValues(nextValues, opts);
|
|
105
111
|
} catch (error) {
|
|
106
112
|
// A failed refresh must never clear what we have: the whole point of the cache
|
|
107
113
|
// is that an unreachable server degrades to the last good config.
|
|
@@ -115,6 +121,22 @@ export async function fetchConfig() {
|
|
|
115
121
|
return inFlight;
|
|
116
122
|
}
|
|
117
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Swap in the values from the last fetch made with activateOnFetch: false.
|
|
126
|
+
* Returns true when something actually changed.
|
|
127
|
+
*/
|
|
128
|
+
export function activateConfig() {
|
|
129
|
+
if (!pending || !options) return false;
|
|
130
|
+
const next = pending;
|
|
131
|
+
pending = null;
|
|
132
|
+
return applyValues(next, options);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Whether a fetched-but-not-yet-applied payload is waiting. */
|
|
136
|
+
export function hasPendingConfig() {
|
|
137
|
+
return pending !== null;
|
|
138
|
+
}
|
|
139
|
+
|
|
118
140
|
/**
|
|
119
141
|
* Fetch on launch, on every return to the foreground, and on a timer.
|
|
120
142
|
* Returns a function that stops both.
|
|
@@ -134,6 +156,35 @@ export function startConfigAutoRefresh(appState) {
|
|
|
134
156
|
stopPolling();
|
|
135
157
|
};
|
|
136
158
|
}
|
|
159
|
+
function applyValues(next, opts) {
|
|
160
|
+
const changed = !shallowEqual(values, next);
|
|
161
|
+
values = next;
|
|
162
|
+
source = 'remote';
|
|
163
|
+
writeCache(opts.storage, {
|
|
164
|
+
values,
|
|
165
|
+
etag,
|
|
166
|
+
fetchedAt
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Listeners drive re-renders and gate re-evaluation: firing them for an identical
|
|
170
|
+
// payload is pure churn, and the 200-with-same-content case is common enough
|
|
171
|
+
// (a proxy that drops the ETag) to be worth checking.
|
|
172
|
+
if (changed) notify();
|
|
173
|
+
return changed;
|
|
174
|
+
}
|
|
175
|
+
function shallowEqual(a, b) {
|
|
176
|
+
const aKeys = Object.keys(a);
|
|
177
|
+
const bKeys = Object.keys(b);
|
|
178
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
179
|
+
return aKeys.every(k => {
|
|
180
|
+
const av = a[k];
|
|
181
|
+
const bv = b[k];
|
|
182
|
+
if (av !== null && bv !== null && typeof av === 'object' && typeof bv === 'object') {
|
|
183
|
+
return JSON.stringify(av) === JSON.stringify(bv);
|
|
184
|
+
}
|
|
185
|
+
return av === bv;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
137
188
|
function stopPolling() {
|
|
138
189
|
if (pollTimer) {
|
|
139
190
|
clearInterval(pollTimer);
|
|
@@ -182,6 +233,31 @@ export function getAllConfig() {
|
|
|
182
233
|
...values
|
|
183
234
|
};
|
|
184
235
|
}
|
|
236
|
+
|
|
237
|
+
/** Parsed object/array value, or the default. Null when neither is usable. */
|
|
238
|
+
export function getConfigJson(key) {
|
|
239
|
+
const value = getConfigValue(key);
|
|
240
|
+
if (value === null || value === undefined) return null;
|
|
241
|
+
if (typeof value === 'object') return value;
|
|
242
|
+
if (typeof value === 'string') {
|
|
243
|
+
try {
|
|
244
|
+
return JSON.parse(value);
|
|
245
|
+
} catch {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Where this key's value came from — the answer to "why is this flag off?". */
|
|
253
|
+
export function getConfigSource(key) {
|
|
254
|
+
if (Object.prototype.hasOwnProperty.call(values, key) && values[key] !== null) return 'remote';
|
|
255
|
+
if (Object.prototype.hasOwnProperty.call(defaults, key)) return 'default';
|
|
256
|
+
return 'missing';
|
|
257
|
+
}
|
|
258
|
+
export function getConfigKeys() {
|
|
259
|
+
return Object.keys(getAllConfig()).sort();
|
|
260
|
+
}
|
|
185
261
|
export function onConfigChange(listener) {
|
|
186
262
|
listeners.add(listener);
|
|
187
263
|
return () => listeners.delete(listener);
|
|
@@ -206,6 +282,7 @@ export function resetConfigForTests() {
|
|
|
206
282
|
fetchedAt = 0;
|
|
207
283
|
source = 'defaults';
|
|
208
284
|
inFlight = null;
|
|
285
|
+
pending = null;
|
|
209
286
|
listeners.clear();
|
|
210
287
|
stopPolling();
|
|
211
288
|
}
|
package/lib/module/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["STORAGE_KEY","DEFAULT_POLL_MS","DEFAULT_TIMEOUT_MS","options","defaults","values","etag","fetchedAt","source","inFlight","pollTimer","listeners","Set","configureConfig","opts","cached","readCache","storage","setConfigDefaults","more","fetchConfig","controller","AbortController","timer","setTimeout","abort","timeoutMs","response","fetch","url","method","headers","buildHeaders","signal","status","ok","Error","payload","json","nextValues","get","Date","now","writeCache","notify","error","onError","clearTimeout","startConfigAutoRefresh","appState","subscription","addEventListener","state","interval","pollIntervalMs","stopPolling","setInterval","remove","clearInterval","getConfigValue","key","Object","prototype","hasOwnProperty","call","fallback","undefined","getConfigBoolean","value","toLowerCase","getConfigNumber","parsed","Number","isNaN","getConfigString","String","getAllConfig","onConfigChange","listener","add","delete","getConfigInfo","keyCount","keys","length","resetConfigForTests","clear","currentEtag","ctx","getContext","Accept","platform","appVersion","osVersion","language","deviceId","userAttributes","JSON","stringify","raw","getString","parse","set","snapshot","forEach"],"sourceRoot":"../../src","sources":["config.ts"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["STORAGE_KEY","DEFAULT_POLL_MS","DEFAULT_TIMEOUT_MS","options","defaults","values","etag","fetchedAt","source","pending","inFlight","pollTimer","listeners","Set","configureConfig","opts","cached","readCache","storage","setConfigDefaults","more","fetchConfig","minInterval","minimumFetchIntervalMs","Date","now","controller","AbortController","timer","setTimeout","abort","timeoutMs","response","fetch","url","method","headers","buildHeaders","signal","status","ok","Error","payload","json","nextValues","Array","isArray","get","activateOnFetch","applyValues","error","onError","clearTimeout","activateConfig","next","hasPendingConfig","startConfigAutoRefresh","appState","subscription","addEventListener","state","interval","pollIntervalMs","stopPolling","setInterval","remove","changed","shallowEqual","writeCache","notify","a","b","aKeys","Object","keys","bKeys","length","every","k","av","bv","JSON","stringify","clearInterval","getConfigValue","key","prototype","hasOwnProperty","call","fallback","undefined","getConfigBoolean","value","toLowerCase","getConfigNumber","parsed","Number","isNaN","getConfigString","String","getAllConfig","getConfigJson","parse","getConfigSource","getConfigKeys","sort","onConfigChange","listener","add","delete","getConfigInfo","keyCount","resetConfigForTests","clear","currentEtag","ctx","getContext","Accept","platform","appVersion","osVersion","language","deviceId","userAttributes","raw","getString","set","snapshot","forEach"],"sourceRoot":"../../src","sources":["config.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA;AACA;AACA;AACA;AACA;;AA+CA,MAAMA,WAAW,GAAG,iBAAiB;AACrC,MAAMC,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI;AACrC,MAAMC,kBAAkB,GAAG,MAAM;AAEjC,IAAIC,OAA6B,GAAG,IAAI;AACxC,IAAIC,QAAqC,GAAG,CAAC,CAAC;AAC9C,IAAIC,MAAmC,GAAG,CAAC,CAAC;AAC5C,IAAIC,IAAmB,GAAG,IAAI;AAC9B,IAAIC,SAAS,GAAG,CAAC;AACjB,IAAIC,MAAuC,GAAG,UAAU;AACxD,IAAIC,OAA2C,GAAG,IAAI;AACtD,IAAIC,QAAiC,GAAG,IAAI;AAC5C,IAAIC,SAAgD,GAAG,IAAI;AAC3D,MAAMC,SAAS,GAAG,IAAIC,GAAG,CAAgD,CAAC;;AAE1E;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAACC,IAAmB,EAAQ;EACzDZ,OAAO,GAAGY,IAAI;EACdX,QAAQ,GAAG;IAAE,IAAIW,IAAI,CAACX,QAAQ,IAAI,CAAC,CAAC;EAAE,CAAC;EAEvC,MAAMY,MAAM,GAAGC,SAAS,CAACF,IAAI,CAACG,OAAO,CAAC;EACtC,IAAIF,MAAM,EAAE;IACVX,MAAM,GAAGW,MAAM,CAACX,MAAM;IACtBC,IAAI,GAAGU,MAAM,CAACV,IAAI;IAClBC,SAAS,GAAGS,MAAM,CAACT,SAAS;IAC5BC,MAAM,GAAG,OAAO;EAClB;AACF;;AAEA;AACA,OAAO,SAASW,iBAAiBA,CAACC,IAAiC,EAAQ;EACzEhB,QAAQ,GAAG;IAAE,GAAGA,QAAQ;IAAE,GAAGgB;EAAK,CAAC;AACrC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,WAAWA,CAAA,EAAqB;EACpD,IAAI,CAAClB,OAAO,EAAE,OAAO,KAAK;EAC1B;EACA,IAAIO,QAAQ,EAAE,OAAOA,QAAQ;EAE7B,MAAMY,WAAW,GAAGnB,OAAO,CAACoB,sBAAsB,IAAI,CAAC;EACvD,IAAID,WAAW,GAAG,CAAC,IAAIf,SAAS,GAAG,CAAC,IAAIiB,IAAI,CAACC,GAAG,CAAC,CAAC,GAAGlB,SAAS,GAAGe,WAAW,EAAE;IAC5E,OAAO,KAAK;EACd;EAEAZ,QAAQ,GAAG,CAAC,YAAY;IACtB,MAAMK,IAAI,GAAGZ,OAAQ;IACrB,MAAMuB,UAAU,GAAG,OAAOC,eAAe,KAAK,WAAW,GAAG,IAAIA,eAAe,CAAC,CAAC,GAAG,IAAI;IACxF,MAAMC,KAAK,GAAGF,UAAU,GACpBG,UAAU,CAAC,MAAMH,UAAU,CAACI,KAAK,CAAC,CAAC,EAAEf,IAAI,CAACgB,SAAS,IAAI7B,kBAAkB,CAAC,GAC1E,IAAI;IAER,IAAI;MACF,MAAM8B,QAAQ,GAAG,MAAMC,KAAK,CAAClB,IAAI,CAACmB,GAAG,EAAE;QACrCC,MAAM,EAAE,KAAK;QACbC,OAAO,EAAEC,YAAY,CAACtB,IAAI,EAAET,IAAI,CAAC;QACjCgC,MAAM,EAAEZ,UAAU,EAAEY;MACtB,CAAC,CAAC;MAEF,IAAIN,QAAQ,CAACO,MAAM,KAAK,GAAG,EAAE,OAAO,KAAK;MACzC,IAAI,CAACP,QAAQ,CAACQ,EAAE,EAAE,MAAM,IAAIC,KAAK,CAAC,qBAAqBT,QAAQ,CAACO,MAAM,EAAE,CAAC;MAEzE,MAAMG,OAAO,GAAG,MAAMV,QAAQ,CAACW,IAAI,CAAC,CAAC;MACrC,MAAMC,UAAU,GAAGF,OAAO,EAAErC,MAAM;MAClC;MACA;MACA,IAAI,CAACuC,UAAU,IAAI,OAAOA,UAAU,KAAK,QAAQ,IAAIC,KAAK,CAACC,OAAO,CAACF,UAAU,CAAC,EAAE;QAC9E,MAAM,IAAIH,KAAK,CAAC,iCAAiC,CAAC;MACpD;MAEAnC,IAAI,GAAG0B,QAAQ,CAACI,OAAO,EAAEW,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI;MAC9CxC,SAAS,GAAGiB,IAAI,CAACC,GAAG,CAAC,CAAC;MAEtB,IAAIV,IAAI,CAACiC,eAAe,KAAK,KAAK,EAAE;QAClCvC,OAAO,GAAGmC,UAAyC;QACnD,OAAO,KAAK;MACd;MAEA,OAAOK,WAAW,CAACL,UAAU,EAAiC7B,IAAI,CAAC;IACrE,CAAC,CAAC,OAAOmC,KAAK,EAAE;MACd;MACA;MACAnC,IAAI,CAACoC,OAAO,GAAGD,KAAK,CAAC;MACrB,OAAO,KAAK;IACd,CAAC,SAAS;MACR,IAAItB,KAAK,EAAEwB,YAAY,CAACxB,KAAK,CAAC;MAC9BlB,QAAQ,GAAG,IAAI;IACjB;EACF,CAAC,EAAE,CAAC;EAEJ,OAAOA,QAAQ;AACjB;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAAS2C,cAAcA,CAAA,EAAY;EACxC,IAAI,CAAC5C,OAAO,IAAI,CAACN,OAAO,EAAE,OAAO,KAAK;EACtC,MAAMmD,IAAI,GAAG7C,OAAO;EACpBA,OAAO,GAAG,IAAI;EACd,OAAOwC,WAAW,CAACK,IAAI,EAAEnD,OAAO,CAAC;AACnC;;AAEA;AACA,OAAO,SAASoD,gBAAgBA,CAAA,EAAY;EAC1C,OAAO9C,OAAO,KAAK,IAAI;AACzB;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAAS+C,sBAAsBA,CAACC,QAEtC,EAAc;EACb,KAAKpC,WAAW,CAAC,CAAC;EAElB,MAAMqC,YAAY,GAAGD,QAAQ,EAAEE,gBAAgB,CAAC,QAAQ,EAAGC,KAAK,IAAK;IACnE,IAAIA,KAAK,KAAK,QAAQ,EAAE,KAAKvC,WAAW,CAAC,CAAC;EAC5C,CAAC,CAAC;EAEF,MAAMwC,QAAQ,GAAG1D,OAAO,EAAE2D,cAAc,IAAI7D,eAAe;EAC3D,IAAI4D,QAAQ,GAAG,CAAC,EAAE;IAChBE,WAAW,CAAC,CAAC;IACbpD,SAAS,GAAGqD,WAAW,CAAC,MAAM,KAAK3C,WAAW,CAAC,CAAC,EAAEwC,QAAQ,CAAC;EAC7D;EAEA,OAAO,MAAM;IACXH,YAAY,EAAEO,MAAM,CAAC,CAAC;IACtBF,WAAW,CAAC,CAAC;EACf,CAAC;AACH;AAEA,SAASd,WAAWA,CAACK,IAAiC,EAAEvC,IAAmB,EAAW;EACpF,MAAMmD,OAAO,GAAG,CAACC,YAAY,CAAC9D,MAAM,EAAEiD,IAAI,CAAC;EAE3CjD,MAAM,GAAGiD,IAAI;EACb9C,MAAM,GAAG,QAAQ;EACjB4D,UAAU,CAACrD,IAAI,CAACG,OAAO,EAAE;IAAEb,MAAM;IAAEC,IAAI;IAAEC;EAAU,CAAC,CAAC;;EAErD;EACA;EACA;EACA,IAAI2D,OAAO,EAAEG,MAAM,CAAC,CAAC;EACrB,OAAOH,OAAO;AAChB;AAEA,SAASC,YAAYA,CAACG,CAA8B,EAAEC,CAA8B,EAAW;EAC7F,MAAMC,KAAK,GAAGC,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC;EAC5B,MAAMK,KAAK,GAAGF,MAAM,CAACC,IAAI,CAACH,CAAC,CAAC;EAC5B,IAAIC,KAAK,CAACI,MAAM,KAAKD,KAAK,CAACC,MAAM,EAAE,OAAO,KAAK;EAC/C,OAAOJ,KAAK,CAACK,KAAK,CAAEC,CAAC,IAAK;IACxB,MAAMC,EAAE,GAAGT,CAAC,CAACQ,CAAC,CAAC;IACf,MAAME,EAAE,GAAGT,CAAC,CAACO,CAAC,CAAC;IACf,IAAIC,EAAE,KAAK,IAAI,IAAIC,EAAE,KAAK,IAAI,IAAI,OAAOD,EAAE,KAAK,QAAQ,IAAI,OAAOC,EAAE,KAAK,QAAQ,EAAE;MAClF,OAAOC,IAAI,CAACC,SAAS,CAACH,EAAE,CAAC,KAAKE,IAAI,CAACC,SAAS,CAACF,EAAE,CAAC;IAClD;IACA,OAAOD,EAAE,KAAKC,EAAE;EAClB,CAAC,CAAC;AACJ;AAEA,SAASjB,WAAWA,CAAA,EAAS;EAC3B,IAAIpD,SAAS,EAAE;IACbwE,aAAa,CAACxE,SAAS,CAAC;IACxBA,SAAS,GAAG,IAAI;EAClB;AACF;;AAEA;;AAEA;AACA,OAAO,SAASyE,cAAcA,CAACC,GAAW,EAAe;EACvD,IAAIZ,MAAM,CAACa,SAAS,CAACC,cAAc,CAACC,IAAI,CAACnF,MAAM,EAAEgF,GAAG,CAAC,IAAIhF,MAAM,CAACgF,GAAG,CAAC,KAAK,IAAI,EAAE;IAC7E,OAAOhF,MAAM,CAACgF,GAAG,CAAC;EACpB;EACA,MAAMI,QAAQ,GAAGrF,QAAQ,CAACiF,GAAG,CAAC;EAC9B,OAAOI,QAAQ,KAAKC,SAAS,GAAG,IAAI,GAAGD,QAAQ;AACjD;AAEA,OAAO,SAASE,gBAAgBA,CAACN,GAAW,EAAW;EACrD,MAAMO,KAAK,GAAGR,cAAc,CAACC,GAAG,CAAC;EACjC,IAAI,OAAOO,KAAK,KAAK,SAAS,EAAE,OAAOA,KAAK;EAC5C;EACA,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK,CAACC,WAAW,CAAC,CAAC,KAAK,MAAM;EACpE,IAAI,OAAOD,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK,KAAK,CAAC;EACjD,OAAO,KAAK;AACd;AAEA,OAAO,SAASE,eAAeA,CAACT,GAAW,EAAU;EACnD,MAAMO,KAAK,GAAGR,cAAc,CAACC,GAAG,CAAC;EACjC,IAAI,OAAOO,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE;IAC7B,MAAMG,MAAM,GAAGC,MAAM,CAACJ,KAAK,CAAC;IAC5B,IAAI,CAACI,MAAM,CAACC,KAAK,CAACF,MAAM,CAAC,EAAE,OAAOA,MAAM;EAC1C;EACA,OAAO,CAAC;AACV;AAEA,OAAO,SAASG,eAAeA,CAACb,GAAW,EAAU;EACnD,MAAMO,KAAK,GAAGR,cAAc,CAACC,GAAG,CAAC;EACjC,IAAI,OAAOO,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAIA,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKF,SAAS,EAAE,OAAO,EAAE;EACpD,OAAOS,MAAM,CAACP,KAAK,CAAC;AACtB;;AAEA;AACA,OAAO,SAASQ,YAAYA,CAAA,EAAgC;EAC1D,OAAO;IAAE,GAAGhG,QAAQ;IAAE,GAAGC;EAAO,CAAC;AACnC;;AAEA;AACA,OAAO,SAASgG,aAAaA,CAAchB,GAAW,EAAY;EAChE,MAAMO,KAAK,GAAGR,cAAc,CAACC,GAAG,CAAC;EACjC,IAAIO,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKF,SAAS,EAAE,OAAO,IAAI;EACtD,IAAI,OAAOE,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE;IAC7B,IAAI;MACF,OAAOX,IAAI,CAACqB,KAAK,CAACV,KAAK,CAAC;IAC1B,CAAC,CAAC,MAAM;MACN,OAAO,IAAI;IACb;EACF;EACA,OAAO,IAAI;AACb;;AAEA;AACA,OAAO,SAASW,eAAeA,CAAClB,GAAW,EAAoC;EAC7E,IAAIZ,MAAM,CAACa,SAAS,CAACC,cAAc,CAACC,IAAI,CAACnF,MAAM,EAAEgF,GAAG,CAAC,IAAIhF,MAAM,CAACgF,GAAG,CAAC,KAAK,IAAI,EAAE,OAAO,QAAQ;EAC9F,IAAIZ,MAAM,CAACa,SAAS,CAACC,cAAc,CAACC,IAAI,CAACpF,QAAQ,EAAEiF,GAAG,CAAC,EAAE,OAAO,SAAS;EACzE,OAAO,SAAS;AAClB;AAEA,OAAO,SAASmB,aAAaA,CAAA,EAAa;EACxC,OAAO/B,MAAM,CAACC,IAAI,CAAC0B,YAAY,CAAC,CAAC,CAAC,CAACK,IAAI,CAAC,CAAC;AAC3C;AAEA,OAAO,SAASC,cAAcA,CAACC,QAAuD,EAAc;EAClG/F,SAAS,CAACgG,GAAG,CAACD,QAAQ,CAAC;EACvB,OAAO,MAAM/F,SAAS,CAACiG,MAAM,CAACF,QAAQ,CAAC;AACzC;;AAEA;AACA,OAAO,SAASG,aAAaA,CAAA,EAK3B;EACA,OAAO;IAAEtG,MAAM;IAAED,SAAS;IAAED,IAAI;IAAEyG,QAAQ,EAAEtC,MAAM,CAACC,IAAI,CAAC0B,YAAY,CAAC,CAAC,CAAC,CAACxB;EAAO,CAAC;AAClF;;AAEA;AACA,OAAO,SAASoC,mBAAmBA,CAAA,EAAS;EAC1C7G,OAAO,GAAG,IAAI;EACdC,QAAQ,GAAG,CAAC,CAAC;EACbC,MAAM,GAAG,CAAC,CAAC;EACXC,IAAI,GAAG,IAAI;EACXC,SAAS,GAAG,CAAC;EACbC,MAAM,GAAG,UAAU;EACnBE,QAAQ,GAAG,IAAI;EACfD,OAAO,GAAG,IAAI;EACdG,SAAS,CAACqG,KAAK,CAAC,CAAC;EACjBlD,WAAW,CAAC,CAAC;AACf;;AAEA;;AAEA,SAAS1B,YAAYA,CAACtB,IAAmB,EAAEmG,WAA0B,EAA0B;EAC7F,MAAMC,GAAG,GAAGpG,IAAI,CAACqG,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC;EACrC,MAAMhF,OAA+B,GAAG;IAAEiF,MAAM,EAAE;EAAmB,CAAC;EAEtE,IAAIF,GAAG,CAACG,QAAQ,EAAElF,OAAO,CAAC,kBAAkB,CAAC,GAAG+E,GAAG,CAACG,QAAQ;EAC5D,IAAIH,GAAG,CAACI,UAAU,EAAEnF,OAAO,CAAC,qBAAqB,CAAC,GAAG+E,GAAG,CAACI,UAAU;EACnE,IAAIJ,GAAG,CAACK,SAAS,EAAEpF,OAAO,CAAC,oBAAoB,CAAC,GAAG+E,GAAG,CAACK,SAAS;EAChE,IAAIL,GAAG,CAACM,QAAQ,EAAErF,OAAO,CAAC,kBAAkB,CAAC,GAAG+E,GAAG,CAACM,QAAQ;EAC5D,IAAIN,GAAG,CAACO,QAAQ,EAAEtF,OAAO,CAAC,iBAAiB,CAAC,GAAG+E,GAAG,CAACO,QAAQ;EAC3D,IAAIP,GAAG,CAACQ,cAAc,IAAIlD,MAAM,CAACC,IAAI,CAACyC,GAAG,CAACQ,cAAc,CAAC,CAAC/C,MAAM,GAAG,CAAC,EAAE;IACpExC,OAAO,CAAC,yBAAyB,CAAC,GAAG6C,IAAI,CAACC,SAAS,CAACiC,GAAG,CAACQ,cAAc,CAAC;EACzE;EACA;EACA;;EAEA,IAAIT,WAAW,EAAE9E,OAAO,CAAC,eAAe,CAAC,GAAG8E,WAAW;EACvD,OAAO9E,OAAO;AAChB;AAEA,SAASnB,SAASA,CAACC,OAAuB,EAAwB;EAChE,IAAI,CAACA,OAAO,EAAE,OAAO,IAAI;EACzB,IAAI;IACF,MAAM0G,GAAG,GAAG1G,OAAO,CAAC2G,SAAS,CAAC7H,WAAW,CAAC;IAC1C,IAAI,CAAC4H,GAAG,EAAE,OAAO,IAAI;IACrB,MAAM7B,MAAM,GAAGd,IAAI,CAACqB,KAAK,CAACsB,GAAG,CAAkB;IAC/C,IAAI,CAAC7B,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAI,CAACA,MAAM,CAAC1F,MAAM,EAAE,OAAO,IAAI;IACxE,OAAO0F,MAAM;EACf,CAAC,CAAC,MAAM;IACN;IACA,OAAO,IAAI;EACb;AACF;AAEA,SAAS3B,UAAUA,CAAClD,OAAkC,EAAEwB,OAAsB,EAAQ;EACpF,IAAI,CAACxB,OAAO,EAAE;EACd,IAAI;IACFA,OAAO,CAAC4G,GAAG,CAAC9H,WAAW,EAAEiF,IAAI,CAACC,SAAS,CAACxC,OAAO,CAAC,CAAC;EACnD,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;AAEA,SAAS2B,MAAMA,CAAA,EAAS;EACtB,MAAM0D,QAAQ,GAAG3B,YAAY,CAAC,CAAC;EAC/BxF,SAAS,CAACoH,OAAO,CAAErB,QAAQ,IAAK;IAC9B,IAAI;MACFA,QAAQ,CAACoB,QAAQ,CAAC;IACpB,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ,CAAC,CAAC;AACJ","ignoreList":[]}
|
|
@@ -49,6 +49,20 @@ export interface ConfigOptions {
|
|
|
49
49
|
getContext?: () => ConfigContext;
|
|
50
50
|
/** Foreground poll interval. 0 disables polling (launch + resume still fetch). */
|
|
51
51
|
pollIntervalMs?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Skip a fetch that lands within this window of the last successful one. 0 (the
|
|
54
|
+
* default) means never skip: unlike Firebase there is no per-request price, so the
|
|
55
|
+
* throttle exists only for callers who want it.
|
|
56
|
+
*/
|
|
57
|
+
minimumFetchIntervalMs?: number;
|
|
58
|
+
/**
|
|
59
|
+
* When false, a fetch stores the payload without applying it — call activateConfig()
|
|
60
|
+
* to swap it in. Mirrors Firebase's fetch/activate split, and matters here because
|
|
61
|
+
* the foreground poll would otherwise flip a flag under a user mid-session: an ad
|
|
62
|
+
* gate or a playback engine changing while a track plays is worse than being a few
|
|
63
|
+
* minutes stale. Default true, matching fetchAndActivate.
|
|
64
|
+
*/
|
|
65
|
+
activateOnFetch?: boolean;
|
|
52
66
|
/** Network timeout per request. */
|
|
53
67
|
timeoutMs?: number;
|
|
54
68
|
onError?: (error: unknown) => void;
|
|
@@ -69,6 +83,13 @@ export declare function setConfigDefaults(more: Record<string, ConfigValue>): vo
|
|
|
69
83
|
* to wrap a config refresh in a try/catch to keep the app running.
|
|
70
84
|
*/
|
|
71
85
|
export declare function fetchConfig(): Promise<boolean>;
|
|
86
|
+
/**
|
|
87
|
+
* Swap in the values from the last fetch made with activateOnFetch: false.
|
|
88
|
+
* Returns true when something actually changed.
|
|
89
|
+
*/
|
|
90
|
+
export declare function activateConfig(): boolean;
|
|
91
|
+
/** Whether a fetched-but-not-yet-applied payload is waiting. */
|
|
92
|
+
export declare function hasPendingConfig(): boolean;
|
|
72
93
|
/**
|
|
73
94
|
* Fetch on launch, on every return to the foreground, and on a timer.
|
|
74
95
|
* Returns a function that stops both.
|
|
@@ -85,6 +106,11 @@ export declare function getConfigNumber(key: string): number;
|
|
|
85
106
|
export declare function getConfigString(key: string): string;
|
|
86
107
|
/** Defaults first, then everything the server sent — what a caller would see key by key. */
|
|
87
108
|
export declare function getAllConfig(): Record<string, ConfigValue>;
|
|
109
|
+
/** Parsed object/array value, or the default. Null when neither is usable. */
|
|
110
|
+
export declare function getConfigJson<T = unknown>(key: string): T | null;
|
|
111
|
+
/** Where this key's value came from — the answer to "why is this flag off?". */
|
|
112
|
+
export declare function getConfigSource(key: string): 'remote' | 'default' | 'missing';
|
|
113
|
+
export declare function getConfigKeys(): string[];
|
|
88
114
|
export declare function onConfigChange(listener: (values: Record<string, ConfigValue>) => void): () => void;
|
|
89
115
|
/** For diagnostics: where the current values came from and how old they are. */
|
|
90
116
|
export declare function getConfigInfo(): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvC,kFAAkF;IAClF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,aAAa,CAAC;IACjC,kFAAkF;IAClF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/scripts/publish.mjs
CHANGED
|
@@ -157,12 +157,15 @@ function getMimeType(ext) {
|
|
|
157
157
|
*/
|
|
158
158
|
function findHermesc(platform) {
|
|
159
159
|
const possiblePaths = [
|
|
160
|
-
// iOS paths
|
|
160
|
+
// iOS paths (present once Pods are installed)
|
|
161
161
|
'ios/Pods/hermes-engine/destroot/bin/hermesc',
|
|
162
|
+
// hermesc as shipped inside react-native itself (host-arch dirs vary by RN version)
|
|
162
163
|
'node_modules/react-native/sdks/hermesc/osx-bin/hermesc',
|
|
163
164
|
'node_modules/react-native/sdks/hermesc/linux64-bin/hermesc',
|
|
164
|
-
|
|
165
|
+
'node_modules/react-native/sdks/hermesc/win64-bin/hermesc.exe',
|
|
166
|
+
// Android paths (present once an Android build has run)
|
|
165
167
|
'node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/hermesc',
|
|
168
|
+
'node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/tools/hermesc/hermesc',
|
|
166
169
|
];
|
|
167
170
|
|
|
168
171
|
for (const p of possiblePaths) {
|
|
@@ -172,12 +175,59 @@ function findHermesc(platform) {
|
|
|
172
175
|
}
|
|
173
176
|
}
|
|
174
177
|
|
|
175
|
-
// Try to find via
|
|
178
|
+
// Try to find via PATH
|
|
176
179
|
try {
|
|
177
|
-
|
|
180
|
+
const viaPath = execSync('command -v hermesc', { encoding: 'utf8' }).trim();
|
|
181
|
+
if (viaPath) return viaPath;
|
|
178
182
|
} catch {
|
|
179
|
-
|
|
183
|
+
/* not on PATH */
|
|
180
184
|
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Locate hermesc, and if it isn't there yet, try to materialize it.
|
|
190
|
+
* A React Native app may only carry hermesc inside the installed CocoaPods (it
|
|
191
|
+
* does not always ship in node_modules for every RN version), so on macOS a
|
|
192
|
+
* missing compiler often means "Pods aren't installed" — which we fix by running
|
|
193
|
+
* pod-install once, then re-checking. Anything else is a hard stop: we NEVER
|
|
194
|
+
* silently fall back to a plain-JS OTA bundle (that would ship readable source
|
|
195
|
+
* over the air). Hermes is mandatory on every publish.
|
|
196
|
+
*/
|
|
197
|
+
function ensureHermesc(platform) {
|
|
198
|
+
let hermesc = findHermesc(platform);
|
|
199
|
+
if (hermesc) return hermesc;
|
|
200
|
+
|
|
201
|
+
const onMac = process.platform === 'darwin';
|
|
202
|
+
const hasPodfile = fs.existsSync(path.resolve('ios/Podfile'));
|
|
203
|
+
if (onMac && hasPodfile) {
|
|
204
|
+
logWarning('Hermes compiler not found — installing iOS Pods to obtain it (one-shot)...');
|
|
205
|
+
try {
|
|
206
|
+
// Prefer a repo pod-install helper if the app provides one, else npx pod-install.
|
|
207
|
+
const repoHelper = path.resolve('scripts/pod-install-if-mac.js');
|
|
208
|
+
const cmd = fs.existsSync(repoHelper)
|
|
209
|
+
? `node ${repoHelper}`
|
|
210
|
+
: 'npx pod-install ios';
|
|
211
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
212
|
+
} catch (error) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`Hermes compiler not found and automatic pod install failed (${error.message}). ` +
|
|
215
|
+
'Run `npx pod-install ios` (or `cd ios && pod install`) and publish again.'
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
hermesc = findHermesc(platform);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!hermesc) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
'Hermes compiler (hermesc) could not be located. Pulse publishes Hermes bytecode only — ' +
|
|
224
|
+
'a plain-JS OTA bundle must never be shipped. Install it before publishing:\n' +
|
|
225
|
+
' • macOS: `npx pod-install ios` (materializes ios/Pods/hermes-engine/.../hermesc)\n' +
|
|
226
|
+
' • or ensure react-native ships hermesc under node_modules/react-native/sdks/hermesc/\n' +
|
|
227
|
+
' • or put hermesc on PATH.'
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
return hermesc;
|
|
181
231
|
}
|
|
182
232
|
|
|
183
233
|
/**
|
|
@@ -213,43 +263,51 @@ function createBundle(platform, bundleDir, entryFile = 'index.ts') {
|
|
|
213
263
|
* Compile bundle with Hermes
|
|
214
264
|
*/
|
|
215
265
|
function compileWithHermes(bundlePath, platform) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return bundlePath;
|
|
220
|
-
}
|
|
266
|
+
// Mandatory: locate (and if needed materialize) hermesc. Throws rather than
|
|
267
|
+
// degrading to a plain-JS bundle — see ensureHermesc.
|
|
268
|
+
const hermesc = ensureHermesc(platform);
|
|
221
269
|
|
|
222
270
|
const hbcPath = bundlePath.replace('.bundle', '.hbc');
|
|
223
271
|
|
|
224
272
|
log(` Compiling with Hermes...`, colors.dim);
|
|
225
273
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
274
|
+
// -emit-binary: Hermes bytecode.
|
|
275
|
+
// -fstrip-function-names: drop JS function names from the string table (smaller
|
|
276
|
+
// bundle, and function names are the biggest readability gift to anyone
|
|
277
|
+
// inspecting the bytecode). Trade-off: JS function names disappear from crash
|
|
278
|
+
// stack traces. Does NOT touch string literals.
|
|
279
|
+
const hermesArgs = ['-emit-binary', '-fstrip-function-names', '-out', hbcPath, bundlePath];
|
|
280
|
+
|
|
281
|
+
// Use spawnSync with larger buffer to avoid ENOBUFS error
|
|
282
|
+
const result = spawnSync(hermesc, hermesArgs, {
|
|
283
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
284
|
+
maxBuffer: 100 * 1024 * 1024, // 100MB buffer
|
|
285
|
+
encoding: 'utf8',
|
|
286
|
+
});
|
|
233
287
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
288
|
+
if (result.error) {
|
|
289
|
+
throw result.error;
|
|
290
|
+
}
|
|
237
291
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
292
|
+
if (result.status !== 0) {
|
|
293
|
+
const stderr = result.stderr || '';
|
|
294
|
+
throw new Error(`Hermes exited with code ${result.status}: ${stderr.slice(0, 500)}`);
|
|
295
|
+
}
|
|
242
296
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
297
|
+
// Remove the plain JS bundle, keep only HBC
|
|
298
|
+
fs.unlinkSync(bundlePath);
|
|
299
|
+
// Rename .hbc to .bundle for compatibility
|
|
300
|
+
const finalPath = bundlePath;
|
|
301
|
+
fs.renameSync(hbcPath, finalPath);
|
|
302
|
+
|
|
303
|
+
// Belt-and-suspenders: the launch asset MUST be Hermes bytecode. If for any
|
|
304
|
+
// reason it isn't, fail the publish instead of shipping readable JS OTA.
|
|
305
|
+
if (!isHermesBytecode(finalPath)) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
'Post-compile check failed: launch bundle is not Hermes bytecode. Refusing to publish a plain-JS OTA bundle.'
|
|
308
|
+
);
|
|
252
309
|
}
|
|
310
|
+
return finalPath;
|
|
253
311
|
}
|
|
254
312
|
|
|
255
313
|
/**
|
package/src/config.ts
CHANGED
|
@@ -53,6 +53,20 @@ export interface ConfigOptions {
|
|
|
53
53
|
getContext?: () => ConfigContext;
|
|
54
54
|
/** Foreground poll interval. 0 disables polling (launch + resume still fetch). */
|
|
55
55
|
pollIntervalMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Skip a fetch that lands within this window of the last successful one. 0 (the
|
|
58
|
+
* default) means never skip: unlike Firebase there is no per-request price, so the
|
|
59
|
+
* throttle exists only for callers who want it.
|
|
60
|
+
*/
|
|
61
|
+
minimumFetchIntervalMs?: number;
|
|
62
|
+
/**
|
|
63
|
+
* When false, a fetch stores the payload without applying it — call activateConfig()
|
|
64
|
+
* to swap it in. Mirrors Firebase's fetch/activate split, and matters here because
|
|
65
|
+
* the foreground poll would otherwise flip a flag under a user mid-session: an ad
|
|
66
|
+
* gate or a playback engine changing while a track plays is worse than being a few
|
|
67
|
+
* minutes stale. Default true, matching fetchAndActivate.
|
|
68
|
+
*/
|
|
69
|
+
activateOnFetch?: boolean;
|
|
56
70
|
/** Network timeout per request. */
|
|
57
71
|
timeoutMs?: number;
|
|
58
72
|
onError?: (error: unknown) => void;
|
|
@@ -74,6 +88,7 @@ let values: Record<string, ConfigValue> = {};
|
|
|
74
88
|
let etag: string | null = null;
|
|
75
89
|
let fetchedAt = 0;
|
|
76
90
|
let source: 'defaults' | 'cache' | 'remote' = 'defaults';
|
|
91
|
+
let pending: Record<string, ConfigValue> | null = null;
|
|
77
92
|
let inFlight: Promise<boolean> | null = null;
|
|
78
93
|
let pollTimer: ReturnType<typeof setInterval> | null = null;
|
|
79
94
|
const listeners = new Set<(values: Record<string, ConfigValue>) => void>();
|
|
@@ -113,6 +128,11 @@ export async function fetchConfig(): Promise<boolean> {
|
|
|
113
128
|
// Collapse concurrent calls (launch + resume can land together) onto one request.
|
|
114
129
|
if (inFlight) return inFlight;
|
|
115
130
|
|
|
131
|
+
const minInterval = options.minimumFetchIntervalMs ?? 0;
|
|
132
|
+
if (minInterval > 0 && fetchedAt > 0 && Date.now() - fetchedAt < minInterval) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
116
136
|
inFlight = (async () => {
|
|
117
137
|
const opts = options!;
|
|
118
138
|
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
@@ -131,16 +151,22 @@ export async function fetchConfig(): Promise<boolean> {
|
|
|
131
151
|
if (!response.ok) throw new Error(`Pulse config HTTP ${response.status}`);
|
|
132
152
|
|
|
133
153
|
const payload = await response.json();
|
|
134
|
-
const nextValues =
|
|
154
|
+
const nextValues = payload?.values;
|
|
155
|
+
// A payload without a values object is a broken response, not "no keys": adopting
|
|
156
|
+
// it would blank every flag at once.
|
|
157
|
+
if (!nextValues || typeof nextValues !== 'object' || Array.isArray(nextValues)) {
|
|
158
|
+
throw new Error('Pulse config: malformed payload');
|
|
159
|
+
}
|
|
135
160
|
|
|
136
|
-
values = nextValues;
|
|
137
161
|
etag = response.headers?.get?.('etag') ?? null;
|
|
138
162
|
fetchedAt = Date.now();
|
|
139
|
-
source = 'remote';
|
|
140
163
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
164
|
+
if (opts.activateOnFetch === false) {
|
|
165
|
+
pending = nextValues as Record<string, ConfigValue>;
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return applyValues(nextValues as Record<string, ConfigValue>, opts);
|
|
144
170
|
} catch (error) {
|
|
145
171
|
// A failed refresh must never clear what we have: the whole point of the cache
|
|
146
172
|
// is that an unreachable server degrades to the last good config.
|
|
@@ -155,6 +181,22 @@ export async function fetchConfig(): Promise<boolean> {
|
|
|
155
181
|
return inFlight;
|
|
156
182
|
}
|
|
157
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Swap in the values from the last fetch made with activateOnFetch: false.
|
|
186
|
+
* Returns true when something actually changed.
|
|
187
|
+
*/
|
|
188
|
+
export function activateConfig(): boolean {
|
|
189
|
+
if (!pending || !options) return false;
|
|
190
|
+
const next = pending;
|
|
191
|
+
pending = null;
|
|
192
|
+
return applyValues(next, options);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Whether a fetched-but-not-yet-applied payload is waiting. */
|
|
196
|
+
export function hasPendingConfig(): boolean {
|
|
197
|
+
return pending !== null;
|
|
198
|
+
}
|
|
199
|
+
|
|
158
200
|
/**
|
|
159
201
|
* Fetch on launch, on every return to the foreground, and on a timer.
|
|
160
202
|
* Returns a function that stops both.
|
|
@@ -180,6 +222,34 @@ export function startConfigAutoRefresh(appState?: {
|
|
|
180
222
|
};
|
|
181
223
|
}
|
|
182
224
|
|
|
225
|
+
function applyValues(next: Record<string, ConfigValue>, opts: ConfigOptions): boolean {
|
|
226
|
+
const changed = !shallowEqual(values, next);
|
|
227
|
+
|
|
228
|
+
values = next;
|
|
229
|
+
source = 'remote';
|
|
230
|
+
writeCache(opts.storage, { values, etag, fetchedAt });
|
|
231
|
+
|
|
232
|
+
// Listeners drive re-renders and gate re-evaluation: firing them for an identical
|
|
233
|
+
// payload is pure churn, and the 200-with-same-content case is common enough
|
|
234
|
+
// (a proxy that drops the ETag) to be worth checking.
|
|
235
|
+
if (changed) notify();
|
|
236
|
+
return changed;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function shallowEqual(a: Record<string, ConfigValue>, b: Record<string, ConfigValue>): boolean {
|
|
240
|
+
const aKeys = Object.keys(a);
|
|
241
|
+
const bKeys = Object.keys(b);
|
|
242
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
243
|
+
return aKeys.every((k) => {
|
|
244
|
+
const av = a[k];
|
|
245
|
+
const bv = b[k];
|
|
246
|
+
if (av !== null && bv !== null && typeof av === 'object' && typeof bv === 'object') {
|
|
247
|
+
return JSON.stringify(av) === JSON.stringify(bv);
|
|
248
|
+
}
|
|
249
|
+
return av === bv;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
183
253
|
function stopPolling(): void {
|
|
184
254
|
if (pollTimer) {
|
|
185
255
|
clearInterval(pollTimer);
|
|
@@ -229,6 +299,32 @@ export function getAllConfig(): Record<string, ConfigValue> {
|
|
|
229
299
|
return { ...defaults, ...values };
|
|
230
300
|
}
|
|
231
301
|
|
|
302
|
+
/** Parsed object/array value, or the default. Null when neither is usable. */
|
|
303
|
+
export function getConfigJson<T = unknown>(key: string): T | null {
|
|
304
|
+
const value = getConfigValue(key);
|
|
305
|
+
if (value === null || value === undefined) return null;
|
|
306
|
+
if (typeof value === 'object') return value as T;
|
|
307
|
+
if (typeof value === 'string') {
|
|
308
|
+
try {
|
|
309
|
+
return JSON.parse(value) as T;
|
|
310
|
+
} catch {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** Where this key's value came from — the answer to "why is this flag off?". */
|
|
318
|
+
export function getConfigSource(key: string): 'remote' | 'default' | 'missing' {
|
|
319
|
+
if (Object.prototype.hasOwnProperty.call(values, key) && values[key] !== null) return 'remote';
|
|
320
|
+
if (Object.prototype.hasOwnProperty.call(defaults, key)) return 'default';
|
|
321
|
+
return 'missing';
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function getConfigKeys(): string[] {
|
|
325
|
+
return Object.keys(getAllConfig()).sort();
|
|
326
|
+
}
|
|
327
|
+
|
|
232
328
|
export function onConfigChange(listener: (values: Record<string, ConfigValue>) => void): () => void {
|
|
233
329
|
listeners.add(listener);
|
|
234
330
|
return () => listeners.delete(listener);
|
|
@@ -253,6 +349,7 @@ export function resetConfigForTests(): void {
|
|
|
253
349
|
fetchedAt = 0;
|
|
254
350
|
source = 'defaults';
|
|
255
351
|
inFlight = null;
|
|
352
|
+
pending = null;
|
|
256
353
|
listeners.clear();
|
|
257
354
|
stopPolling();
|
|
258
355
|
}
|