@savvagent/solid 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/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/index.d.mts +173 -0
- package/dist/index.d.ts +173 -0
- package/dist/index.js +117 -0
- package/dist/index.mjs +93 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Savvagent, LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# @savvagent/solid
|
|
2
|
+
|
|
3
|
+
SolidJS SDK for Savvagent with reactive primitives (signals and resources).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @savvagent/solid
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { SavvagentProvider, createFlag } from '@savvagent/solid';
|
|
15
|
+
import { Show } from 'solid-js';
|
|
16
|
+
|
|
17
|
+
function App() {
|
|
18
|
+
return (
|
|
19
|
+
<SavvagentProvider config={{ apiKey: 'sdk_...' }}>
|
|
20
|
+
<MyFeature />
|
|
21
|
+
</SavvagentProvider>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function MyFeature() {
|
|
26
|
+
const flag = createFlag('new-feature');
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Show when={!flag.loading()} fallback={<div>Loading...</div>}>
|
|
30
|
+
<Show when={flag.value()} fallback={<OldFeature />}>
|
|
31
|
+
<NewFeature />
|
|
32
|
+
</Show>
|
|
33
|
+
</Show>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API Reference
|
|
39
|
+
|
|
40
|
+
### `createFlag(flagKey, options)`
|
|
41
|
+
|
|
42
|
+
Create a reactive flag with full state.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
const flag = createFlag('new-feature', {
|
|
46
|
+
context: { user_id: userId() },
|
|
47
|
+
defaultValue: false,
|
|
48
|
+
realtime: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Access values
|
|
52
|
+
flag.value(); // boolean
|
|
53
|
+
flag.loading(); // boolean
|
|
54
|
+
flag.error(); // Error | null
|
|
55
|
+
flag.refetch(); // force re-evaluation
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `createFlagValue(flagKey, options)`
|
|
59
|
+
|
|
60
|
+
Simple accessor for flag value only.
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
const isEnabled = createFlagValue('new-feature');
|
|
64
|
+
|
|
65
|
+
return <Show when={isEnabled()}><NewFeature /></Show>;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `createUserSignals()`
|
|
69
|
+
|
|
70
|
+
Manage user identification.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
const [userId, setUserId] = createUserSignals();
|
|
74
|
+
|
|
75
|
+
createEffect(() => {
|
|
76
|
+
setUserId(currentUser()?.id || null);
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as solid_js from 'solid-js';
|
|
2
|
+
import { ParentProps, Accessor } from 'solid-js';
|
|
3
|
+
import { FlagClientConfig, FlagClient, FlagContext, FlagEvaluationResult } from '@savvagent/sdk';
|
|
4
|
+
export { ApiTypes, ErrorEvent, EvaluationEvent, FlagClient, FlagClientConfig, FlagContext, FlagEvaluationResult, FlagUpdateEvent, components } from '@savvagent/sdk';
|
|
5
|
+
|
|
6
|
+
interface SavvagentProviderProps extends ParentProps {
|
|
7
|
+
config: FlagClientConfig;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Provider component that initializes and provides the Savvagent client.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { SavvagentProvider } from '@savvagent/solid';
|
|
15
|
+
*
|
|
16
|
+
* function App() {
|
|
17
|
+
* return (
|
|
18
|
+
* <SavvagentProvider config={{ apiKey: 'sdk_...' }}>
|
|
19
|
+
* <MyApp />
|
|
20
|
+
* </SavvagentProvider>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function SavvagentProvider(props: SavvagentProviderProps): solid_js.JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Get the Savvagent client instance.
|
|
28
|
+
* Must be used within a SavvagentProvider.
|
|
29
|
+
*
|
|
30
|
+
* @returns The FlagClient instance
|
|
31
|
+
* @throws Error if used outside of SavvagentProvider
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* import { useSavvagent } from '@savvagent/solid';
|
|
36
|
+
*
|
|
37
|
+
* function MyComponent() {
|
|
38
|
+
* const client = useSavvagent();
|
|
39
|
+
* const enabled = await client.isEnabled('my-feature');
|
|
40
|
+
* return <div>Enabled: {enabled}</div>;
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare function useSavvagent(): FlagClient;
|
|
45
|
+
interface CreateFlagOptions {
|
|
46
|
+
/** Context for flag evaluation */
|
|
47
|
+
context?: FlagContext;
|
|
48
|
+
/** Default value while loading or on error */
|
|
49
|
+
defaultValue?: boolean;
|
|
50
|
+
/** Enable real-time updates */
|
|
51
|
+
realtime?: boolean;
|
|
52
|
+
/** Custom error handler */
|
|
53
|
+
onError?: (error: Error) => void;
|
|
54
|
+
}
|
|
55
|
+
interface CreateFlagReturn {
|
|
56
|
+
/** Current flag value */
|
|
57
|
+
value: Accessor<boolean>;
|
|
58
|
+
/** Whether the flag is loading */
|
|
59
|
+
loading: Accessor<boolean>;
|
|
60
|
+
/** Error if evaluation failed */
|
|
61
|
+
error: Accessor<Error | null>;
|
|
62
|
+
/** Detailed evaluation result */
|
|
63
|
+
result: Accessor<FlagEvaluationResult | null>;
|
|
64
|
+
/** Force re-evaluation */
|
|
65
|
+
refetch: () => void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create a reactive flag with automatic updates.
|
|
69
|
+
*
|
|
70
|
+
* @param flagKey - The feature flag key
|
|
71
|
+
* @param options - Configuration options
|
|
72
|
+
* @returns Reactive flag state
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* import { createFlag } from '@savvagent/solid';
|
|
77
|
+
* import { Show } from 'solid-js';
|
|
78
|
+
*
|
|
79
|
+
* function MyComponent() {
|
|
80
|
+
* const flag = createFlag('new-feature', {
|
|
81
|
+
* context: { user_id: userId() },
|
|
82
|
+
* defaultValue: false,
|
|
83
|
+
* realtime: true,
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* return (
|
|
87
|
+
* <Show when={!flag.loading()} fallback={<div>Loading...</div>}>
|
|
88
|
+
* <Show when={flag.value()} fallback={<OldFeature />}>
|
|
89
|
+
* <NewFeature />
|
|
90
|
+
* </Show>
|
|
91
|
+
* </Show>
|
|
92
|
+
* );
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function createFlag(flagKey: string, options?: CreateFlagOptions): CreateFlagReturn;
|
|
97
|
+
/**
|
|
98
|
+
* Create a simple reactive flag that returns only the boolean value.
|
|
99
|
+
*
|
|
100
|
+
* @param flagKey - The feature flag key
|
|
101
|
+
* @param options - Configuration options
|
|
102
|
+
* @returns Accessor for flag value
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```tsx
|
|
106
|
+
* import { createFlagValue } from '@savvagent/solid';
|
|
107
|
+
* import { Show } from 'solid-js';
|
|
108
|
+
*
|
|
109
|
+
* function MyComponent() {
|
|
110
|
+
* const isEnabled = createFlagValue('new-feature');
|
|
111
|
+
*
|
|
112
|
+
* return (
|
|
113
|
+
* <Show when={isEnabled()}>
|
|
114
|
+
* <NewFeature />
|
|
115
|
+
* </Show>
|
|
116
|
+
* );
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
declare function createFlagValue(flagKey: string, options?: CreateFlagOptions): Accessor<boolean>;
|
|
121
|
+
/**
|
|
122
|
+
* Create signals for user identification.
|
|
123
|
+
*
|
|
124
|
+
* @returns User ID management functions
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* import { createUserSignals } from '@savvagent/solid';
|
|
129
|
+
* import { createEffect } from 'solid-js';
|
|
130
|
+
*
|
|
131
|
+
* function AuthHandler() {
|
|
132
|
+
* const [userId, setUserId] = createUserSignals();
|
|
133
|
+
*
|
|
134
|
+
* createEffect(() => {
|
|
135
|
+
* if (currentUser()) {
|
|
136
|
+
* setUserId(currentUser().id);
|
|
137
|
+
* } else {
|
|
138
|
+
* setUserId(null);
|
|
139
|
+
* }
|
|
140
|
+
* });
|
|
141
|
+
*
|
|
142
|
+
* return null;
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
declare function createUserSignals(): readonly [Accessor<string | null>, (id: string | null) => void];
|
|
147
|
+
/**
|
|
148
|
+
* Track an error with flag context.
|
|
149
|
+
*
|
|
150
|
+
* @param flagKey - The flag key associated with the error
|
|
151
|
+
* @param error - The error that occurred
|
|
152
|
+
* @param context - Optional context
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```tsx
|
|
156
|
+
* import { trackError } from '@savvagent/solid';
|
|
157
|
+
*
|
|
158
|
+
* function MyComponent() {
|
|
159
|
+
* const handleAction = async () => {
|
|
160
|
+
* try {
|
|
161
|
+
* await doSomething();
|
|
162
|
+
* } catch (error) {
|
|
163
|
+
* trackError('new-feature', error as Error);
|
|
164
|
+
* }
|
|
165
|
+
* };
|
|
166
|
+
*
|
|
167
|
+
* return <button onClick={handleAction}>Try Feature</button>;
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare function trackError(flagKey: string, error: Error, context?: FlagContext): void;
|
|
172
|
+
|
|
173
|
+
export { type CreateFlagOptions, type CreateFlagReturn, SavvagentProvider, type SavvagentProviderProps, createFlag, createFlagValue, createUserSignals, trackError, useSavvagent };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as solid_js from 'solid-js';
|
|
2
|
+
import { ParentProps, Accessor } from 'solid-js';
|
|
3
|
+
import { FlagClientConfig, FlagClient, FlagContext, FlagEvaluationResult } from '@savvagent/sdk';
|
|
4
|
+
export { ApiTypes, ErrorEvent, EvaluationEvent, FlagClient, FlagClientConfig, FlagContext, FlagEvaluationResult, FlagUpdateEvent, components } from '@savvagent/sdk';
|
|
5
|
+
|
|
6
|
+
interface SavvagentProviderProps extends ParentProps {
|
|
7
|
+
config: FlagClientConfig;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Provider component that initializes and provides the Savvagent client.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { SavvagentProvider } from '@savvagent/solid';
|
|
15
|
+
*
|
|
16
|
+
* function App() {
|
|
17
|
+
* return (
|
|
18
|
+
* <SavvagentProvider config={{ apiKey: 'sdk_...' }}>
|
|
19
|
+
* <MyApp />
|
|
20
|
+
* </SavvagentProvider>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function SavvagentProvider(props: SavvagentProviderProps): solid_js.JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Get the Savvagent client instance.
|
|
28
|
+
* Must be used within a SavvagentProvider.
|
|
29
|
+
*
|
|
30
|
+
* @returns The FlagClient instance
|
|
31
|
+
* @throws Error if used outside of SavvagentProvider
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* import { useSavvagent } from '@savvagent/solid';
|
|
36
|
+
*
|
|
37
|
+
* function MyComponent() {
|
|
38
|
+
* const client = useSavvagent();
|
|
39
|
+
* const enabled = await client.isEnabled('my-feature');
|
|
40
|
+
* return <div>Enabled: {enabled}</div>;
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare function useSavvagent(): FlagClient;
|
|
45
|
+
interface CreateFlagOptions {
|
|
46
|
+
/** Context for flag evaluation */
|
|
47
|
+
context?: FlagContext;
|
|
48
|
+
/** Default value while loading or on error */
|
|
49
|
+
defaultValue?: boolean;
|
|
50
|
+
/** Enable real-time updates */
|
|
51
|
+
realtime?: boolean;
|
|
52
|
+
/** Custom error handler */
|
|
53
|
+
onError?: (error: Error) => void;
|
|
54
|
+
}
|
|
55
|
+
interface CreateFlagReturn {
|
|
56
|
+
/** Current flag value */
|
|
57
|
+
value: Accessor<boolean>;
|
|
58
|
+
/** Whether the flag is loading */
|
|
59
|
+
loading: Accessor<boolean>;
|
|
60
|
+
/** Error if evaluation failed */
|
|
61
|
+
error: Accessor<Error | null>;
|
|
62
|
+
/** Detailed evaluation result */
|
|
63
|
+
result: Accessor<FlagEvaluationResult | null>;
|
|
64
|
+
/** Force re-evaluation */
|
|
65
|
+
refetch: () => void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create a reactive flag with automatic updates.
|
|
69
|
+
*
|
|
70
|
+
* @param flagKey - The feature flag key
|
|
71
|
+
* @param options - Configuration options
|
|
72
|
+
* @returns Reactive flag state
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* import { createFlag } from '@savvagent/solid';
|
|
77
|
+
* import { Show } from 'solid-js';
|
|
78
|
+
*
|
|
79
|
+
* function MyComponent() {
|
|
80
|
+
* const flag = createFlag('new-feature', {
|
|
81
|
+
* context: { user_id: userId() },
|
|
82
|
+
* defaultValue: false,
|
|
83
|
+
* realtime: true,
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* return (
|
|
87
|
+
* <Show when={!flag.loading()} fallback={<div>Loading...</div>}>
|
|
88
|
+
* <Show when={flag.value()} fallback={<OldFeature />}>
|
|
89
|
+
* <NewFeature />
|
|
90
|
+
* </Show>
|
|
91
|
+
* </Show>
|
|
92
|
+
* );
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function createFlag(flagKey: string, options?: CreateFlagOptions): CreateFlagReturn;
|
|
97
|
+
/**
|
|
98
|
+
* Create a simple reactive flag that returns only the boolean value.
|
|
99
|
+
*
|
|
100
|
+
* @param flagKey - The feature flag key
|
|
101
|
+
* @param options - Configuration options
|
|
102
|
+
* @returns Accessor for flag value
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```tsx
|
|
106
|
+
* import { createFlagValue } from '@savvagent/solid';
|
|
107
|
+
* import { Show } from 'solid-js';
|
|
108
|
+
*
|
|
109
|
+
* function MyComponent() {
|
|
110
|
+
* const isEnabled = createFlagValue('new-feature');
|
|
111
|
+
*
|
|
112
|
+
* return (
|
|
113
|
+
* <Show when={isEnabled()}>
|
|
114
|
+
* <NewFeature />
|
|
115
|
+
* </Show>
|
|
116
|
+
* );
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
declare function createFlagValue(flagKey: string, options?: CreateFlagOptions): Accessor<boolean>;
|
|
121
|
+
/**
|
|
122
|
+
* Create signals for user identification.
|
|
123
|
+
*
|
|
124
|
+
* @returns User ID management functions
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* import { createUserSignals } from '@savvagent/solid';
|
|
129
|
+
* import { createEffect } from 'solid-js';
|
|
130
|
+
*
|
|
131
|
+
* function AuthHandler() {
|
|
132
|
+
* const [userId, setUserId] = createUserSignals();
|
|
133
|
+
*
|
|
134
|
+
* createEffect(() => {
|
|
135
|
+
* if (currentUser()) {
|
|
136
|
+
* setUserId(currentUser().id);
|
|
137
|
+
* } else {
|
|
138
|
+
* setUserId(null);
|
|
139
|
+
* }
|
|
140
|
+
* });
|
|
141
|
+
*
|
|
142
|
+
* return null;
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
declare function createUserSignals(): readonly [Accessor<string | null>, (id: string | null) => void];
|
|
147
|
+
/**
|
|
148
|
+
* Track an error with flag context.
|
|
149
|
+
*
|
|
150
|
+
* @param flagKey - The flag key associated with the error
|
|
151
|
+
* @param error - The error that occurred
|
|
152
|
+
* @param context - Optional context
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```tsx
|
|
156
|
+
* import { trackError } from '@savvagent/solid';
|
|
157
|
+
*
|
|
158
|
+
* function MyComponent() {
|
|
159
|
+
* const handleAction = async () => {
|
|
160
|
+
* try {
|
|
161
|
+
* await doSomething();
|
|
162
|
+
* } catch (error) {
|
|
163
|
+
* trackError('new-feature', error as Error);
|
|
164
|
+
* }
|
|
165
|
+
* };
|
|
166
|
+
*
|
|
167
|
+
* return <button onClick={handleAction}>Try Feature</button>;
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare function trackError(flagKey: string, error: Error, context?: FlagContext): void;
|
|
172
|
+
|
|
173
|
+
export { type CreateFlagOptions, type CreateFlagReturn, SavvagentProvider, type SavvagentProviderProps, createFlag, createFlagValue, createUserSignals, trackError, useSavvagent };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.tsx
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
FlagClient: () => import_sdk2.FlagClient,
|
|
24
|
+
SavvagentProvider: () => SavvagentProvider,
|
|
25
|
+
createFlag: () => createFlag,
|
|
26
|
+
createFlagValue: () => createFlagValue,
|
|
27
|
+
createUserSignals: () => createUserSignals,
|
|
28
|
+
trackError: () => trackError,
|
|
29
|
+
useSavvagent: () => useSavvagent
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
var import_solid_js = require("solid-js");
|
|
33
|
+
var import_sdk = require("@savvagent/sdk");
|
|
34
|
+
var import_sdk2 = require("@savvagent/sdk");
|
|
35
|
+
var SavvagentContext = (0, import_solid_js.createContext)();
|
|
36
|
+
function SavvagentProvider(props) {
|
|
37
|
+
const client = new import_sdk.FlagClient(props.config);
|
|
38
|
+
(0, import_solid_js.onCleanup)(() => {
|
|
39
|
+
client.close();
|
|
40
|
+
});
|
|
41
|
+
return /* @__PURE__ */ React.createElement(SavvagentContext.Provider, { value: client }, props.children);
|
|
42
|
+
}
|
|
43
|
+
function useSavvagent() {
|
|
44
|
+
const client = (0, import_solid_js.useContext)(SavvagentContext);
|
|
45
|
+
if (!client) {
|
|
46
|
+
throw new Error("useSavvagent must be used within a SavvagentProvider");
|
|
47
|
+
}
|
|
48
|
+
return client;
|
|
49
|
+
}
|
|
50
|
+
function createFlag(flagKey, options = {}) {
|
|
51
|
+
const client = useSavvagent();
|
|
52
|
+
const {
|
|
53
|
+
context,
|
|
54
|
+
defaultValue = false,
|
|
55
|
+
realtime = true,
|
|
56
|
+
onError
|
|
57
|
+
} = options;
|
|
58
|
+
const [trigger, setTrigger] = (0, import_solid_js.createSignal)(0);
|
|
59
|
+
const [result] = (0, import_solid_js.createResource)(
|
|
60
|
+
trigger,
|
|
61
|
+
async () => {
|
|
62
|
+
try {
|
|
63
|
+
return await client.evaluate(flagKey, context);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
const error2 = err;
|
|
66
|
+
onError?.(error2);
|
|
67
|
+
throw error2;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
const value = () => result()?.value ?? defaultValue;
|
|
72
|
+
const loading = () => result.loading;
|
|
73
|
+
const error = () => result.error ?? null;
|
|
74
|
+
(0, import_solid_js.createEffect)(() => {
|
|
75
|
+
if (!realtime) return;
|
|
76
|
+
const unsubscribe = client.subscribe(flagKey, () => {
|
|
77
|
+
setTrigger((t) => t + 1);
|
|
78
|
+
});
|
|
79
|
+
(0, import_solid_js.onCleanup)(() => {
|
|
80
|
+
unsubscribe();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
value,
|
|
85
|
+
loading,
|
|
86
|
+
error,
|
|
87
|
+
result: () => result() ?? null,
|
|
88
|
+
refetch: () => setTrigger((t) => t + 1)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function createFlagValue(flagKey, options = {}) {
|
|
92
|
+
const flag = createFlag(flagKey, options);
|
|
93
|
+
return flag.value;
|
|
94
|
+
}
|
|
95
|
+
function createUserSignals() {
|
|
96
|
+
const client = useSavvagent();
|
|
97
|
+
const [userId, setUserIdSignal] = (0, import_solid_js.createSignal)(client.getUserId());
|
|
98
|
+
const setUserId = (id) => {
|
|
99
|
+
client.setUserId(id);
|
|
100
|
+
setUserIdSignal(id);
|
|
101
|
+
};
|
|
102
|
+
return [userId, setUserId];
|
|
103
|
+
}
|
|
104
|
+
function trackError(flagKey, error, context) {
|
|
105
|
+
const client = useSavvagent();
|
|
106
|
+
client.trackError(flagKey, error, context);
|
|
107
|
+
}
|
|
108
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
109
|
+
0 && (module.exports = {
|
|
110
|
+
FlagClient,
|
|
111
|
+
SavvagentProvider,
|
|
112
|
+
createFlag,
|
|
113
|
+
createFlagValue,
|
|
114
|
+
createUserSignals,
|
|
115
|
+
trackError,
|
|
116
|
+
useSavvagent
|
|
117
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/index.tsx
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
useContext,
|
|
5
|
+
createSignal,
|
|
6
|
+
createResource,
|
|
7
|
+
createEffect,
|
|
8
|
+
onCleanup
|
|
9
|
+
} from "solid-js";
|
|
10
|
+
import { FlagClient } from "@savvagent/sdk";
|
|
11
|
+
import { FlagClient as FlagClient2 } from "@savvagent/sdk";
|
|
12
|
+
var SavvagentContext = createContext();
|
|
13
|
+
function SavvagentProvider(props) {
|
|
14
|
+
const client = new FlagClient(props.config);
|
|
15
|
+
onCleanup(() => {
|
|
16
|
+
client.close();
|
|
17
|
+
});
|
|
18
|
+
return /* @__PURE__ */ React.createElement(SavvagentContext.Provider, { value: client }, props.children);
|
|
19
|
+
}
|
|
20
|
+
function useSavvagent() {
|
|
21
|
+
const client = useContext(SavvagentContext);
|
|
22
|
+
if (!client) {
|
|
23
|
+
throw new Error("useSavvagent must be used within a SavvagentProvider");
|
|
24
|
+
}
|
|
25
|
+
return client;
|
|
26
|
+
}
|
|
27
|
+
function createFlag(flagKey, options = {}) {
|
|
28
|
+
const client = useSavvagent();
|
|
29
|
+
const {
|
|
30
|
+
context,
|
|
31
|
+
defaultValue = false,
|
|
32
|
+
realtime = true,
|
|
33
|
+
onError
|
|
34
|
+
} = options;
|
|
35
|
+
const [trigger, setTrigger] = createSignal(0);
|
|
36
|
+
const [result] = createResource(
|
|
37
|
+
trigger,
|
|
38
|
+
async () => {
|
|
39
|
+
try {
|
|
40
|
+
return await client.evaluate(flagKey, context);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
const error2 = err;
|
|
43
|
+
onError?.(error2);
|
|
44
|
+
throw error2;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
const value = () => result()?.value ?? defaultValue;
|
|
49
|
+
const loading = () => result.loading;
|
|
50
|
+
const error = () => result.error ?? null;
|
|
51
|
+
createEffect(() => {
|
|
52
|
+
if (!realtime) return;
|
|
53
|
+
const unsubscribe = client.subscribe(flagKey, () => {
|
|
54
|
+
setTrigger((t) => t + 1);
|
|
55
|
+
});
|
|
56
|
+
onCleanup(() => {
|
|
57
|
+
unsubscribe();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
value,
|
|
62
|
+
loading,
|
|
63
|
+
error,
|
|
64
|
+
result: () => result() ?? null,
|
|
65
|
+
refetch: () => setTrigger((t) => t + 1)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function createFlagValue(flagKey, options = {}) {
|
|
69
|
+
const flag = createFlag(flagKey, options);
|
|
70
|
+
return flag.value;
|
|
71
|
+
}
|
|
72
|
+
function createUserSignals() {
|
|
73
|
+
const client = useSavvagent();
|
|
74
|
+
const [userId, setUserIdSignal] = createSignal(client.getUserId());
|
|
75
|
+
const setUserId = (id) => {
|
|
76
|
+
client.setUserId(id);
|
|
77
|
+
setUserIdSignal(id);
|
|
78
|
+
};
|
|
79
|
+
return [userId, setUserId];
|
|
80
|
+
}
|
|
81
|
+
function trackError(flagKey, error, context) {
|
|
82
|
+
const client = useSavvagent();
|
|
83
|
+
client.trackError(flagKey, error, context);
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
FlagClient2 as FlagClient,
|
|
87
|
+
SavvagentProvider,
|
|
88
|
+
createFlag,
|
|
89
|
+
createFlagValue,
|
|
90
|
+
createUserSignals,
|
|
91
|
+
trackError,
|
|
92
|
+
useSavvagent
|
|
93
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@savvagent/solid",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SolidJS SDK for Savvagent feature flags with reactive primitives",
|
|
5
|
+
"author": "Savvagent",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/index.mjs",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"solid-js": ">=1.0.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@savvagent/sdk": "1.0.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"solid-js": "^1.8.0",
|
|
28
|
+
"tsup": "^8.0.0",
|
|
29
|
+
"typescript": "^5.4.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"savvagent",
|
|
33
|
+
"feature-flags",
|
|
34
|
+
"solidjs",
|
|
35
|
+
"solid",
|
|
36
|
+
"reactive",
|
|
37
|
+
"signals",
|
|
38
|
+
"feature-toggles"
|
|
39
|
+
],
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/savvagent/savvagent-sdks",
|
|
43
|
+
"directory": "packages/solid"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/savvagent/savvagent-sdks/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/savvagent/savvagent-sdks/tree/main/packages/solid#readme",
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup src/index.tsx --format cjs,esm --dts --external solid-js",
|
|
54
|
+
"dev": "tsup src/index.tsx --format cjs,esm --dts --external solid-js --watch",
|
|
55
|
+
"test": "vitest",
|
|
56
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
57
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
58
|
+
}
|
|
59
|
+
}
|