@quonfig/react 0.0.14 → 1.0.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/CHANGELOG.md CHANGED
@@ -1,11 +1,34 @@
1
1
  Changelog
2
2
 
3
- ## 0.0.14 - 2026-05-19
3
+ ## 1.0.0 - 2026-06-06
4
+
5
+ - **Stable 1.0.0 release.** The Quonfig React SDK is now declared stable. No API or behavior changes
6
+ from 0.0.15 — this is a coordinated 1.0.0 version stamp across the entire Quonfig SDK family.
7
+ Tracks `@quonfig/javascript` >= 1.0.0.
8
+
9
+ ## 0.0.15 - 2026-06-05
10
+
11
+ - Bumped the `@quonfig/javascript` floor to `>=0.0.18` to pick up ETag/304 conditional polling
12
+ (qfg-iikt) and the `poll()` bootstrap self-heal (qfg-8uw5). Without the bump the provider's
13
+ polling could not benefit from the 304 fast-path or the startup-blip recovery.
14
+ - Fix: `<QuonfigProvider>` now catches the rejection from its initial `poll()` call. The provider
15
+ fired `poll()` fire-and-forget inside `init()`'s `.then` (not awaited or returned), so a
16
+ first-fetch rejection became an unhandled promise rejection while the app showed loaded=true. It
17
+ is now logged as a non-fatal warning (not routed through `onError`) since the underlying polling
18
+ loop self-heals on the next tick (qfg-8uw5).
19
+
20
+ ## 0.0.14 - 2026-05-21
4
21
 
5
22
  - **Breaking (typing-level):** removed the `collectLoggerNames` prop from `<QuonfigProvider>`
6
23
  (qfg-owyw). The underlying `@quonfig/javascript` option was removed in 0.0.17 (qfg-o2fk) — there
7
24
  is no consumer for the per-logger telemetry on the server. TypeScript callers passing
8
25
  `collectLoggerNames` to the provider will get a type error; drop the prop.
26
+ - **chore: replace the `@quonfig/javascript` `portal:` devDependency with a published npm range
27
+ (qfg-zu8o).** The dev entry was `portal:../sdk-javascript`, which only resolves inside the
28
+ monorepo; Dependabot's isolated single-repo npm updater could not resolve it and every npm update
29
+ job failed. The devDependency is now a plain npm range (`>=0.0.14`) matching the
30
+ `peerDependencies` floor. No runtime or published-package change — local development against an
31
+ unpublished sibling `../sdk-javascript` now uses `yarn link` (see `CONTRIBUTING.md`).
9
32
 
10
33
  ## 0.0.13 - 2026-05-10
11
34
 
package/dist/index.cjs CHANGED
@@ -10,7 +10,7 @@ var React__default = /*#__PURE__*/_interopDefault(React);
10
10
  // src/index.tsx
11
11
 
12
12
  // src/version.ts
13
- var version_default = "0.0.9";
13
+ var version_default = "0.0.15";
14
14
 
15
15
  // src/sdkLogger.ts
