pulse-updates 1.0.15 → 1.0.16

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.
@@ -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 = nextValues;
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
- source = 'remote';
115
- writeCache(opts.storage, {
116
- values,
117
- etag,
118
- fetchedAt
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":"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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":"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","ignoreList":[]}
@@ -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 = nextValues;
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
- source = 'remote';
98
- writeCache(opts.storage, {
99
- values,
100
- etag,
101
- fetchedAt
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
  }
@@ -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":"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","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;AAsBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAWzD;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAEzE;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CA6CpD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE;IAChD,gBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAChG,GAAG,MAAM,IAAI,CAiBb;AAWD,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAMvD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAE1D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAGlG;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI;IAC/B,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAEA;AAED,oDAAoD;AACpD,wBAAgB,mBAAmB,IAAI,IAAI,CAU1C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-updates",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "OTA updates for React Native - lightweight alternative to expo-updates",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
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 = (payload?.values ?? {}) as Record<string, ConfigValue>;
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
- writeCache(opts.storage, { values, etag, fetchedAt });
142
- notify();
143
- return true;
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
  }