@quonfig/react 0.0.3
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 +242 -0
- package/LICENSE +7 -0
- package/README.md +146 -0
- package/dist/index.cjs +305 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.mjs +293 -0
- package/dist/index.mjs.map +1 -0
- package/dist/quonfig-react.bundle.js +15 -0
- package/package.json +79 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
Changelog
|
|
2
|
+
|
|
3
|
+
## 0.0.2 - 2025-10-12
|
|
4
|
+
|
|
5
|
+
- Support re-hydration of flags via QuonfigProvider
|
|
6
|
+
|
|
7
|
+
## 0.0.1 - 2025-10-01
|
|
8
|
+
|
|
9
|
+
- Official patch release
|
|
10
|
+
|
|
11
|
+
## 0.0.0-pre.12 - 2025-10-01
|
|
12
|
+
|
|
13
|
+
- fix: reference Contexts as a type, not a runtime value
|
|
14
|
+
|
|
15
|
+
## 0.0.0-pre.11 - 2025-09-30
|
|
16
|
+
|
|
17
|
+
- feat: use type gen / types from sdk-javscript
|
|
18
|
+
|
|
19
|
+
## 0.0.0-pre.10 - 2025-09-29
|
|
20
|
+
|
|
21
|
+
- chore: remove old typesafe implementation + tighten typesafe class interface requirements
|
|
22
|
+
|
|
23
|
+
## 0.0.0-pre.9 - 2025-09-26
|
|
24
|
+
|
|
25
|
+
- fix: Hook up `createQuonfigHook` to actually use the typesafe class instance and provide access to
|
|
26
|
+
it's getter methods
|
|
27
|
+
|
|
28
|
+
## 0.0.0-pre.8 - 2025-09-24
|
|
29
|
+
|
|
30
|
+
- feat: Upgrade sdk-javascript dependency to use new quonfig.com endpoints
|
|
31
|
+
|
|
32
|
+
## 0.0.0-pre.6 - 2025-09-23
|
|
33
|
+
|
|
34
|
+
- feat: Properly type other key inputs to the reforge hooks
|
|
35
|
+
|
|
36
|
+
## 0.0.0-pre.5 - 2025-09-05
|
|
37
|
+
|
|
38
|
+
- feat: Stop using private javascript sdk apis
|
|
39
|
+
|
|
40
|
+
## 0.0.0-pre.4 - 2025-09-05
|
|
41
|
+
|
|
42
|
+
- chore: Pin to pre-release of javascript sdk for now
|
|
43
|
+
|
|
44
|
+
## 0.0.0-pre.3 - 2025-09-05
|
|
45
|
+
|
|
46
|
+
- fix: javascript sdk dependency definition
|
|
47
|
+
|
|
48
|
+
## 0.0.0-pre.2 - 2025-09-05
|
|
49
|
+
|
|
50
|
+
- fix: Resolve issues with TypeScript module merging of types
|
|
51
|
+
|
|
52
|
+
## 0.0.0-pre.1 - 2025-08-20
|
|
53
|
+
|
|
54
|
+
- feat: Simplify type definitions and expose as overridable interfaces
|
|
55
|
+
|
|
56
|
+
## 0.0.0-pre.0 - 2025-08-04
|
|
57
|
+
|
|
58
|
+
- chore: Quonfig rebrand
|
|
59
|
+
|
|
60
|
+
# @prefab-cloud/prefab-cloud-react
|
|
61
|
+
|
|
62
|
+
All releases below were released as part of the
|
|
63
|
+
[@prefab-cloud/prefab-cloud-react](https://github.com/prefab-cloud/prefab-cloud-react) package.
|
|
64
|
+
|
|
65
|
+
## @prefab-cloud/prefab-cloud-react 0.4.6 - 2025-05-22
|
|
66
|
+
|
|
67
|
+
- Extra error handling for loader and telemetry uploader
|
|
68
|
+
|
|
69
|
+
## @prefab-cloud/prefab-cloud-react 0.4.5 - 2025-04-10
|
|
70
|
+
|
|
71
|
+
- Silently handle Telemetry AbortErrors
|
|
72
|
+
|
|
73
|
+
## @prefab-cloud/prefab-cloud-react 0.4.4 - 2025-03-12
|
|
74
|
+
|
|
75
|
+
- Use tsup for better ESM/CJS compatibility
|
|
76
|
+
|
|
77
|
+
## @prefab-cloud/prefab-cloud-react 0.4.2 - 2025-03-11
|
|
78
|
+
|
|
79
|
+
- Add ESM support (#59)
|
|
80
|
+
|
|
81
|
+
## @prefab-cloud/prefab-cloud-react 0.4.1 - 2024-09-12
|
|
82
|
+
|
|
83
|
+
- Update Reforge JS client to 0.4.2 (for bootstrapping)
|
|
84
|
+
|
|
85
|
+
## @prefab-cloud/prefab-cloud-react 0.4.0 - 2024-08-21
|
|
86
|
+
|
|
87
|
+
- Update Reforge JS client to 0.4.0 / global delivery
|
|
88
|
+
|
|
89
|
+
## @prefab-cloud/prefab-cloud-react 0.3.7 - 2024-08-20
|
|
90
|
+
|
|
91
|
+
- More robust error handling (#56)
|
|
92
|
+
|
|
93
|
+
## @prefab-cloud/prefab-cloud-react 0.3.6 - 2024-07-18
|
|
94
|
+
|
|
95
|
+
- Fixes error when uploading eval telemetry for stringList values
|
|
96
|
+
|
|
97
|
+
## @prefab-cloud/prefab-cloud-react 0.3.5 - 2024-07-17
|
|
98
|
+
|
|
99
|
+
- Reduces volume of internal logging done by telemetry uploader
|
|
100
|
+
|
|
101
|
+
## @prefab-cloud/prefab-cloud-react 0.3.4 - 2024-07-16
|
|
102
|
+
|
|
103
|
+
- Adds validation console errors for Context object
|
|
104
|
+
|
|
105
|
+
## @prefab-cloud/prefab-cloud-react 0.3.3 - 2024-7-10
|
|
106
|
+
|
|
107
|
+
- Adds collectContextMode option to control context telemetry
|
|
108
|
+
- Tries to flush telemetry when browser window closes
|
|
109
|
+
- Improves prefix for internal logger names
|
|
110
|
+
|
|
111
|
+
## @prefab-cloud/prefab-cloud-react 0.3.2 - 2024-06-20
|
|
112
|
+
|
|
113
|
+
- Allow nesting a QuonfigProvider in a ReforgeTestProvider (#48)
|
|
114
|
+
|
|
115
|
+
## @prefab-cloud/prefab-cloud-react 0.3.1 - 2024-06-13
|
|
116
|
+
|
|
117
|
+
- Support for nested QuonfigProviders
|
|
118
|
+
|
|
119
|
+
## @prefab-cloud/prefab-cloud-react 0.3.0 - 2024-06-04
|
|
120
|
+
|
|
121
|
+
- collectEvaluationSummaries is now opt-out (#42)
|
|
122
|
+
|
|
123
|
+
## @prefab-cloud/prefab-cloud-react 0.2.7 - 2024-05-31
|
|
124
|
+
|
|
125
|
+
- Support durations
|
|
126
|
+
|
|
127
|
+
## @prefab-cloud/prefab-cloud-react 0.2.6 - 2024-05-10
|
|
128
|
+
|
|
129
|
+
- Export types for ConfigValue and ContextAttributes
|
|
130
|
+
|
|
131
|
+
## @prefab-cloud/prefab-cloud-react 0.2.5 - 2024-05-07
|
|
132
|
+
|
|
133
|
+
- Remove `react-dom` from peerDependencies
|
|
134
|
+
|
|
135
|
+
## @prefab-cloud/prefab-cloud-react 0.2.4 - 2024-05-03
|
|
136
|
+
|
|
137
|
+
- Support for JSON config values
|
|
138
|
+
|
|
139
|
+
## @prefab-cloud/prefab-cloud-react 0.2.3 - 2024-04-12
|
|
140
|
+
|
|
141
|
+
- Expose known keys (#36)
|
|
142
|
+
|
|
143
|
+
## @prefab-cloud/prefab-cloud-react 0.2.2 - 2024-01-17
|
|
144
|
+
|
|
145
|
+
- Updates to errors and warnings
|
|
146
|
+
|
|
147
|
+
## @prefab-cloud/prefab-cloud-react 0.2.1 - 2024-01-11
|
|
148
|
+
|
|
149
|
+
- Fix default endpoint for telemetry
|
|
150
|
+
|
|
151
|
+
## @prefab-cloud/prefab-cloud-react 0.2.0 - 2023-12-12
|
|
152
|
+
|
|
153
|
+
- Remove identity support. Use Context instead. (#30)
|
|
154
|
+
- Re-fetch when context attributes change. (#31)
|
|
155
|
+
|
|
156
|
+
## @prefab-cloud/prefab-cloud-react 0.1.21 - 2023-12-11
|
|
157
|
+
|
|
158
|
+
- Use correct client version string
|
|
159
|
+
|
|
160
|
+
## @prefab-cloud/prefab-cloud-react 0.1.20 - 2023-10-31
|
|
161
|
+
|
|
162
|
+
- Opt-in param for logger telemetry
|
|
163
|
+
|
|
164
|
+
## @prefab-cloud/prefab-cloud-react 0.1.19 - 2023-10-24
|
|
165
|
+
|
|
166
|
+
- Start reporting evaluation telemetry when keys are actually used
|
|
167
|
+
|
|
168
|
+
## @prefab-cloud/prefab-cloud-react 0.1.18 - 2023-10-13
|
|
169
|
+
|
|
170
|
+
- Warn instead of erroring when no context is provided
|
|
171
|
+
|
|
172
|
+
## @prefab-cloud/prefab-cloud-react 0.1.17 - 2023-09-20
|
|
173
|
+
|
|
174
|
+
- Add support for a `afterEvaluationCallback` callback for forwarding evaluation events to analytics
|
|
175
|
+
tools, etc.
|
|
176
|
+
|
|
177
|
+
## @prefab-cloud/prefab-cloud-react 0.1.16 - 2023-08-10
|
|
178
|
+
|
|
179
|
+
- Fix race condition (#21)
|
|
180
|
+
|
|
181
|
+
## @prefab-cloud/prefab-cloud-react 0.1.15 - 2023-07-11
|
|
182
|
+
|
|
183
|
+
- Update javascript package dependency to v0.1.14
|
|
184
|
+
|
|
185
|
+
## @prefab-cloud/prefab-cloud-react 0.1.14 - 2023-07-11
|
|
186
|
+
|
|
187
|
+
- Update javascript package dependency to v0.1.13
|
|
188
|
+
|
|
189
|
+
## @prefab-cloud/prefab-cloud-react 0.1.13 - 2023-07-10
|
|
190
|
+
|
|
191
|
+
- Update javascript package dependency to v0.1.12
|
|
192
|
+
|
|
193
|
+
## @prefab-cloud/prefab-cloud-react 0.1.12 - 2023-07-10
|
|
194
|
+
|
|
195
|
+
- Update eslint and resolve all existing errors/warnings
|
|
196
|
+
- Add and configure prettier
|
|
197
|
+
- Add support for passing a pollInterval to the `QuonfigProvider`
|
|
198
|
+
|
|
199
|
+
## @prefab-cloud/prefab-cloud-react [0.1.11] - 2023-07-06
|
|
200
|
+
|
|
201
|
+
- Update javascript package dependency to v0.1.11
|
|
202
|
+
|
|
203
|
+
## @prefab-cloud/prefab-cloud-react [0.1.10] - 2023-06-27
|
|
204
|
+
|
|
205
|
+
- Update javascript package dependency to v0.1.10
|
|
206
|
+
|
|
207
|
+
## @prefab-cloud/prefab-cloud-react [0.1.9] - 2023-06-27
|
|
208
|
+
|
|
209
|
+
- Update javascript package dependency to v0.1.9
|
|
210
|
+
|
|
211
|
+
## @prefab-cloud/prefab-cloud-react [0.1.8] - 2023-06-27
|
|
212
|
+
|
|
213
|
+
- Initial CHANGELOG (with backdated content)
|
|
214
|
+
- Formatting cleanup
|
|
215
|
+
|
|
216
|
+
## @prefab-cloud/prefab-cloud-react [0.1.7] - 2023-05-01
|
|
217
|
+
|
|
218
|
+
- Add Context and deprecate `identityAttributes` (#4)
|
|
219
|
+
|
|
220
|
+
## @prefab-cloud/prefab-cloud-react [0.1.6] - 2023-04-04
|
|
221
|
+
|
|
222
|
+
- Fix emitted types (#2)
|
|
223
|
+
|
|
224
|
+
## @prefab-cloud/prefab-cloud-react [0.1.5] - 2023-03-16
|
|
225
|
+
|
|
226
|
+
- Allow passing endpoints
|
|
227
|
+
|
|
228
|
+
## @prefab-cloud/prefab-cloud-react [0.1.4] - 2023-03-16
|
|
229
|
+
|
|
230
|
+
- Update dependencies and use named exports
|
|
231
|
+
|
|
232
|
+
## @prefab-cloud/prefab-cloud-react [0.1.3] - 2022-09-29
|
|
233
|
+
|
|
234
|
+
- Bump javascript package dependency to 0.1.3
|
|
235
|
+
|
|
236
|
+
## @prefab-cloud/prefab-cloud-react [0.1.2] - 2022-08-18
|
|
237
|
+
|
|
238
|
+
- Bump javascript package dependency to 0.1.2
|
|
239
|
+
|
|
240
|
+
## @prefab-cloud/prefab-cloud-react [0.0.1] - 2022-08-15
|
|
241
|
+
|
|
242
|
+
- Initial release
|
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright 2025 Reforge
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @quonfig/react
|
|
2
|
+
|
|
3
|
+
A React provider and hook for [Quonfig](https://quonfig.com)
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
`npm install @quonfig/react` or `yarn add @quonfig/react`
|
|
8
|
+
|
|
9
|
+
TypeScript types are included with the package.
|
|
10
|
+
|
|
11
|
+
## Usage in your app
|
|
12
|
+
|
|
13
|
+
### Configure the Provider
|
|
14
|
+
|
|
15
|
+
Wrap your component tree in the `QuonfigProvider`, e.g.
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
import { QuonfigProvider } from "@quonfig/react";
|
|
19
|
+
|
|
20
|
+
const WrappedApp = () => {
|
|
21
|
+
const context = {
|
|
22
|
+
user: { email: "jeffrey@example.com" },
|
|
23
|
+
subscription: { plan: "advanced" },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const onError = (error) => {
|
|
27
|
+
console.error(error);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<QuonfigProvider sdkKey={"YOUR_SDK_KEY"} contextAttributes={context} onError={onError}>
|
|
32
|
+
<App />
|
|
33
|
+
</QuonfigProvider>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Here's an explanation of each provider prop:
|
|
39
|
+
|
|
40
|
+
| property | required | type | purpose |
|
|
41
|
+
| ------------------- | -------- | ----------------- | ------------------------------------------------------------------------------ |
|
|
42
|
+
| `sdkKey` | yes | `string` | your Quonfig SDK key |
|
|
43
|
+
| `onError` | no | `(error) => void` | callback invoked if quonfig fails to initialize |
|
|
44
|
+
| `contextAttributes` | no | `Contexts` | this is the context attributes object you passed when setting up the provider |
|
|
45
|
+
| `timeout` | no | `number` | initialization timeout (defaults to 10 seconds) |
|
|
46
|
+
| `pollInterval` | no | `number` | configures quonfig to poll for updates every `pollInterval` ms. |
|
|
47
|
+
|
|
48
|
+
### Usage in Your Components
|
|
49
|
+
|
|
50
|
+
Use the `useQuonfig` hook to fetch flags and config values:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const Logo = () => {
|
|
54
|
+
const { isEnabled } = useQuonfig();
|
|
55
|
+
|
|
56
|
+
if (isEnabled("new-logo")) {
|
|
57
|
+
return <img src={newLogo} className="App-logo" alt="logo" />;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return <img src={logo} className="App-logo" alt="logo" />;
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`useQuonfig` exposes the following:
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
const { isEnabled, get, loading, contextAttributes } = useQuonfig();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Here's an explanation of each property:
|
|
71
|
+
|
|
72
|
+
| property | example | purpose |
|
|
73
|
+
| ------------------- | ----------------------- | ---------------------------------------------------------------------------------------- |
|
|
74
|
+
| `isEnabled` | `isEnabled("new-logo")` | returns a boolean (default `false`) if a feature is enabled based on the current context |
|
|
75
|
+
| `get` | `get('retry-count')` | returns the value of a flag or config |
|
|
76
|
+
| `loading` | `if (loading) { ... }` | a boolean indicating whether quonfig content is being loaded |
|
|
77
|
+
| `contextAttributes` | N/A | this is the context attributes object you passed when setting up the provider |
|
|
78
|
+
| `quonfig` | N/A | the underlying JavaScript quonfig instance |
|
|
79
|
+
| `keys` | N/A | an array of all the flag and config names in the current configuration |
|
|
80
|
+
|
|
81
|
+
## Usage in your test suite
|
|
82
|
+
|
|
83
|
+
Wrap the component under test in a `QuonfigTestProvider` and provide a config object to set up your
|
|
84
|
+
test state.
|
|
85
|
+
|
|
86
|
+
e.g. if you wanted to test the following trivial component
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
function MyComponent() {
|
|
90
|
+
const { get, isEnabled, loading } = useQuonfig();
|
|
91
|
+
const greeting = get("greeting") || "Greetings";
|
|
92
|
+
|
|
93
|
+
if (loading) {
|
|
94
|
+
return <div>Loading...</div>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div>
|
|
99
|
+
<h1 role="alert">{greeting}</h1>
|
|
100
|
+
{isEnabled("secretFeature") && (
|
|
101
|
+
<button type="submit" title="secret-feature">
|
|
102
|
+
Secret feature
|
|
103
|
+
</button>
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
You could do the following in [jest]/[rtl]
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
import { QuonfigTestProvider } from '@quonfig/react';
|
|
114
|
+
|
|
115
|
+
const renderInTestProvider = (config: {[key: string]: any}) => {
|
|
116
|
+
render(
|
|
117
|
+
<QuonfigTestProvider config={config}>
|
|
118
|
+
<MyComponent />
|
|
119
|
+
</QuonfigTestProvider>,
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
it('shows a custom greeting', async () => {
|
|
124
|
+
renderInTestProvider({ greeting: 'Hello' });
|
|
125
|
+
|
|
126
|
+
const alert = screen.queryByRole('alert');
|
|
127
|
+
expect(alert).toHaveTextContent('Hello');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('shows the secret feature when it is enabled', async () => {
|
|
131
|
+
renderInTestProvider({ secretFeature: true });
|
|
132
|
+
|
|
133
|
+
const secretFeature = screen.queryByTitle('secret-feature');
|
|
134
|
+
expect(secretFeature).toBeInTheDocument();
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
Contributions are what make the open source community such an amazing place to learn, inspire, and
|
|
141
|
+
create. Any contributions you make are **greatly appreciated**. For detailed contributing
|
|
142
|
+
guidelines, please see [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
143
|
+
|
|
144
|
+
[jest]: https://jestjs.io/
|
|
145
|
+
[rtl]: https://testing-library.com/docs/react-testing-library/intro/
|
|
146
|
+
[Quonfig]: https://quonfig.com
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var javascript = require('@quonfig/javascript');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
9
|
+
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
12
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// package.json
|
|
16
|
+
var require_package = __commonJS({
|
|
17
|
+
"package.json"(exports, module) {
|
|
18
|
+
module.exports = {
|
|
19
|
+
packageManager: "yarn@4.11.0",
|
|
20
|
+
name: "@quonfig/react",
|
|
21
|
+
version: "0.0.3",
|
|
22
|
+
description: "Feature Flags & Dynamic Configuration as a Service",
|
|
23
|
+
main: "dist/index.cjs",
|
|
24
|
+
module: "dist/index.mjs",
|
|
25
|
+
types: "dist/index.d.ts",
|
|
26
|
+
repository: {
|
|
27
|
+
type: "git",
|
|
28
|
+
url: "https://github.com/quonfig/sdk-react.git"
|
|
29
|
+
},
|
|
30
|
+
bugs: {
|
|
31
|
+
url: "https://github.com/quonfig/sdk-react/issues"
|
|
32
|
+
},
|
|
33
|
+
homepage: "https://github.com/quonfig/sdk-react#readme",
|
|
34
|
+
exports: {
|
|
35
|
+
".": {
|
|
36
|
+
types: "./dist/index.d.ts",
|
|
37
|
+
import: "./dist/index.mjs",
|
|
38
|
+
require: "./dist/index.cjs",
|
|
39
|
+
default: "./dist/index.cjs"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
files: [
|
|
43
|
+
"dist/",
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"CHANGELOG.md"
|
|
47
|
+
],
|
|
48
|
+
scripts: {
|
|
49
|
+
build: "rm -rf dist/ && tsup",
|
|
50
|
+
dev: "tsup --watch",
|
|
51
|
+
bundle: "esbuild --minify --target=esnext --bundle --outfile=dist/quonfig-react.bundle.js --global-name=window.quonfigReactNamespace dist/index.cjs && echo 'window.quonfigReact = window.quonfigReactNamespace.quonfigReact' >> dist/quonfig-react.bundle.js",
|
|
52
|
+
test: "tsup && jest --verbose",
|
|
53
|
+
lint: "eslint --ext .ts,.tsx src/",
|
|
54
|
+
prettier: "prettier . -l",
|
|
55
|
+
"prettier:fix": "prettier --write ."
|
|
56
|
+
},
|
|
57
|
+
author: "Jeffrey Chupp",
|
|
58
|
+
license: "ISC",
|
|
59
|
+
keywords: [
|
|
60
|
+
"feature-flags",
|
|
61
|
+
"config"
|
|
62
|
+
],
|
|
63
|
+
devDependencies: {
|
|
64
|
+
"@quonfig/javascript": "file:../sdk-javascript",
|
|
65
|
+
"@testing-library/jest-dom": "^5.16.5",
|
|
66
|
+
"@testing-library/react": "^13.3.0",
|
|
67
|
+
"@types/jest": "^28.1.6",
|
|
68
|
+
"@types/node": "^18.6.5",
|
|
69
|
+
"@types/react": "^19.1.10",
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
|
71
|
+
"@typescript-eslint/parser": "^5.33.0",
|
|
72
|
+
eslint: "^8.21.0",
|
|
73
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
74
|
+
"eslint-config-airbnb-typescript": "^17.0.0",
|
|
75
|
+
"eslint-config-prettier": "^8.8.0",
|
|
76
|
+
"eslint-plugin-import": "^2.26.0",
|
|
77
|
+
"eslint-plugin-jest": "^26.8.2",
|
|
78
|
+
"eslint-plugin-jsx-a11y": "^6.6.1",
|
|
79
|
+
"eslint-plugin-react": "^7.30.1",
|
|
80
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
81
|
+
jest: "^28.1.3",
|
|
82
|
+
"jest-environment-jsdom": "^28.1.3",
|
|
83
|
+
"jest-fetch-mock": "^3.0.3",
|
|
84
|
+
prettier: "^3.0.0",
|
|
85
|
+
react: "^19.1.1",
|
|
86
|
+
"react-dom": "^19.1.1",
|
|
87
|
+
"ts-jest": "^28.0.7",
|
|
88
|
+
"ts-node": "^10.9.1",
|
|
89
|
+
tsup: "^8.4.0",
|
|
90
|
+
typescript: "^4.7.4"
|
|
91
|
+
},
|
|
92
|
+
peerDependencies: {
|
|
93
|
+
"@quonfig/javascript": ">=0.0.2",
|
|
94
|
+
react: "^16 || ^17 || ^18 || ^19"
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
var { version } = require_package();
|
|
100
|
+
var defaultContext = {
|
|
101
|
+
get: (_key) => void 0,
|
|
102
|
+
getDuration: (_key) => void 0,
|
|
103
|
+
isEnabled: (_key) => false,
|
|
104
|
+
keys: [],
|
|
105
|
+
loading: true,
|
|
106
|
+
contextAttributes: {},
|
|
107
|
+
quonfig: javascript.quonfig,
|
|
108
|
+
settings: {}
|
|
109
|
+
};
|
|
110
|
+
var QuonfigContext = React__default.default.createContext(
|
|
111
|
+
defaultContext
|
|
112
|
+
);
|
|
113
|
+
function createQuonfigHook(TypesafeClass) {
|
|
114
|
+
return function useQuonfigHook() {
|
|
115
|
+
const baseContext = React__default.default.useContext(QuonfigContext);
|
|
116
|
+
const typesafeInstance = React__default.default.useMemo(() => {
|
|
117
|
+
const instance = new TypesafeClass(baseContext.quonfig);
|
|
118
|
+
Object.assign(instance, {
|
|
119
|
+
getDuration: baseContext.getDuration,
|
|
120
|
+
contextAttributes: baseContext.contextAttributes,
|
|
121
|
+
isEnabled: baseContext.isEnabled,
|
|
122
|
+
loading: baseContext.loading,
|
|
123
|
+
keys: baseContext.keys,
|
|
124
|
+
settings: baseContext.settings
|
|
125
|
+
});
|
|
126
|
+
return instance;
|
|
127
|
+
}, [baseContext]);
|
|
128
|
+
return typesafeInstance;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
var useBaseQuonfig = () => React__default.default.useContext(QuonfigContext);
|
|
132
|
+
var useQuonfig = () => useBaseQuonfig();
|
|
133
|
+
var globalQuonfigIsTaken = false;
|
|
134
|
+
var assignQuonfigClient = () => {
|
|
135
|
+
if (globalQuonfigIsTaken) {
|
|
136
|
+
return new javascript.Quonfig();
|
|
137
|
+
}
|
|
138
|
+
globalQuonfigIsTaken = true;
|
|
139
|
+
return javascript.quonfig;
|
|
140
|
+
};
|
|
141
|
+
var getContextKey = (contextAttributes, onError) => {
|
|
142
|
+
try {
|
|
143
|
+
if (Object.keys(contextAttributes).length === 0) {
|
|
144
|
+
console.warn(
|
|
145
|
+
"QuonfigProvider: You haven't passed any contextAttributes. See https://docs.quonfig.com/docs/sdks/react#using-context"
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return javascript.encodeContexts(contextAttributes);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
onError(e);
|
|
151
|
+
return "";
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
function QuonfigProvider({
|
|
155
|
+
sdkKey,
|
|
156
|
+
contextAttributes = {},
|
|
157
|
+
onError = (e) => {
|
|
158
|
+
console.error(e);
|
|
159
|
+
},
|
|
160
|
+
initialFlags,
|
|
161
|
+
children,
|
|
162
|
+
timeout,
|
|
163
|
+
apiUrl,
|
|
164
|
+
apiUrls,
|
|
165
|
+
pollInterval,
|
|
166
|
+
afterEvaluationCallback = void 0,
|
|
167
|
+
collectEvaluationSummaries,
|
|
168
|
+
collectLoggerNames
|
|
169
|
+
}) {
|
|
170
|
+
const settings = {
|
|
171
|
+
sdkKey,
|
|
172
|
+
apiUrl,
|
|
173
|
+
apiUrls,
|
|
174
|
+
timeout,
|
|
175
|
+
pollInterval,
|
|
176
|
+
onError,
|
|
177
|
+
afterEvaluationCallback,
|
|
178
|
+
collectEvaluationSummaries,
|
|
179
|
+
collectLoggerNames
|
|
180
|
+
};
|
|
181
|
+
const mostRecentlyLoadingContextKey = React__default.default.useRef(void 0);
|
|
182
|
+
const [loading, setLoading] = React__default.default.useState(true);
|
|
183
|
+
const [initialLoad, setInitialLoad] = React__default.default.useState(true);
|
|
184
|
+
const [loadedContextKey, setLoadedContextKey] = React__default.default.useState("");
|
|
185
|
+
const quonfigClient = React__default.default.useMemo(() => assignQuonfigClient(), []);
|
|
186
|
+
const contextKey = getContextKey(contextAttributes, onError);
|
|
187
|
+
if (initialFlags && initialLoad) {
|
|
188
|
+
quonfigClient.hydrate(initialFlags);
|
|
189
|
+
setInitialLoad(false);
|
|
190
|
+
setLoadedContextKey(contextKey);
|
|
191
|
+
setLoading(false);
|
|
192
|
+
mostRecentlyLoadingContextKey.current = contextKey;
|
|
193
|
+
if (pollInterval) {
|
|
194
|
+
console.warn("Polling is not supported when hydrating flags via initialFlags");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
React__default.default.useEffect(() => {
|
|
198
|
+
setInitialLoad(false);
|
|
199
|
+
if (mostRecentlyLoadingContextKey.current === contextKey) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
setLoading(true);
|
|
203
|
+
try {
|
|
204
|
+
if (mostRecentlyLoadingContextKey.current === void 0) {
|
|
205
|
+
mostRecentlyLoadingContextKey.current = contextKey;
|
|
206
|
+
if (!sdkKey) {
|
|
207
|
+
throw new Error("QuonfigProvider: sdkKey is required");
|
|
208
|
+
}
|
|
209
|
+
quonfigClient.clientNameString = "sdk-react";
|
|
210
|
+
const initOptions = {
|
|
211
|
+
context: contextAttributes,
|
|
212
|
+
sdkKey,
|
|
213
|
+
apiUrl,
|
|
214
|
+
apiUrls,
|
|
215
|
+
timeout,
|
|
216
|
+
afterEvaluationCallback,
|
|
217
|
+
collectEvaluationSummaries,
|
|
218
|
+
collectLoggerNames
|
|
219
|
+
};
|
|
220
|
+
quonfigClient.init(initOptions).then(() => {
|
|
221
|
+
setLoadedContextKey(contextKey);
|
|
222
|
+
setLoading(false);
|
|
223
|
+
if (pollInterval) {
|
|
224
|
+
quonfigClient.poll({ frequencyInMs: pollInterval });
|
|
225
|
+
}
|
|
226
|
+
}).catch((reason) => {
|
|
227
|
+
setLoading(false);
|
|
228
|
+
onError(reason);
|
|
229
|
+
});
|
|
230
|
+
} else {
|
|
231
|
+
mostRecentlyLoadingContextKey.current = contextKey;
|
|
232
|
+
quonfigClient.updateContext(contextAttributes).then(() => {
|
|
233
|
+
setLoadedContextKey(contextKey);
|
|
234
|
+
setLoading(false);
|
|
235
|
+
}).catch((reason) => {
|
|
236
|
+
setLoading(false);
|
|
237
|
+
onError(reason);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
} catch (e) {
|
|
241
|
+
setLoading(false);
|
|
242
|
+
onError(e);
|
|
243
|
+
}
|
|
244
|
+
}, [
|
|
245
|
+
sdkKey,
|
|
246
|
+
loadedContextKey,
|
|
247
|
+
contextKey,
|
|
248
|
+
loading,
|
|
249
|
+
setLoading,
|
|
250
|
+
onError,
|
|
251
|
+
quonfigClient.instanceHash
|
|
252
|
+
]);
|
|
253
|
+
const value = React__default.default.useMemo(() => {
|
|
254
|
+
const baseContext = {
|
|
255
|
+
isEnabled: quonfigClient.isEnabled.bind(quonfigClient),
|
|
256
|
+
contextAttributes,
|
|
257
|
+
get: quonfigClient.get.bind(quonfigClient),
|
|
258
|
+
getDuration: quonfigClient.getDuration.bind(quonfigClient),
|
|
259
|
+
keys: Object.keys(quonfigClient.extract()),
|
|
260
|
+
quonfig: quonfigClient,
|
|
261
|
+
loading,
|
|
262
|
+
settings
|
|
263
|
+
};
|
|
264
|
+
return baseContext;
|
|
265
|
+
}, [loadedContextKey, loading, quonfigClient.instanceHash, settings]);
|
|
266
|
+
return /* @__PURE__ */ React__default.default.createElement(QuonfigContext.Provider, { value }, children);
|
|
267
|
+
}
|
|
268
|
+
function QuonfigTestProvider({
|
|
269
|
+
sdkKey,
|
|
270
|
+
config,
|
|
271
|
+
children
|
|
272
|
+
}) {
|
|
273
|
+
const get = (key) => config[key];
|
|
274
|
+
const getDuration = (key) => config[key];
|
|
275
|
+
const isEnabled = (key) => !!get(key);
|
|
276
|
+
const quonfigClient = React__default.default.useMemo(() => assignQuonfigClient(), []);
|
|
277
|
+
const value = React__default.default.useMemo(() => {
|
|
278
|
+
quonfigClient.get = get;
|
|
279
|
+
quonfigClient.getDuration = getDuration;
|
|
280
|
+
quonfigClient.isEnabled = isEnabled;
|
|
281
|
+
const baseContext = {
|
|
282
|
+
isEnabled,
|
|
283
|
+
contextAttributes: config.contextAttributes,
|
|
284
|
+
get,
|
|
285
|
+
getDuration,
|
|
286
|
+
loading: false,
|
|
287
|
+
quonfig: quonfigClient,
|
|
288
|
+
keys: Object.keys(config),
|
|
289
|
+
settings: { sdkKey: sdkKey != null ? sdkKey : "fake-sdk-key-via-the-test-provider" }
|
|
290
|
+
};
|
|
291
|
+
return baseContext;
|
|
292
|
+
}, [config, quonfigClient, sdkKey]);
|
|
293
|
+
return /* @__PURE__ */ React__default.default.createElement(QuonfigContext.Provider, { value }, children);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
Object.defineProperty(exports, "quonfig", {
|
|
297
|
+
enumerable: true,
|
|
298
|
+
get: function () { return javascript.quonfig; }
|
|
299
|
+
});
|
|
300
|
+
exports.QuonfigProvider = QuonfigProvider;
|
|
301
|
+
exports.QuonfigTestProvider = QuonfigTestProvider;
|
|
302
|
+
exports.createQuonfigHook = createQuonfigHook;
|
|
303
|
+
exports.useQuonfig = useQuonfig;
|
|
304
|
+
//# sourceMappingURL=index.cjs.map
|
|
305
|
+
//# sourceMappingURL=index.cjs.map
|