16
16
  var NOOP = () => {
@@ -187,7 +187,9 @@ function QuonfigProvider({
187
187
  setLoadedContextKey(contextKey);
188
188
  setLoading(false);
189
189
  if (pollInterval) {
190
- quonfigClient.poll({ frequencyInMs: pollInterval });
190
+ quonfigClient.poll({ frequencyInMs: pollInterval }).catch((err) => {
191
+ normalizedLogger.warn("Initial poll fetch failed; polling will retry", err);
192
+ });
191
193
  }
192
194
  }).catch((reason) => {
193
195
  setLoading(false);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/sdkLogger.ts","../src/QuonfigProvider.tsx","../src/QuonfigTestProvider.tsx"],"names":["React","quonfig","Quonfig","encodeContexts"],"mappings":";;;;;;;;;;;;AACA,IAAO,eAAA,GAAQ,OAAA;;;ACqBf,IAAM,OAAO,MAAY;AAAC,CAAA;AAE1B,IAAM,MAAA,GAAS,WAAA;AAEf,SAAS,gBAAA,GAAqC;AAC5C,EAAA,OAAO;AAAA;AAAA,IAEL,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,QAAQ,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,IACnE,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,QAAQ,IAAA,CAAK,MAAA,EAAQ,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,IACjE,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,QAAQ,IAAA,CAAK,MAAA,EAAQ,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,IACjE,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,QAAQ,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,GAAG,IAAI;AAAA;AAAA,GAErE;AACF;AAEO,SAAS,gBAAgB,MAAA,EAA8C;AAC5E,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,gBAAA,EAAiB;AACrC,EAAA,OAAO;AAAA,IACL,OAAO,MAAA,CAAO,KAAA,GAAQ,OAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA;AAAA,IAClD,MAAM,MAAA,CAAO,IAAA,GAAO,OAAO,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA;AAAA,IAC/C,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AAAA,IAC7B,KAAA,EAAO,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,MAAM;AAAA,GACjC;AACF;;;ACxBA,IAAM,oBAAA,GAAuBA,sBAAA,CAAM,aAAA,CAA8B,IAAI,CAAA;AAoE9D,IAAM,cAAA,GAA8B;AAAA,EACzC,GAAA,EAAK,CAAC,IAAA,KAAS,MAAA;AAAA,EACf,WAAA,EAAa,CAAC,IAAA,KAAS,MAAA;AAAA,EACvB,SAAA,EAAW,CAAC,IAAA,KAAS,KAAA;AAAA,EACrB,MAAM,EAAC;AAAA,EACP,OAAA,EAAS,IAAA;AAAA,EACT,mBAAmB,EAAC;AAAA,WACpBC,kBAAA;AAAA,EACA,UAAU;AACZ,CAAA;AAEO,IAAM,iBAAiBD,sBAAA,CAAM,aAAA;AAAA,EAClC;AACF,CAAA;AAGO,SAAS,kBAAqB,aAAA,EAAwC;AAC3E,EAAA,OAAO,SAAS,cAAA,GAAkC;AAChD,IAAA,MAAM,WAAA,GAAcA,sBAAA,CAAM,UAAA,CAAW,cAAc,CAAA;AAGnD,IAAA,MAAM,gBAAA,GAAmBA,sBAAA,CAAM,OAAA,CAAQ,MAAM;AAC3C,MAAA,MAAM,QAAA,GAAW,IAAI,aAAA,CAAc,WAAA,CAAY,OAAO,CAAA;AAGtD,MAAA,MAAA,CAAO,OAAO,QAAA,EAAiB;AAAA,QAC7B,aAAa,WAAA,CAAY,WAAA;AAAA,QACzB,mBAAmB,WAAA,CAAY,iBAAA;AAAA,QAC/B,WAAW,WAAA,CAAY,SAAA;AAAA,QACvB,SAAS,WAAA,CAAY,OAAA;AAAA,QACrB,MAAM,WAAA,CAAY,IAAA;AAAA,QAClB,UAAU,WAAA,CAAY;AAAA,OACvB,CAAA;AAED,MAAA,OAAO,QAAA;AAAA,IACT,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,IAAA,OAAO,gBAAA;AAAA,EACT,CAAA;AACF;AAGO,IAAM,cAAA,GAAiB,MAAMA,sBAAA,CAAM,UAAA,CAAW,cAAc,CAAA;AAG5D,IAAM,UAAA,GAAa,MAAuB,cAAA;AAW1C,SAAS,QAAQ,GAAA,EAA0B;AAjJlD,EAAA,IAAA,EAAA;AAkJE,EAAA,MAAM,MAAA,GAAA,CAAS,EAAA,GAAAA,sBAAA,CAAM,UAAA,CAAW,oBAAoB,MAArC,IAAA,GAAA,EAAA,GAA0CC,kBAAA;AACzD,EAAA,MAAM,YAAYD,sBAAA,CAAM,WAAA;AAAA,IACtB,CAAC,QAAA,KAAyB,MAAA,CAAO,SAAA,CAAU,QAAQ,CAAA;AAAA,IACnD,CAAC,MAAM;AAAA,GACT;AACA,EAAA,MAAM,WAAA,GAAcA,sBAAA,CAAM,WAAA,CAAY,MAAM,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,EAAG,CAAC,MAAA,EAAQ,GAAG,CAAC,CAAA;AAC1E,EAAA,MAAM,oBAAoBA,sBAAA,CAAM,WAAA,CAAY,MAAmB,MAAA,EAAW,EAAE,CAAA;AAC5E,EAAA,OAAOA,sBAAA,CAAM,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,iBAAiB,CAAA;AAC7E;AAOO,IAAM,mBAAmB,MAAe;AAC7C,EAAA,MAAM,YAAA,GAAeA,sBAAA,CAAM,UAAA,CAAW,oBAAoB,CAAA;AAE1D,EAAA,MAAM,eAAA,GAAkBA,sBAAA,CAAM,MAAA,CAAO,YAAY,CAAA;AACjD,EAAA,OAAOA,sBAAA,CAAM,OAAA,CAAQ,MAAO,eAAA,CAAgB,OAAA,GAAU,IAAIE,kBAAA,EAAQ,GAAID,kBAAA,EAAU,EAAE,CAAA;AACpF,CAAA;AASA,IAAM,aAAA,GAAgB,CACpB,iBAAA,EACA,MAAA,EACA,OAAA,KACW;AACX,EAAA,IAAI;AACF,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,iBAAiB,CAAA,CAAE,WAAW,CAAA,EAAG;AAC/C,MAAA,MAAA,CAAO,IAAA;AAAA,QACL;AAAA,OACF;AAAA,IACF;AAEA,IAAA,OAAOE,0BAAe,iBAAiB,CAAA;AAAA,EACzC,SAAS,CAAA,EAAG;AACV,IAAA,OAAA,CAAQ,CAAU,CAAA;AAClB,IAAA,OAAO,EAAA;AAAA,EACT;AACF,CAAA;AAEA,SAAS,eAAA,CAAgB;AAAA,EACvB,MAAA;AAAA,EACA,oBAAoB,EAAC;AAAA,EACrB,OAAA,EAAS,WAAA;AAAA,EACT,MAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,uBAAA,GAA0B,MAAA;AAAA,EAC1B;AACF,CAAA,EAA4C;AAC1C,EAAA,MAAM,gBAAA,GAAmBH,uBAAM,OAAA,CAAQ,MAAM,gBAAgB,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAC9E,EAAA,MAAM,UAAUA,sBAAA,CAAM,WAAA;AAAA,IACpB,CAAC,CAAA,KAAe;AACd,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,WAAA,CAAY,CAAU,CAAA;AAAA,MACxB,CAAA,MAAO;AACL,QAAA,MAAM,UAAU,CAAA,YAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,OAAO,CAAC,CAAA;AACzD,QAAA,gBAAA,CAAiB,KAAA,CAAM,SAAS,CAAC,CAAA;AAAA,MACnC;AAAA,IACF,CAAA;AAAA,IACA,CAAC,aAAa,gBAAgB;AAAA,GAChC;AACA,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,MAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA,OAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACF;AAIA,EAAA,MAAM,6BAAA,GAAgCA,sBAAA,CAAM,MAAA,CAA2B,MAAS,CAAA;AAGhF,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,sBAAA,CAAM,SAAS,IAAI,CAAA;AACjD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIA,sBAAA,CAAM,SAAS,IAAI,CAAA;AAGzD,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAIA,sBAAA,CAAM,SAAS,EAAE,CAAA;AAEjE,EAAA,MAAM,gBAAyB,gBAAA,EAAiB;AAKhD,EAAA,MAAM,cAAcA,sBAAA,CAAM,oBAAA;AAAA,IACxBA,sBAAA,CAAM,WAAA,CAAY,CAAC,QAAA,KAAa,aAAA,CAAc,UAAU,QAAQ,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAAA,IAClFA,uBAAM,WAAA,CAAY,MAAM,cAAc,WAAA,EAAa,CAAC,aAAa,CAAC,CAAA;AAAA,IAClEA,sBAAA,CAAM,WAAA,CAAY,MAAM,CAAA,EAAG,EAAE;AAAA,GAC/B;AAEA,EAAA,MAAM,UAAA,GAAa,aAAA,CAAc,iBAAA,EAAmB,gBAAA,EAAkB,OAAO,CAAA;AAE7E,EAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,IAAA,aAAA,CAAc,QAAQ,YAAY,CAAA;AAClC,IAAA,cAAA,CAAe,KAAK,CAAA;AACpB,IAAA,mBAAA,CAAoB,UAAU,CAAA;AAC9B,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,6BAAA,CAA8B,OAAA,GAAU,UAAA;AAExC,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,gBAAA,CAAiB,KAAK,gEAAgE,CAAA;AAAA,IACxF;AAAA,EACF;AAEA,EAAAA,sBAAA,CAAM,UAAU,MAAM;AACpB,IAAA,cAAA,CAAe,KAAK,CAAA;AAEpB,IAAA,IAAI,6BAAA,CAA8B,YAAY,UAAA,EAAY;AACxD,MAAA;AAAA,IACF;AAEA,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,IAAI;AACF,MAAA,IAAI,6BAAA,CAA8B,YAAY,KAAA,CAAA,EAAW;AACvD,QAAA,6BAAA,CAA8B,OAAA,GAAU,UAAA;AAExC,QAAA,IAAI,CAAC,MAAA,EAAQ;AACX,UAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,QACvD;AAEA,QAAA,aAAA,CAAc,UAAA,GAAa,OAAA;AAC3B,QAAA,aAAA,CAAc,aAAA,GAAgB,eAAA;AAE9B,QAAA,MAAM,eAAA,GAAkB,OAAA,IAAA,IAAA,GAAA,OAAA,GAAY,MAAA,GAAS,CAAC,MAAM,CAAA,GAAI,KAAA,CAAA;AAExD,QAAA,MAAM,WAAA,GAA2B;AAAA,UAC/B,OAAA,EAAS,iBAAA;AAAA,UACT,MAAA;AAAA,UACA,OAAA,EAAS,eAAA;AAAA,UACT,MAAA;AAAA,UACA,OAAA;AAAA,UACA,uBAAA;AAAA,UACA;AAAA,SACF;AAEA,QAAA,aAAA,CACG,IAAA,CAAK,WAAW,CAAA,CAChB,IAAA,CAAK,MAAM;AACV,UAAA,mBAAA,CAAoB,UAAU,CAAA;AAC9B,UAAA,UAAA,CAAW,KAAK,CAAA;AAEhB,UAAA,IAAI,YAAA,EAAc;AAChB,YAAA,aAAA,CAAc,IAAA,CAAK,EAAE,aAAA,EAAe,YAAA,EAAc,CAAA;AAAA,UACpD;AAAA,QACF,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,MAAA,KAAgB;AACtB,UAAA,UAAA,CAAW,KAAK,CAAA;AAChB,UAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,QAChB,CAAC,CAAA;AAAA,MACL,CAAA,MAAO;AACL,QAAA,6BAAA,CAA8B,OAAA,GAAU,UAAA;AAExC,QAAA,aAAA,CACG,aAAA,CAAc,iBAAiB,CAAA,CAC/B,IAAA,CAAK,MAAM;AACV,UAAA,mBAAA,CAAoB,UAAU,CAAA;AAC9B,UAAA,UAAA,CAAW,KAAK,CAAA;AAAA,QAClB,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,MAAA,KAAgB;AACtB,UAAA,UAAA,CAAW,KAAK,CAAA;AAChB,UAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,QAChB,CAAC,CAAA;AAAA,MACL;AAAA,IACF,SAAS,CAAA,EAAG;AACV,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA,OAAA,CAAQ,CAAU,CAAA;AAAA,IACpB;AAAA,EACF,CAAA,EAAG;AAAA,IACD,MAAA;AAAA,IACA,gBAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA,aAAA,CAAc;AAAA,GACf,CAAA;AAOD,EAAAA,sBAAA,CAAM,SAAA;AAAA,IACJ,MAAM,MAAM;AACV,MAAA,aAAA,CAAc,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AACpC,MAAA,6BAAA,CAA8B,OAAA,GAAU,MAAA;AAAA,IAC1C,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,KAAA,GAAQA,sBAAA,CAAM,OAAA,CAAQ,MAAM;AAChC,IAAA,MAAM,WAAA,GAA+B;AAAA,MACnC,SAAA,EAAW,aAAA,CAAc,SAAA,CAAU,IAAA,CAAK,aAAa,CAAA;AAAA,MACrD,iBAAA;AAAA,MACA,GAAA,EAAK,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,aAAa,CAAA;AAAA,MACzC,WAAA,EAAa,aAAA,CAAc,WAAA,CAAY,IAAA,CAAK,aAAa,CAAA;AAAA,MACzD,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,aAAA,CAAc,SAAS,CAAA;AAAA,MACzC,OAAA,EAAS,aAAA;AAAA,MACT,OAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,gBAAA,EAAkB,OAAA,EAAS,cAAc,YAAA,EAAc,QAAA,EAAU,WAAW,CAAC,CAAA;AAEjF,EAAA,uBACEA,sBAAA,CAAA,aAAA,CAAC,oBAAA,CAAqB,QAAA,EAArB,EAA8B,KAAA,EAAO,aAAA,EAAA,kBACpCA,sBAAA,CAAA,aAAA,CAAC,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAA,EAAe,QAAS,CACnD,CAAA;AAEJ;AC1WA,SAAS,mBAAA,CAAoB;AAAA,EAC3B,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAgD;AAC9C,EAAA,MAAM,GAAA,GAAM,CAAC,GAAA,KAAgB,MAAA,CAAO,GAAG,CAAA;AACvC,EAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAAgB,MAAA,CAAO,GAAG,CAAA;AAC/C,EAAA,MAAM,YAAY,CAAC,GAAA,KAAgB,CAAC,CAAC,IAAI,GAAG,CAAA;AAE5C,EAAA,MAAM,gBAAgB,gBAAA,EAAiB;AAEvC,EAAA,MAAM,KAAA,GAAQA,sBAAAA,CAAM,OAAA,CAAQ,MAAM;AAChC,IAAA,aAAA,CAAc,GAAA,GAAM,GAAA;AACpB,IAAA,aAAA,CAAc,WAAA,GAAc,WAAA;AAC5B,IAAA,aAAA,CAAc,SAAA,GAAY,SAAA;AAE1B,IAAA,MAAM,WAAA,GAA+B;AAAA,MACnC,SAAA;AAAA,MACA,mBAAmB,MAAA,CAAO,iBAAA;AAAA,MAC1B,GAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,KAAA;AAAA,MACT,OAAA,EAAS,aAAA;AAAA,MACT,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AAAA,MACxB,QAAA,EAAU,EAAE,MAAA,EAAQ,MAAA,IAAA,IAAA,GAAA,MAAA,GAAU,oCAAA;AAAqC,KACrE;AAEA,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,MAAA,EAAQ,aAAA,EAAe,MAAM,CAAC,CAAA;AAElC,EAAA,uBACEA,sBAAAA,CAAA,aAAA,CAAC,oBAAA,CAAqB,QAAA,EAArB,EAA8B,KAAA,EAAO,aAAA,EAAA,kBACpCA,sBAAAA,CAAA,cAAC,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAA,EAAe,QAAS,CACnD,CAAA;AAEJ","file":"index.cjs","sourcesContent":["// AUTO-GENERATED from package.json by scripts/generate-version.mjs — do not edit.\nexport default \"0.0.9\";\n","/**\n * Pluggable logger interface for SDK-internal warnings and errors.\n *\n * Shape mirrors @quonfig/node so the contract is uniform across the\n * TypeScript SDKs: `warn` and `error` are required; `debug` and `info` are\n * optional and become no-ops when the supplied logger does not implement\n * them.\n */\nexport interface Logger {\n debug?(message: string, ...args: unknown[]): void;\n info?(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport interface NormalizedLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst NOOP = (): void => {};\n\nconst PREFIX = \"[quonfig]\";\n\nfunction defaultSdkLogger(): NormalizedLogger {\n return {\n /* eslint-disable no-console */\n debug: (message, ...args) => console.debug(PREFIX, message, ...args),\n info: (message, ...args) => console.info(PREFIX, message, ...args),\n warn: (message, ...args) => console.warn(PREFIX, message, ...args),\n error: (message, ...args) => console.error(PREFIX, message, ...args),\n /* eslint-enable no-console */\n };\n}\n\nexport function normalizeLogger(logger: Logger | undefined): NormalizedLogger {\n if (!logger) return defaultSdkLogger();\n return {\n debug: logger.debug ? logger.debug.bind(logger) : NOOP,\n info: logger.info ? logger.info.bind(logger) : NOOP,\n warn: logger.warn.bind(logger),\n error: logger.error.bind(logger),\n };\n}\n","import React, { PropsWithChildren } from \"react\";\nimport {\n quonfig,\n type InitOptions,\n type ConfigValue,\n type Contexts,\n Quonfig,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Duration,\n encodeContexts,\n} from \"@quonfig/javascript\";\nimport reactSdkVersion from \"./version\";\nimport { normalizeLogger, type Logger, type NormalizedLogger } from \"./sdkLogger\";\n\n// qfg-lkpm.6: per-tree owner context. The value is the active Quonfig client\n// for this provider subtree. A null value means no Provider is above us, so\n// the next mount can claim the module-level singleton; a non-null value\n// signals \"you're nested, mint a fresh client\". This replaces the previous\n// module-level `globalQuonfigIsTaken` flag, which never reset and so leaked\n// state across test runs and (in principle) across SSR render trees.\nconst QuonfigClientContext = React.createContext<Quonfig | null>(null);\n\n// @quonfig/cli#generate will create interfaces into this namespace for React to consume\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface FrontEndConfigurationAccessor {}\n\nexport type TypedFrontEndConfigurationAccessor = keyof FrontEndConfigurationAccessor extends never\n ? Record<string, unknown>\n : {\n [TypedFlagKey in keyof FrontEndConfigurationAccessor]: FrontEndConfigurationAccessor[TypedFlagKey];\n };\n\ntype ClassMethods<T> = { [K in keyof T]: T[K] };\n\ntype QuonfigTypesafeClass<T = unknown> = new (\n // eslint-disable-next-line no-shadow\n quonfig: Quonfig\n) => T;\n\ntype SharedSettings = Partial<\n Pick<InitOptions, \"sdkKey\" | \"apiUrls\" | \"domain\" | \"timeout\" | \"collectEvaluationSummaries\">\n> & {\n // Convenience alias for a single API URL — normalized to apiUrls=[apiUrl]\n // before being passed to the underlying SDK, which only accepts apiUrls.\n apiUrl?: string;\n // We need to redefine the afterEvaluationCallback type to ensure proper dynamic resolution of K\n afterEvaluationCallback?: <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n contexts: Contexts | undefined\n ) => void;\n pollInterval?: number;\n onError?: (error: Error) => void;\n};\n\nexport type BaseContext = {\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n getDuration: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => Duration | undefined;\n contextAttributes: Contexts;\n isEnabled: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => boolean;\n loading: boolean;\n quonfig: typeof quonfig;\n keys: (keyof TypedFrontEndConfigurationRaw)[];\n settings: SharedSettings;\n};\n\nexport type ProvidedContext = BaseContext & ClassMethods<QuonfigTypesafeClass>;\n\nexport const defaultContext: BaseContext = {\n get: (_key) => undefined,\n getDuration: (_key) => undefined,\n isEnabled: (_key) => false,\n keys: [],\n loading: true,\n contextAttributes: {},\n quonfig,\n settings: {},\n};\n\nexport const QuonfigContext = React.createContext<ProvidedContext>(\n defaultContext as ProvidedContext\n);\n\n// This is a factory function that creates a fully typed useQuonfig hook for a specific QuonfigTypesafe class\nexport function createQuonfigHook<T>(TypesafeClass: QuonfigTypesafeClass<T>) {\n return function useQuonfigHook(): BaseContext & T {\n const baseContext = React.useContext(QuonfigContext);\n\n // Memoize the typesafe instance to prevent unnecessary constructor calls\n const typesafeInstance = React.useMemo(() => {\n const instance = new TypesafeClass(baseContext.quonfig);\n\n // Copy baseContext properties to typesafeInstance except for `get` + `quonfig`\n Object.assign(instance as any, {\n getDuration: baseContext.getDuration,\n contextAttributes: baseContext.contextAttributes,\n isEnabled: baseContext.isEnabled,\n loading: baseContext.loading,\n keys: baseContext.keys,\n settings: baseContext.settings,\n });\n\n return instance;\n }, [baseContext]);\n\n return typesafeInstance as BaseContext & T;\n };\n}\n\n// Basic hook for general use - requires type parameter\nexport const useBaseQuonfig = () => React.useContext(QuonfigContext);\n\n// General hook that returns the context with any explicit type\nexport const useQuonfig = (): ProvidedContext => useBaseQuonfig() as unknown as ProvidedContext;\n\n// qfg-lkpm.6: per-key selector hook. Subscribes via the underlying client's\n// notify list rather than React context, so a flag mutation only re-renders\n// components whose selected key actually changed. `useQuonfig()` re-renders\n// on every dataVersion bump because the context value identity changes; this\n// hook bypasses that.\nexport function useFlag<K extends keyof TypedFrontEndConfigurationRaw>(\n key: K\n): TypedFrontEndConfigurationRaw[K];\nexport function useFlag(key: string): ConfigValue;\nexport function useFlag(key: string): ConfigValue {\n const client = React.useContext(QuonfigClientContext) ?? quonfig;\n const subscribe = React.useCallback(\n (onChange: () => void) => client.subscribe(onChange),\n [client]\n );\n const getSnapshot = React.useCallback(() => client.get(key), [client, key]);\n const getServerSnapshot = React.useCallback((): ConfigValue => undefined, []);\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n// qfg-lkpm.6: replacement for the old module-level `globalQuonfigIsTaken`\n// flag. A provider asks \"is there already a Quonfig client above me in the\n// React tree?\". If yes, mint a fresh client (multi-tenant nesting); if no,\n// claim the module singleton so non-React code that imports `quonfig`\n// directly sees the same instance.\nexport const useQuonfigClient = (): Quonfig => {\n const parentClient = React.useContext(QuonfigClientContext);\n // Mount-only: parent context is fixed for the lifetime of this provider.\n const parentClientRef = React.useRef(parentClient);\n return React.useMemo(() => (parentClientRef.current ? new Quonfig() : quonfig), []);\n};\n\nexport type QuonfigProviderProps = SharedSettings & {\n sdkKey: string;\n contextAttributes?: Contexts;\n initialFlags?: Record<string, unknown>;\n logger?: Logger;\n};\n\nconst getContextKey = (\n contextAttributes: Contexts,\n logger: NormalizedLogger,\n onError: (e: Error) => void\n): string => {\n try {\n if (Object.keys(contextAttributes).length === 0) {\n logger.warn(\n \"QuonfigProvider: You haven't passed any contextAttributes. See https://docs.quonfig.com/docs/sdks/react#using-context\"\n );\n }\n\n return encodeContexts(contextAttributes);\n } catch (e) {\n onError(e as Error);\n return \"\";\n }\n};\n\nfunction QuonfigProvider({\n sdkKey,\n contextAttributes = {},\n onError: userOnError,\n logger,\n initialFlags,\n children,\n timeout,\n apiUrl,\n apiUrls,\n domain,\n pollInterval,\n afterEvaluationCallback = undefined,\n collectEvaluationSummaries,\n}: PropsWithChildren<QuonfigProviderProps>) {\n const normalizedLogger = React.useMemo(() => normalizeLogger(logger), [logger]);\n const onError = React.useCallback(\n (e: unknown) => {\n if (userOnError) {\n userOnError(e as Error);\n } else {\n const message = e instanceof Error ? e.message : String(e);\n normalizedLogger.error(message, e);\n }\n },\n [userOnError, normalizedLogger]\n );\n const settings = {\n sdkKey,\n apiUrl,\n apiUrls,\n domain,\n timeout,\n pollInterval,\n onError,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n // We use this state to prevent a double-init when useEffect fires due to\n // StrictMode\n const mostRecentlyLoadingContextKey = React.useRef<string | undefined>(undefined);\n // We use this state to pass the loading state to the Provider (updating\n // currentLoadingContextKey won't trigger an update)\n const [loading, setLoading] = React.useState(true);\n const [initialLoad, setInitialLoad] = React.useState(true);\n // Here we track the current identity so we can reload our config when it\n // changes\n const [loadedContextKey, setLoadedContextKey] = React.useState(\"\");\n\n const quonfigClient: Quonfig = useQuonfigClient();\n\n // qfg-daxq: re-render when the underlying client's in-memory config changes\n // (poll fetch, setConfig, hydrate). Without this the singleton mutates in\n // place and React never sees the update.\n const dataVersion = React.useSyncExternalStore(\n React.useCallback((onChange) => quonfigClient.subscribe(onChange), [quonfigClient]),\n React.useCallback(() => quonfigClient.dataVersion, [quonfigClient]),\n React.useCallback(() => 0, [])\n );\n\n const contextKey = getContextKey(contextAttributes, normalizedLogger, onError);\n\n if (initialFlags && initialLoad) {\n quonfigClient.hydrate(initialFlags);\n setInitialLoad(false);\n setLoadedContextKey(contextKey);\n setLoading(false);\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (pollInterval) {\n normalizedLogger.warn(\"Polling is not supported when hydrating flags via initialFlags\");\n }\n }\n\n React.useEffect(() => {\n setInitialLoad(false);\n\n if (mostRecentlyLoadingContextKey.current === contextKey) {\n return;\n }\n\n setLoading(true);\n try {\n if (mostRecentlyLoadingContextKey.current === undefined) {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (!sdkKey) {\n throw new Error(\"QuonfigProvider: sdkKey is required\");\n }\n\n quonfigClient.clientName = \"react\";\n quonfigClient.clientVersion = reactSdkVersion;\n\n const resolvedApiUrls = apiUrls ?? (apiUrl ? [apiUrl] : undefined);\n\n const initOptions: InitOptions = {\n context: contextAttributes,\n sdkKey,\n apiUrls: resolvedApiUrls,\n domain,\n timeout,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n quonfigClient\n .init(initOptions)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n\n if (pollInterval) {\n quonfigClient.poll({ frequencyInMs: pollInterval });\n }\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n } else {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n quonfigClient\n .updateContext(contextAttributes)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n }\n } catch (e) {\n setLoading(false);\n onError(e as Error);\n }\n }, [\n sdkKey,\n loadedContextKey,\n contextKey,\n loading,\n setLoading,\n onError,\n quonfigClient.instanceHash,\n ]);\n\n // qfg-2acr: drain telemetry + stop polling/telemetry timers when the\n // provider unmounts so route swaps don't leave the singleton polling\n // forever. Mount-only deps so context-attribute changes don't tear down\n // the SDK. In React StrictMode the synthetic unmount fires too — we\n // reset the init-guard ref so the next mount cleanly re-inits.\n React.useEffect(\n () => () => {\n quonfigClient.close().catch(() => {});\n mostRecentlyLoadingContextKey.current = undefined;\n },\n [quonfigClient]\n );\n\n const value = React.useMemo(() => {\n const baseContext: ProvidedContext = {\n isEnabled: quonfigClient.isEnabled.bind(quonfigClient),\n contextAttributes,\n get: quonfigClient.get.bind(quonfigClient),\n getDuration: quonfigClient.getDuration.bind(quonfigClient),\n keys: Object.keys(quonfigClient.extract()),\n quonfig: quonfigClient,\n loading,\n settings,\n };\n\n return baseContext;\n }, [loadedContextKey, loading, quonfigClient.instanceHash, settings, dataVersion]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigProvider, QuonfigClientContext, ConfigValue, SharedSettings, QuonfigTypesafeClass };\n","import React, { PropsWithChildren } from \"react\";\nimport {\n QuonfigContext,\n QuonfigClientContext,\n useQuonfigClient,\n ProvidedContext,\n} from \"./QuonfigProvider\";\n\nexport type QuonfigTestProviderProps = {\n config: Record<string, any>;\n sdkKey?: string;\n};\n\nfunction QuonfigTestProvider({\n sdkKey,\n config,\n children,\n}: PropsWithChildren<QuonfigTestProviderProps>) {\n const get = (key: string) => config[key];\n const getDuration = (key: string) => config[key];\n const isEnabled = (key: string) => !!get(key);\n\n const quonfigClient = useQuonfigClient();\n\n const value = React.useMemo(() => {\n quonfigClient.get = get;\n quonfigClient.getDuration = getDuration;\n quonfigClient.isEnabled = isEnabled;\n\n const baseContext: ProvidedContext = {\n isEnabled,\n contextAttributes: config.contextAttributes,\n get,\n getDuration,\n loading: false,\n quonfig: quonfigClient,\n keys: Object.keys(config),\n settings: { sdkKey: sdkKey ?? \"fake-sdk-key-via-the-test-provider\" },\n };\n\n return baseContext;\n }, [config, quonfigClient, sdkKey]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigTestProvider };\n"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/sdkLogger.ts","../src/QuonfigProvider.tsx","../src/QuonfigTestProvider.tsx"],"names":["React","quonfig","Quonfig","encodeContexts"],"mappings":"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","file":"index.cjs","sourcesContent":["// AUTO-GENERATED from package.json by scripts/generate-version.mjs — do not edit.\nexport default \"0.0.15\";\n","/**\n * Pluggable logger interface for SDK-internal warnings and errors.\n *\n * Shape mirrors @quonfig/node so the contract is uniform across the\n * TypeScript SDKs: `warn` and `error` are required; `debug` and `info` are\n * optional and become no-ops when the supplied logger does not implement\n * them.\n */\nexport interface Logger {\n debug?(message: string, ...args: unknown[]): void;\n info?(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport interface NormalizedLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst NOOP = (): void => {};\n\nconst PREFIX = \"[quonfig]\";\n\nfunction defaultSdkLogger(): NormalizedLogger {\n return {\n /* eslint-disable no-console */\n debug: (message, ...args) => console.debug(PREFIX, message, ...args),\n info: (message, ...args) => console.info(PREFIX, message, ...args),\n warn: (message, ...args) => console.warn(PREFIX, message, ...args),\n error: (message, ...args) => console.error(PREFIX, message, ...args),\n /* eslint-enable no-console */\n };\n}\n\nexport function normalizeLogger(logger: Logger | undefined): NormalizedLogger {\n if (!logger) return defaultSdkLogger();\n return {\n debug: logger.debug ? logger.debug.bind(logger) : NOOP,\n info: logger.info ? logger.info.bind(logger) : NOOP,\n warn: logger.warn.bind(logger),\n error: logger.error.bind(logger),\n };\n}\n","import React, { PropsWithChildren } from \"react\";\nimport {\n quonfig,\n type InitOptions,\n type ConfigValue,\n type Contexts,\n Quonfig,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Duration,\n encodeContexts,\n} from \"@quonfig/javascript\";\nimport reactSdkVersion from \"./version\";\nimport { normalizeLogger, type Logger, type NormalizedLogger } from \"./sdkLogger\";\n\n// qfg-lkpm.6: per-tree owner context. The value is the active Quonfig client\n// for this provider subtree. A null value means no Provider is above us, so\n// the next mount can claim the module-level singleton; a non-null value\n// signals \"you're nested, mint a fresh client\". This replaces the previous\n// module-level `globalQuonfigIsTaken` flag, which never reset and so leaked\n// state across test runs and (in principle) across SSR render trees.\nconst QuonfigClientContext = React.createContext<Quonfig | null>(null);\n\n// @quonfig/cli#generate will create interfaces into this namespace for React to consume\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface FrontEndConfigurationAccessor {}\n\nexport type TypedFrontEndConfigurationAccessor = keyof FrontEndConfigurationAccessor extends never\n ? Record<string, unknown>\n : {\n [TypedFlagKey in keyof FrontEndConfigurationAccessor]: FrontEndConfigurationAccessor[TypedFlagKey];\n };\n\ntype ClassMethods<T> = { [K in keyof T]: T[K] };\n\ntype QuonfigTypesafeClass<T = unknown> = new (\n // eslint-disable-next-line no-shadow\n quonfig: Quonfig\n) => T;\n\ntype SharedSettings = Partial<\n Pick<InitOptions, \"sdkKey\" | \"apiUrls\" | \"domain\" | \"timeout\" | \"collectEvaluationSummaries\">\n> & {\n // Convenience alias for a single API URL — normalized to apiUrls=[apiUrl]\n // before being passed to the underlying SDK, which only accepts apiUrls.\n apiUrl?: string;\n // We need to redefine the afterEvaluationCallback type to ensure proper dynamic resolution of K\n afterEvaluationCallback?: <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n contexts: Contexts | undefined\n ) => void;\n pollInterval?: number;\n onError?: (error: Error) => void;\n};\n\nexport type BaseContext = {\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n getDuration: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => Duration | undefined;\n contextAttributes: Contexts;\n isEnabled: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => boolean;\n loading: boolean;\n quonfig: typeof quonfig;\n keys: (keyof TypedFrontEndConfigurationRaw)[];\n settings: SharedSettings;\n};\n\nexport type ProvidedContext = BaseContext & ClassMethods<QuonfigTypesafeClass>;\n\nexport const defaultContext: BaseContext = {\n get: (_key) => undefined,\n getDuration: (_key) => undefined,\n isEnabled: (_key) => false,\n keys: [],\n loading: true,\n contextAttributes: {},\n quonfig,\n settings: {},\n};\n\nexport const QuonfigContext = React.createContext<ProvidedContext>(\n defaultContext as ProvidedContext\n);\n\n// This is a factory function that creates a fully typed useQuonfig hook for a specific QuonfigTypesafe class\nexport function createQuonfigHook<T>(TypesafeClass: QuonfigTypesafeClass<T>) {\n return function useQuonfigHook(): BaseContext & T {\n const baseContext = React.useContext(QuonfigContext);\n\n // Memoize the typesafe instance to prevent unnecessary constructor calls\n const typesafeInstance = React.useMemo(() => {\n const instance = new TypesafeClass(baseContext.quonfig);\n\n // Copy baseContext properties to typesafeInstance except for `get` + `quonfig`\n Object.assign(instance as any, {\n getDuration: baseContext.getDuration,\n contextAttributes: baseContext.contextAttributes,\n isEnabled: baseContext.isEnabled,\n loading: baseContext.loading,\n keys: baseContext.keys,\n settings: baseContext.settings,\n });\n\n return instance;\n }, [baseContext]);\n\n return typesafeInstance as BaseContext & T;\n };\n}\n\n// Basic hook for general use - requires type parameter\nexport const useBaseQuonfig = () => React.useContext(QuonfigContext);\n\n// General hook that returns the context with any explicit type\nexport const useQuonfig = (): ProvidedContext => useBaseQuonfig() as unknown as ProvidedContext;\n\n// qfg-lkpm.6: per-key selector hook. Subscribes via the underlying client's\n// notify list rather than React context, so a flag mutation only re-renders\n// components whose selected key actually changed. `useQuonfig()` re-renders\n// on every dataVersion bump because the context value identity changes; this\n// hook bypasses that.\nexport function useFlag<K extends keyof TypedFrontEndConfigurationRaw>(\n key: K\n): TypedFrontEndConfigurationRaw[K];\nexport function useFlag(key: string): ConfigValue;\nexport function useFlag(key: string): ConfigValue {\n const client = React.useContext(QuonfigClientContext) ?? quonfig;\n const subscribe = React.useCallback(\n (onChange: () => void) => client.subscribe(onChange),\n [client]\n );\n const getSnapshot = React.useCallback(() => client.get(key), [client, key]);\n const getServerSnapshot = React.useCallback((): ConfigValue => undefined, []);\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n// qfg-lkpm.6: replacement for the old module-level `globalQuonfigIsTaken`\n// flag. A provider asks \"is there already a Quonfig client above me in the\n// React tree?\". If yes, mint a fresh client (multi-tenant nesting); if no,\n// claim the module singleton so non-React code that imports `quonfig`\n// directly sees the same instance.\nexport const useQuonfigClient = (): Quonfig => {\n const parentClient = React.useContext(QuonfigClientContext);\n // Mount-only: parent context is fixed for the lifetime of this provider.\n const parentClientRef = React.useRef(parentClient);\n return React.useMemo(() => (parentClientRef.current ? new Quonfig() : quonfig), []);\n};\n\nexport type QuonfigProviderProps = SharedSettings & {\n sdkKey: string;\n contextAttributes?: Contexts;\n initialFlags?: Record<string, unknown>;\n logger?: Logger;\n};\n\nconst getContextKey = (\n contextAttributes: Contexts,\n logger: NormalizedLogger,\n onError: (e: Error) => void\n): string => {\n try {\n if (Object.keys(contextAttributes).length === 0) {\n logger.warn(\n \"QuonfigProvider: You haven't passed any contextAttributes. See https://docs.quonfig.com/docs/sdks/react#using-context\"\n );\n }\n\n return encodeContexts(contextAttributes);\n } catch (e) {\n onError(e as Error);\n return \"\";\n }\n};\n\nfunction QuonfigProvider({\n sdkKey,\n contextAttributes = {},\n onError: userOnError,\n logger,\n initialFlags,\n children,\n timeout,\n apiUrl,\n apiUrls,\n domain,\n pollInterval,\n afterEvaluationCallback = undefined,\n collectEvaluationSummaries,\n}: PropsWithChildren<QuonfigProviderProps>) {\n const normalizedLogger = React.useMemo(() => normalizeLogger(logger), [logger]);\n const onError = React.useCallback(\n (e: unknown) => {\n if (userOnError) {\n userOnError(e as Error);\n } else {\n const message = e instanceof Error ? e.message : String(e);\n normalizedLogger.error(message, e);\n }\n },\n [userOnError, normalizedLogger]\n );\n const settings = {\n sdkKey,\n apiUrl,\n apiUrls,\n domain,\n timeout,\n pollInterval,\n onError,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n // We use this state to prevent a double-init when useEffect fires due to\n // StrictMode\n const mostRecentlyLoadingContextKey = React.useRef<string | undefined>(undefined);\n // We use this state to pass the loading state to the Provider (updating\n // currentLoadingContextKey won't trigger an update)\n const [loading, setLoading] = React.useState(true);\n const [initialLoad, setInitialLoad] = React.useState(true);\n // Here we track the current identity so we can reload our config when it\n // changes\n const [loadedContextKey, setLoadedContextKey] = React.useState(\"\");\n\n const quonfigClient: Quonfig = useQuonfigClient();\n\n // qfg-daxq: re-render when the underlying client's in-memory config changes\n // (poll fetch, setConfig, hydrate). Without this the singleton mutates in\n // place and React never sees the update.\n const dataVersion = React.useSyncExternalStore(\n React.useCallback((onChange) => quonfigClient.subscribe(onChange), [quonfigClient]),\n React.useCallback(() => quonfigClient.dataVersion, [quonfigClient]),\n React.useCallback(() => 0, [])\n );\n\n const contextKey = getContextKey(contextAttributes, normalizedLogger, onError);\n\n if (initialFlags && initialLoad) {\n quonfigClient.hydrate(initialFlags);\n setInitialLoad(false);\n setLoadedContextKey(contextKey);\n setLoading(false);\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (pollInterval) {\n normalizedLogger.warn(\"Polling is not supported when hydrating flags via initialFlags\");\n }\n }\n\n React.useEffect(() => {\n setInitialLoad(false);\n\n if (mostRecentlyLoadingContextKey.current === contextKey) {\n return;\n }\n\n setLoading(true);\n try {\n if (mostRecentlyLoadingContextKey.current === undefined) {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (!sdkKey) {\n throw new Error(\"QuonfigProvider: sdkKey is required\");\n }\n\n quonfigClient.clientName = \"react\";\n quonfigClient.clientVersion = reactSdkVersion;\n\n const resolvedApiUrls = apiUrls ?? (apiUrl ? [apiUrl] : undefined);\n\n const initOptions: InitOptions = {\n context: contextAttributes,\n sdkKey,\n apiUrls: resolvedApiUrls,\n domain,\n timeout,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n quonfigClient\n .init(initOptions)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n\n if (pollInterval) {\n // poll()'s first fetch can reject on a startup network blip, but\n // the polling loop is still scheduled and self-heals on the next\n // tick (qfg-8uw5). Attach a catch so that expected first-fetch\n // rejection is a non-fatal warning, not an unhandled rejection —\n // and don't route it through onError, which would surface a\n // user-facing error for a transient blip that recovers on its own.\n quonfigClient.poll({ frequencyInMs: pollInterval }).catch((err) => {\n normalizedLogger.warn(\"Initial poll fetch failed; polling will retry\", err);\n });\n }\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n } else {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n quonfigClient\n .updateContext(contextAttributes)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n }\n } catch (e) {\n setLoading(false);\n onError(e as Error);\n }\n }, [\n sdkKey,\n loadedContextKey,\n contextKey,\n loading,\n setLoading,\n onError,\n quonfigClient.instanceHash,\n ]);\n\n // qfg-2acr: drain telemetry + stop polling/telemetry timers when the\n // provider unmounts so route swaps don't leave the singleton polling\n // forever. Mount-only deps so context-attribute changes don't tear down\n // the SDK. In React StrictMode the synthetic unmount fires too — we\n // reset the init-guard ref so the next mount cleanly re-inits.\n React.useEffect(\n () => () => {\n quonfigClient.close().catch(() => {});\n mostRecentlyLoadingContextKey.current = undefined;\n },\n [quonfigClient]\n );\n\n const value = React.useMemo(() => {\n const baseContext: ProvidedContext = {\n isEnabled: quonfigClient.isEnabled.bind(quonfigClient),\n contextAttributes,\n get: quonfigClient.get.bind(quonfigClient),\n getDuration: quonfigClient.getDuration.bind(quonfigClient),\n keys: Object.keys(quonfigClient.extract()),\n quonfig: quonfigClient,\n loading,\n settings,\n };\n\n return baseContext;\n }, [loadedContextKey, loading, quonfigClient.instanceHash, settings, dataVersion]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigProvider, QuonfigClientContext, ConfigValue, SharedSettings, QuonfigTypesafeClass };\n","import React, { PropsWithChildren } from \"react\";\nimport {\n QuonfigContext,\n QuonfigClientContext,\n useQuonfigClient,\n ProvidedContext,\n} from \"./QuonfigProvider\";\n\nexport type QuonfigTestProviderProps = {\n config: Record<string, any>;\n sdkKey?: string;\n};\n\nfunction QuonfigTestProvider({\n sdkKey,\n config,\n children,\n}: PropsWithChildren<QuonfigTestProviderProps>) {\n const get = (key: string) => config[key];\n const getDuration = (key: string) => config[key];\n const isEnabled = (key: string) => !!get(key);\n\n const quonfigClient = useQuonfigClient();\n\n const value = React.useMemo(() => {\n quonfigClient.get = get;\n quonfigClient.getDuration = getDuration;\n quonfigClient.isEnabled = isEnabled;\n\n const baseContext: ProvidedContext = {\n isEnabled,\n contextAttributes: config.contextAttributes,\n get,\n getDuration,\n loading: false,\n quonfig: quonfigClient,\n keys: Object.keys(config),\n settings: { sdkKey: sdkKey ?? \"fake-sdk-key-via-the-test-provider\" },\n };\n\n return baseContext;\n }, [config, quonfigClient, sdkKey]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigTestProvider };\n"]}
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import React from 'react';
5
5
  // src/index.tsx
6
6
 
7
7
  // src/version.ts
8
- var version_default = "0.0.9";
8
+ var version_default = "0.0.15";
9
9
 
10
10
  // src/sdkLogger.ts
11
11
  var NOOP = () => {
@@ -182,7 +182,9 @@ function QuonfigProvider({
182
182
  setLoadedContextKey(contextKey);
183
183
  setLoading(false);
184
184
  if (pollInterval) {
185
- quonfigClient.poll({ frequencyInMs: pollInterval });
185
+ quonfigClient.poll({ frequencyInMs: pollInterval }).catch((err) => {
186
+ normalizedLogger.warn("Initial poll fetch failed; polling will retry", err);
187
+ });
186
188
  }
187
189
  }).catch((reason) => {
188
190
  setLoading(false);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/sdkLogger.ts","../src/QuonfigProvider.tsx","../src/QuonfigTestProvider.tsx"],"names":["React"],"mappings":"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","file":"index.mjs","sourcesContent":["// AUTO-GENERATED from package.json by scripts/generate-version.mjs — do not edit.\nexport default \"0.0.9\";\n","/**\n * Pluggable logger interface for SDK-internal warnings and errors.\n *\n * Shape mirrors @quonfig/node so the contract is uniform across the\n * TypeScript SDKs: `warn` and `error` are required; `debug` and `info` are\n * optional and become no-ops when the supplied logger does not implement\n * them.\n */\nexport interface Logger {\n debug?(message: string, ...args: unknown[]): void;\n info?(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport interface NormalizedLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst NOOP = (): void => {};\n\nconst PREFIX = \"[quonfig]\";\n\nfunction defaultSdkLogger(): NormalizedLogger {\n return {\n /* eslint-disable no-console */\n debug: (message, ...args) => console.debug(PREFIX, message, ...args),\n info: (message, ...args) => console.info(PREFIX, message, ...args),\n warn: (message, ...args) => console.warn(PREFIX, message, ...args),\n error: (message, ...args) => console.error(PREFIX, message, ...args),\n /* eslint-enable no-console */\n };\n}\n\nexport function normalizeLogger(logger: Logger | undefined): NormalizedLogger {\n if (!logger) return defaultSdkLogger();\n return {\n debug: logger.debug ? logger.debug.bind(logger) : NOOP,\n info: logger.info ? logger.info.bind(logger) : NOOP,\n warn: logger.warn.bind(logger),\n error: logger.error.bind(logger),\n };\n}\n","import React, { PropsWithChildren } from \"react\";\nimport {\n quonfig,\n type InitOptions,\n type ConfigValue,\n type Contexts,\n Quonfig,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Duration,\n encodeContexts,\n} from \"@quonfig/javascript\";\nimport reactSdkVersion from \"./version\";\nimport { normalizeLogger, type Logger, type NormalizedLogger } from \"./sdkLogger\";\n\n// qfg-lkpm.6: per-tree owner context. The value is the active Quonfig client\n// for this provider subtree. A null value means no Provider is above us, so\n// the next mount can claim the module-level singleton; a non-null value\n// signals \"you're nested, mint a fresh client\". This replaces the previous\n// module-level `globalQuonfigIsTaken` flag, which never reset and so leaked\n// state across test runs and (in principle) across SSR render trees.\nconst QuonfigClientContext = React.createContext<Quonfig | null>(null);\n\n// @quonfig/cli#generate will create interfaces into this namespace for React to consume\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface FrontEndConfigurationAccessor {}\n\nexport type TypedFrontEndConfigurationAccessor = keyof FrontEndConfigurationAccessor extends never\n ? Record<string, unknown>\n : {\n [TypedFlagKey in keyof FrontEndConfigurationAccessor]: FrontEndConfigurationAccessor[TypedFlagKey];\n };\n\ntype ClassMethods<T> = { [K in keyof T]: T[K] };\n\ntype QuonfigTypesafeClass<T = unknown> = new (\n // eslint-disable-next-line no-shadow\n quonfig: Quonfig\n) => T;\n\ntype SharedSettings = Partial<\n Pick<InitOptions, \"sdkKey\" | \"apiUrls\" | \"domain\" | \"timeout\" | \"collectEvaluationSummaries\">\n> & {\n // Convenience alias for a single API URL — normalized to apiUrls=[apiUrl]\n // before being passed to the underlying SDK, which only accepts apiUrls.\n apiUrl?: string;\n // We need to redefine the afterEvaluationCallback type to ensure proper dynamic resolution of K\n afterEvaluationCallback?: <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n contexts: Contexts | undefined\n ) => void;\n pollInterval?: number;\n onError?: (error: Error) => void;\n};\n\nexport type BaseContext = {\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n getDuration: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => Duration | undefined;\n contextAttributes: Contexts;\n isEnabled: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => boolean;\n loading: boolean;\n quonfig: typeof quonfig;\n keys: (keyof TypedFrontEndConfigurationRaw)[];\n settings: SharedSettings;\n};\n\nexport type ProvidedContext = BaseContext & ClassMethods<QuonfigTypesafeClass>;\n\nexport const defaultContext: BaseContext = {\n get: (_key) => undefined,\n getDuration: (_key) => undefined,\n isEnabled: (_key) => false,\n keys: [],\n loading: true,\n contextAttributes: {},\n quonfig,\n settings: {},\n};\n\nexport const QuonfigContext = React.createContext<ProvidedContext>(\n defaultContext as ProvidedContext\n);\n\n// This is a factory function that creates a fully typed useQuonfig hook for a specific QuonfigTypesafe class\nexport function createQuonfigHook<T>(TypesafeClass: QuonfigTypesafeClass<T>) {\n return function useQuonfigHook(): BaseContext & T {\n const baseContext = React.useContext(QuonfigContext);\n\n // Memoize the typesafe instance to prevent unnecessary constructor calls\n const typesafeInstance = React.useMemo(() => {\n const instance = new TypesafeClass(baseContext.quonfig);\n\n // Copy baseContext properties to typesafeInstance except for `get` + `quonfig`\n Object.assign(instance as any, {\n getDuration: baseContext.getDuration,\n contextAttributes: baseContext.contextAttributes,\n isEnabled: baseContext.isEnabled,\n loading: baseContext.loading,\n keys: baseContext.keys,\n settings: baseContext.settings,\n });\n\n return instance;\n }, [baseContext]);\n\n return typesafeInstance as BaseContext & T;\n };\n}\n\n// Basic hook for general use - requires type parameter\nexport const useBaseQuonfig = () => React.useContext(QuonfigContext);\n\n// General hook that returns the context with any explicit type\nexport const useQuonfig = (): ProvidedContext => useBaseQuonfig() as unknown as ProvidedContext;\n\n// qfg-lkpm.6: per-key selector hook. Subscribes via the underlying client's\n// notify list rather than React context, so a flag mutation only re-renders\n// components whose selected key actually changed. `useQuonfig()` re-renders\n// on every dataVersion bump because the context value identity changes; this\n// hook bypasses that.\nexport function useFlag<K extends keyof TypedFrontEndConfigurationRaw>(\n key: K\n): TypedFrontEndConfigurationRaw[K];\nexport function useFlag(key: string): ConfigValue;\nexport function useFlag(key: string): ConfigValue {\n const client = React.useContext(QuonfigClientContext) ?? quonfig;\n const subscribe = React.useCallback(\n (onChange: () => void) => client.subscribe(onChange),\n [client]\n );\n const getSnapshot = React.useCallback(() => client.get(key), [client, key]);\n const getServerSnapshot = React.useCallback((): ConfigValue => undefined, []);\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n// qfg-lkpm.6: replacement for the old module-level `globalQuonfigIsTaken`\n// flag. A provider asks \"is there already a Quonfig client above me in the\n// React tree?\". If yes, mint a fresh client (multi-tenant nesting); if no,\n// claim the module singleton so non-React code that imports `quonfig`\n// directly sees the same instance.\nexport const useQuonfigClient = (): Quonfig => {\n const parentClient = React.useContext(QuonfigClientContext);\n // Mount-only: parent context is fixed for the lifetime of this provider.\n const parentClientRef = React.useRef(parentClient);\n return React.useMemo(() => (parentClientRef.current ? new Quonfig() : quonfig), []);\n};\n\nexport type QuonfigProviderProps = SharedSettings & {\n sdkKey: string;\n contextAttributes?: Contexts;\n initialFlags?: Record<string, unknown>;\n logger?: Logger;\n};\n\nconst getContextKey = (\n contextAttributes: Contexts,\n logger: NormalizedLogger,\n onError: (e: Error) => void\n): string => {\n try {\n if (Object.keys(contextAttributes).length === 0) {\n logger.warn(\n \"QuonfigProvider: You haven't passed any contextAttributes. See https://docs.quonfig.com/docs/sdks/react#using-context\"\n );\n }\n\n return encodeContexts(contextAttributes);\n } catch (e) {\n onError(e as Error);\n return \"\";\n }\n};\n\nfunction QuonfigProvider({\n sdkKey,\n contextAttributes = {},\n onError: userOnError,\n logger,\n initialFlags,\n children,\n timeout,\n apiUrl,\n apiUrls,\n domain,\n pollInterval,\n afterEvaluationCallback = undefined,\n collectEvaluationSummaries,\n}: PropsWithChildren<QuonfigProviderProps>) {\n const normalizedLogger = React.useMemo(() => normalizeLogger(logger), [logger]);\n const onError = React.useCallback(\n (e: unknown) => {\n if (userOnError) {\n userOnError(e as Error);\n } else {\n const message = e instanceof Error ? e.message : String(e);\n normalizedLogger.error(message, e);\n }\n },\n [userOnError, normalizedLogger]\n );\n const settings = {\n sdkKey,\n apiUrl,\n apiUrls,\n domain,\n timeout,\n pollInterval,\n onError,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n // We use this state to prevent a double-init when useEffect fires due to\n // StrictMode\n const mostRecentlyLoadingContextKey = React.useRef<string | undefined>(undefined);\n // We use this state to pass the loading state to the Provider (updating\n // currentLoadingContextKey won't trigger an update)\n const [loading, setLoading] = React.useState(true);\n const [initialLoad, setInitialLoad] = React.useState(true);\n // Here we track the current identity so we can reload our config when it\n // changes\n const [loadedContextKey, setLoadedContextKey] = React.useState(\"\");\n\n const quonfigClient: Quonfig = useQuonfigClient();\n\n // qfg-daxq: re-render when the underlying client's in-memory config changes\n // (poll fetch, setConfig, hydrate). Without this the singleton mutates in\n // place and React never sees the update.\n const dataVersion = React.useSyncExternalStore(\n React.useCallback((onChange) => quonfigClient.subscribe(onChange), [quonfigClient]),\n React.useCallback(() => quonfigClient.dataVersion, [quonfigClient]),\n React.useCallback(() => 0, [])\n );\n\n const contextKey = getContextKey(contextAttributes, normalizedLogger, onError);\n\n if (initialFlags && initialLoad) {\n quonfigClient.hydrate(initialFlags);\n setInitialLoad(false);\n setLoadedContextKey(contextKey);\n setLoading(false);\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (pollInterval) {\n normalizedLogger.warn(\"Polling is not supported when hydrating flags via initialFlags\");\n }\n }\n\n React.useEffect(() => {\n setInitialLoad(false);\n\n if (mostRecentlyLoadingContextKey.current === contextKey) {\n return;\n }\n\n setLoading(true);\n try {\n if (mostRecentlyLoadingContextKey.current === undefined) {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (!sdkKey) {\n throw new Error(\"QuonfigProvider: sdkKey is required\");\n }\n\n quonfigClient.clientName = \"react\";\n quonfigClient.clientVersion = reactSdkVersion;\n\n const resolvedApiUrls = apiUrls ?? (apiUrl ? [apiUrl] : undefined);\n\n const initOptions: InitOptions = {\n context: contextAttributes,\n sdkKey,\n apiUrls: resolvedApiUrls,\n domain,\n timeout,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n quonfigClient\n .init(initOptions)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n\n if (pollInterval) {\n quonfigClient.poll({ frequencyInMs: pollInterval });\n }\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n } else {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n quonfigClient\n .updateContext(contextAttributes)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n }\n } catch (e) {\n setLoading(false);\n onError(e as Error);\n }\n }, [\n sdkKey,\n loadedContextKey,\n contextKey,\n loading,\n setLoading,\n onError,\n quonfigClient.instanceHash,\n ]);\n\n // qfg-2acr: drain telemetry + stop polling/telemetry timers when the\n // provider unmounts so route swaps don't leave the singleton polling\n // forever. Mount-only deps so context-attribute changes don't tear down\n // the SDK. In React StrictMode the synthetic unmount fires too — we\n // reset the init-guard ref so the next mount cleanly re-inits.\n React.useEffect(\n () => () => {\n quonfigClient.close().catch(() => {});\n mostRecentlyLoadingContextKey.current = undefined;\n },\n [quonfigClient]\n );\n\n const value = React.useMemo(() => {\n const baseContext: ProvidedContext = {\n isEnabled: quonfigClient.isEnabled.bind(quonfigClient),\n contextAttributes,\n get: quonfigClient.get.bind(quonfigClient),\n getDuration: quonfigClient.getDuration.bind(quonfigClient),\n keys: Object.keys(quonfigClient.extract()),\n quonfig: quonfigClient,\n loading,\n settings,\n };\n\n return baseContext;\n }, [loadedContextKey, loading, quonfigClient.instanceHash, settings, dataVersion]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigProvider, QuonfigClientContext, ConfigValue, SharedSettings, QuonfigTypesafeClass };\n","import React, { PropsWithChildren } from \"react\";\nimport {\n QuonfigContext,\n QuonfigClientContext,\n useQuonfigClient,\n ProvidedContext,\n} from \"./QuonfigProvider\";\n\nexport type QuonfigTestProviderProps = {\n config: Record<string, any>;\n sdkKey?: string;\n};\n\nfunction QuonfigTestProvider({\n sdkKey,\n config,\n children,\n}: PropsWithChildren<QuonfigTestProviderProps>) {\n const get = (key: string) => config[key];\n const getDuration = (key: string) => config[key];\n const isEnabled = (key: string) => !!get(key);\n\n const quonfigClient = useQuonfigClient();\n\n const value = React.useMemo(() => {\n quonfigClient.get = get;\n quonfigClient.getDuration = getDuration;\n quonfigClient.isEnabled = isEnabled;\n\n const baseContext: ProvidedContext = {\n isEnabled,\n contextAttributes: config.contextAttributes,\n get,\n getDuration,\n loading: false,\n quonfig: quonfigClient,\n keys: Object.keys(config),\n settings: { sdkKey: sdkKey ?? \"fake-sdk-key-via-the-test-provider\" },\n };\n\n return baseContext;\n }, [config, quonfigClient, sdkKey]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigTestProvider };\n"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/sdkLogger.ts","../src/QuonfigProvider.tsx","../src/QuonfigTestProvider.tsx"],"names":["React"],"mappings":"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","file":"index.mjs","sourcesContent":["// AUTO-GENERATED from package.json by scripts/generate-version.mjs — do not edit.\nexport default \"0.0.15\";\n","/**\n * Pluggable logger interface for SDK-internal warnings and errors.\n *\n * Shape mirrors @quonfig/node so the contract is uniform across the\n * TypeScript SDKs: `warn` and `error` are required; `debug` and `info` are\n * optional and become no-ops when the supplied logger does not implement\n * them.\n */\nexport interface Logger {\n debug?(message: string, ...args: unknown[]): void;\n info?(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport interface NormalizedLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst NOOP = (): void => {};\n\nconst PREFIX = \"[quonfig]\";\n\nfunction defaultSdkLogger(): NormalizedLogger {\n return {\n /* eslint-disable no-console */\n debug: (message, ...args) => console.debug(PREFIX, message, ...args),\n info: (message, ...args) => console.info(PREFIX, message, ...args),\n warn: (message, ...args) => console.warn(PREFIX, message, ...args),\n error: (message, ...args) => console.error(PREFIX, message, ...args),\n /* eslint-enable no-console */\n };\n}\n\nexport function normalizeLogger(logger: Logger | undefined): NormalizedLogger {\n if (!logger) return defaultSdkLogger();\n return {\n debug: logger.debug ? logger.debug.bind(logger) : NOOP,\n info: logger.info ? logger.info.bind(logger) : NOOP,\n warn: logger.warn.bind(logger),\n error: logger.error.bind(logger),\n };\n}\n","import React, { PropsWithChildren } from \"react\";\nimport {\n quonfig,\n type InitOptions,\n type ConfigValue,\n type Contexts,\n Quonfig,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Duration,\n encodeContexts,\n} from \"@quonfig/javascript\";\nimport reactSdkVersion from \"./version\";\nimport { normalizeLogger, type Logger, type NormalizedLogger } from \"./sdkLogger\";\n\n// qfg-lkpm.6: per-tree owner context. The value is the active Quonfig client\n// for this provider subtree. A null value means no Provider is above us, so\n// the next mount can claim the module-level singleton; a non-null value\n// signals \"you're nested, mint a fresh client\". This replaces the previous\n// module-level `globalQuonfigIsTaken` flag, which never reset and so leaked\n// state across test runs and (in principle) across SSR render trees.\nconst QuonfigClientContext = React.createContext<Quonfig | null>(null);\n\n// @quonfig/cli#generate will create interfaces into this namespace for React to consume\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface FrontEndConfigurationAccessor {}\n\nexport type TypedFrontEndConfigurationAccessor = keyof FrontEndConfigurationAccessor extends never\n ? Record<string, unknown>\n : {\n [TypedFlagKey in keyof FrontEndConfigurationAccessor]: FrontEndConfigurationAccessor[TypedFlagKey];\n };\n\ntype ClassMethods<T> = { [K in keyof T]: T[K] };\n\ntype QuonfigTypesafeClass<T = unknown> = new (\n // eslint-disable-next-line no-shadow\n quonfig: Quonfig\n) => T;\n\ntype SharedSettings = Partial<\n Pick<InitOptions, \"sdkKey\" | \"apiUrls\" | \"domain\" | \"timeout\" | \"collectEvaluationSummaries\">\n> & {\n // Convenience alias for a single API URL — normalized to apiUrls=[apiUrl]\n // before being passed to the underlying SDK, which only accepts apiUrls.\n apiUrl?: string;\n // We need to redefine the afterEvaluationCallback type to ensure proper dynamic resolution of K\n afterEvaluationCallback?: <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n contexts: Contexts | undefined\n ) => void;\n pollInterval?: number;\n onError?: (error: Error) => void;\n};\n\nexport type BaseContext = {\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n getDuration: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => Duration | undefined;\n contextAttributes: Contexts;\n isEnabled: <\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(\n key: K\n ) => boolean;\n loading: boolean;\n quonfig: typeof quonfig;\n keys: (keyof TypedFrontEndConfigurationRaw)[];\n settings: SharedSettings;\n};\n\nexport type ProvidedContext = BaseContext & ClassMethods<QuonfigTypesafeClass>;\n\nexport const defaultContext: BaseContext = {\n get: (_key) => undefined,\n getDuration: (_key) => undefined,\n isEnabled: (_key) => false,\n keys: [],\n loading: true,\n contextAttributes: {},\n quonfig,\n settings: {},\n};\n\nexport const QuonfigContext = React.createContext<ProvidedContext>(\n defaultContext as ProvidedContext\n);\n\n// This is a factory function that creates a fully typed useQuonfig hook for a specific QuonfigTypesafe class\nexport function createQuonfigHook<T>(TypesafeClass: QuonfigTypesafeClass<T>) {\n return function useQuonfigHook(): BaseContext & T {\n const baseContext = React.useContext(QuonfigContext);\n\n // Memoize the typesafe instance to prevent unnecessary constructor calls\n const typesafeInstance = React.useMemo(() => {\n const instance = new TypesafeClass(baseContext.quonfig);\n\n // Copy baseContext properties to typesafeInstance except for `get` + `quonfig`\n Object.assign(instance as any, {\n getDuration: baseContext.getDuration,\n contextAttributes: baseContext.contextAttributes,\n isEnabled: baseContext.isEnabled,\n loading: baseContext.loading,\n keys: baseContext.keys,\n settings: baseContext.settings,\n });\n\n return instance;\n }, [baseContext]);\n\n return typesafeInstance as BaseContext & T;\n };\n}\n\n// Basic hook for general use - requires type parameter\nexport const useBaseQuonfig = () => React.useContext(QuonfigContext);\n\n// General hook that returns the context with any explicit type\nexport const useQuonfig = (): ProvidedContext => useBaseQuonfig() as unknown as ProvidedContext;\n\n// qfg-lkpm.6: per-key selector hook. Subscribes via the underlying client's\n// notify list rather than React context, so a flag mutation only re-renders\n// components whose selected key actually changed. `useQuonfig()` re-renders\n// on every dataVersion bump because the context value identity changes; this\n// hook bypasses that.\nexport function useFlag<K extends keyof TypedFrontEndConfigurationRaw>(\n key: K\n): TypedFrontEndConfigurationRaw[K];\nexport function useFlag(key: string): ConfigValue;\nexport function useFlag(key: string): ConfigValue {\n const client = React.useContext(QuonfigClientContext) ?? quonfig;\n const subscribe = React.useCallback(\n (onChange: () => void) => client.subscribe(onChange),\n [client]\n );\n const getSnapshot = React.useCallback(() => client.get(key), [client, key]);\n const getServerSnapshot = React.useCallback((): ConfigValue => undefined, []);\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n// qfg-lkpm.6: replacement for the old module-level `globalQuonfigIsTaken`\n// flag. A provider asks \"is there already a Quonfig client above me in the\n// React tree?\". If yes, mint a fresh client (multi-tenant nesting); if no,\n// claim the module singleton so non-React code that imports `quonfig`\n// directly sees the same instance.\nexport const useQuonfigClient = (): Quonfig => {\n const parentClient = React.useContext(QuonfigClientContext);\n // Mount-only: parent context is fixed for the lifetime of this provider.\n const parentClientRef = React.useRef(parentClient);\n return React.useMemo(() => (parentClientRef.current ? new Quonfig() : quonfig), []);\n};\n\nexport type QuonfigProviderProps = SharedSettings & {\n sdkKey: string;\n contextAttributes?: Contexts;\n initialFlags?: Record<string, unknown>;\n logger?: Logger;\n};\n\nconst getContextKey = (\n contextAttributes: Contexts,\n logger: NormalizedLogger,\n onError: (e: Error) => void\n): string => {\n try {\n if (Object.keys(contextAttributes).length === 0) {\n logger.warn(\n \"QuonfigProvider: You haven't passed any contextAttributes. See https://docs.quonfig.com/docs/sdks/react#using-context\"\n );\n }\n\n return encodeContexts(contextAttributes);\n } catch (e) {\n onError(e as Error);\n return \"\";\n }\n};\n\nfunction QuonfigProvider({\n sdkKey,\n contextAttributes = {},\n onError: userOnError,\n logger,\n initialFlags,\n children,\n timeout,\n apiUrl,\n apiUrls,\n domain,\n pollInterval,\n afterEvaluationCallback = undefined,\n collectEvaluationSummaries,\n}: PropsWithChildren<QuonfigProviderProps>) {\n const normalizedLogger = React.useMemo(() => normalizeLogger(logger), [logger]);\n const onError = React.useCallback(\n (e: unknown) => {\n if (userOnError) {\n userOnError(e as Error);\n } else {\n const message = e instanceof Error ? e.message : String(e);\n normalizedLogger.error(message, e);\n }\n },\n [userOnError, normalizedLogger]\n );\n const settings = {\n sdkKey,\n apiUrl,\n apiUrls,\n domain,\n timeout,\n pollInterval,\n onError,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n // We use this state to prevent a double-init when useEffect fires due to\n // StrictMode\n const mostRecentlyLoadingContextKey = React.useRef<string | undefined>(undefined);\n // We use this state to pass the loading state to the Provider (updating\n // currentLoadingContextKey won't trigger an update)\n const [loading, setLoading] = React.useState(true);\n const [initialLoad, setInitialLoad] = React.useState(true);\n // Here we track the current identity so we can reload our config when it\n // changes\n const [loadedContextKey, setLoadedContextKey] = React.useState(\"\");\n\n const quonfigClient: Quonfig = useQuonfigClient();\n\n // qfg-daxq: re-render when the underlying client's in-memory config changes\n // (poll fetch, setConfig, hydrate). Without this the singleton mutates in\n // place and React never sees the update.\n const dataVersion = React.useSyncExternalStore(\n React.useCallback((onChange) => quonfigClient.subscribe(onChange), [quonfigClient]),\n React.useCallback(() => quonfigClient.dataVersion, [quonfigClient]),\n React.useCallback(() => 0, [])\n );\n\n const contextKey = getContextKey(contextAttributes, normalizedLogger, onError);\n\n if (initialFlags && initialLoad) {\n quonfigClient.hydrate(initialFlags);\n setInitialLoad(false);\n setLoadedContextKey(contextKey);\n setLoading(false);\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (pollInterval) {\n normalizedLogger.warn(\"Polling is not supported when hydrating flags via initialFlags\");\n }\n }\n\n React.useEffect(() => {\n setInitialLoad(false);\n\n if (mostRecentlyLoadingContextKey.current === contextKey) {\n return;\n }\n\n setLoading(true);\n try {\n if (mostRecentlyLoadingContextKey.current === undefined) {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n if (!sdkKey) {\n throw new Error(\"QuonfigProvider: sdkKey is required\");\n }\n\n quonfigClient.clientName = \"react\";\n quonfigClient.clientVersion = reactSdkVersion;\n\n const resolvedApiUrls = apiUrls ?? (apiUrl ? [apiUrl] : undefined);\n\n const initOptions: InitOptions = {\n context: contextAttributes,\n sdkKey,\n apiUrls: resolvedApiUrls,\n domain,\n timeout,\n afterEvaluationCallback,\n collectEvaluationSummaries,\n };\n\n quonfigClient\n .init(initOptions)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n\n if (pollInterval) {\n // poll()'s first fetch can reject on a startup network blip, but\n // the polling loop is still scheduled and self-heals on the next\n // tick (qfg-8uw5). Attach a catch so that expected first-fetch\n // rejection is a non-fatal warning, not an unhandled rejection —\n // and don't route it through onError, which would surface a\n // user-facing error for a transient blip that recovers on its own.\n quonfigClient.poll({ frequencyInMs: pollInterval }).catch((err) => {\n normalizedLogger.warn(\"Initial poll fetch failed; polling will retry\", err);\n });\n }\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n } else {\n mostRecentlyLoadingContextKey.current = contextKey;\n\n quonfigClient\n .updateContext(contextAttributes)\n .then(() => {\n setLoadedContextKey(contextKey);\n setLoading(false);\n })\n .catch((reason: any) => {\n setLoading(false);\n onError(reason);\n });\n }\n } catch (e) {\n setLoading(false);\n onError(e as Error);\n }\n }, [\n sdkKey,\n loadedContextKey,\n contextKey,\n loading,\n setLoading,\n onError,\n quonfigClient.instanceHash,\n ]);\n\n // qfg-2acr: drain telemetry + stop polling/telemetry timers when the\n // provider unmounts so route swaps don't leave the singleton polling\n // forever. Mount-only deps so context-attribute changes don't tear down\n // the SDK. In React StrictMode the synthetic unmount fires too — we\n // reset the init-guard ref so the next mount cleanly re-inits.\n React.useEffect(\n () => () => {\n quonfigClient.close().catch(() => {});\n mostRecentlyLoadingContextKey.current = undefined;\n },\n [quonfigClient]\n );\n\n const value = React.useMemo(() => {\n const baseContext: ProvidedContext = {\n isEnabled: quonfigClient.isEnabled.bind(quonfigClient),\n contextAttributes,\n get: quonfigClient.get.bind(quonfigClient),\n getDuration: quonfigClient.getDuration.bind(quonfigClient),\n keys: Object.keys(quonfigClient.extract()),\n quonfig: quonfigClient,\n loading,\n settings,\n };\n\n return baseContext;\n }, [loadedContextKey, loading, quonfigClient.instanceHash, settings, dataVersion]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigProvider, QuonfigClientContext, ConfigValue, SharedSettings, QuonfigTypesafeClass };\n","import React, { PropsWithChildren } from \"react\";\nimport {\n QuonfigContext,\n QuonfigClientContext,\n useQuonfigClient,\n ProvidedContext,\n} from \"./QuonfigProvider\";\n\nexport type QuonfigTestProviderProps = {\n config: Record<string, any>;\n sdkKey?: string;\n};\n\nfunction QuonfigTestProvider({\n sdkKey,\n config,\n children,\n}: PropsWithChildren<QuonfigTestProviderProps>) {\n const get = (key: string) => config[key];\n const getDuration = (key: string) => config[key];\n const isEnabled = (key: string) => !!get(key);\n\n const quonfigClient = useQuonfigClient();\n\n const value = React.useMemo(() => {\n quonfigClient.get = get;\n quonfigClient.getDuration = getDuration;\n quonfigClient.isEnabled = isEnabled;\n\n const baseContext: ProvidedContext = {\n isEnabled,\n contextAttributes: config.contextAttributes,\n get,\n getDuration,\n loading: false,\n quonfig: quonfigClient,\n keys: Object.keys(config),\n settings: { sdkKey: sdkKey ?? \"fake-sdk-key-via-the-test-provider\" },\n };\n\n return baseContext;\n }, [config, quonfigClient, sdkKey]);\n\n return (\n <QuonfigClientContext.Provider value={quonfigClient}>\n <QuonfigContext.Provider value={value}>{children}</QuonfigContext.Provider>\n </QuonfigClientContext.Provider>\n );\n}\n\nexport { QuonfigTestProvider };\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageManager": "yarn@4.11.0",
3
3
  "name": "@quonfig/react",
4
- "version": "0.0.14",
4
+ "version": "1.0.0",
5
5
  "description": "Feature Flags & Dynamic Configuration as a Service",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -62,7 +62,7 @@
62
62
  "config"
63
63
  ],
64
64
  "devDependencies": {
65
- "@quonfig/javascript": ">=0.0.14",
65
+ "@quonfig/javascript": ">=1.0.0",
66
66
  "@size-limit/preset-small-lib": "^11.1.6",
67
67
  "@testing-library/jest-dom": "^5.16.5",
68
68
  "@testing-library/react": "^13.3.0",
@@ -93,7 +93,7 @@
93
93
  "typescript": "^4.7.4"
94
94
  },
95
95
  "peerDependencies": {
96
- "@quonfig/javascript": ">=0.0.14",
96
+ "@quonfig/javascript": ">=1.0.0",
97
97
  "react": "^18 || ^19"
98
98
  }
99
99
  }