@spotify-confidence/openfeature-server-provider-local 0.4.0 → 0.5.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 +14 -0
- package/README.md +64 -7
- package/dist/confidence_resolver.wasm +0 -0
- package/dist/index.browser.d.ts +247 -99
- package/dist/index.browser.js +1626 -754
- package/dist/index.node.d.ts +247 -99
- package/dist/index.node.js +1626 -754
- package/dist/{messages-CvypvyG4.js → messages-BjOGSPNo.js} +1 -1
- package/dist/messages-ZL-6wQib.js +208 -0
- package/package.json +2 -2
- package/dist/messages-Bw39oRlC.js +0 -524
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0](https://github.com/spotify/confidence-resolver/compare/openfeature-provider-js-v0.4.0...openfeature-provider-js-v0.5.0) (2025-12-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* pluggable materialization ([#211](https://github.com/spotify/confidence-resolver/issues/211)) ([96aea72](https://github.com/spotify/confidence-resolver/commit/96aea72a2dce2e02fdfa4374e4fa245f0efc177b))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* rust-guest bumped from 0.1.11 to 0.1.12
|
|
16
|
+
|
|
3
17
|
## [0.4.0](https://github.com/spotify/confidence-resolver/compare/openfeature-provider-js-v0.3.0...openfeature-provider-js-v0.4.0) (2025-12-11)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -138,15 +138,72 @@ The provider periodically:
|
|
|
138
138
|
|
|
139
139
|
---
|
|
140
140
|
|
|
141
|
-
##
|
|
141
|
+
## Materialization Stores
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
Materialization stores provide persistent storage for sticky variant assignments and custom targeting segments. This enables two key use cases:
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
1. **Sticky Assignments**: Maintain consistent variant assignments across evaluations even when targeting attributes change. This enables pausing intake (stopping new users from entering an experiment) while keeping existing users in their assigned variants.
|
|
146
|
+
|
|
147
|
+
2. **Custom Targeting via Materialized Segments**: Precomputed sets of identifiers from datasets that should be targeted. Instead of evaluating complex targeting rules at runtime, materializations allow efficient lookup of whether a unit (user, session, etc.) is included in a target segment.
|
|
148
|
+
|
|
149
|
+
### Default Behavior
|
|
150
|
+
|
|
151
|
+
⚠️ Warning: If your flags rely on sticky assignments or materialized segments, the default SDK behaviour will prevent those rules from being applied and your evaluations will fall back to default values. For production workloads that need sticky behavior or segment lookups, implement and configure a real `MaterializationStore` (e.g., Redis, DynamoDB, or a key-value store) to avoid unexpected fallbacks and ensure consistent variant assignment.
|
|
152
|
+
|
|
153
|
+
### Remote Materialization Store
|
|
154
|
+
|
|
155
|
+
For quick setup without managing your own storage infrastructure, enable the built-in remote materialization store:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const provider = createConfidenceServerProvider({
|
|
159
|
+
flagClientSecret: process.env.CONFIDENCE_FLAG_CLIENT_SECRET!,
|
|
160
|
+
materializationStore: 'CONFIDENCE_REMOTE_STORE',
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**When to use**:
|
|
165
|
+
- You need sticky assignments or materialized segments but don't want to manage storage infrastructure
|
|
166
|
+
- Quick prototyping or getting started
|
|
167
|
+
- Lower-volume applications where network latency is acceptable
|
|
168
|
+
|
|
169
|
+
**Trade-offs**:
|
|
170
|
+
- Additional network calls during flag resolution (adds latency)
|
|
171
|
+
- Lower performance compared to local storage implementations (Redis, DynamoDB, etc.)
|
|
172
|
+
|
|
173
|
+
### Custom Implementations
|
|
174
|
+
|
|
175
|
+
For improved latency and reduced network calls, implement the `MaterializationStore` interface to store materialization data in your infrastructure:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import { MaterializationStore } from '@spotify-confidence/openfeature-server-provider-local';
|
|
179
|
+
|
|
180
|
+
class MyRedisStore implements MaterializationStore {
|
|
181
|
+
async readMaterializations(readOps: MaterializationStore.ReadOp[]): Promise<MaterializationStore.ReadResult[]> {
|
|
182
|
+
// Load materialization data from Redis
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async writeMaterializations(writeOps: MaterializationStore.WriteOp[]): Promise<void> {
|
|
186
|
+
// Store materialization data to Redis
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const provider = createConfidenceServerProvider({
|
|
191
|
+
flagClientSecret: process.env.CONFIDENCE_FLAG_CLIENT_SECRET!,
|
|
192
|
+
materializationStore: new MyRedisStore(),
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
For read-only stores (e.g., pre-populated materialized segments without sticky assignment writes), omit the `writeMaterializations` method.
|
|
197
|
+
|
|
198
|
+
### When to Use Materialization Stores
|
|
199
|
+
|
|
200
|
+
Consider implementing a materialization store if:
|
|
201
|
+
- You need to support sticky variant assignments for experiments
|
|
202
|
+
- You use materialized segments for custom targeting
|
|
203
|
+
- You want to minimize network latency during flag resolution
|
|
204
|
+
- You have high-volume flag evaluations
|
|
205
|
+
|
|
206
|
+
If you don't use sticky assignments or materialized segments, the default behavior is sufficient.
|
|
150
207
|
|
|
151
208
|
---
|
|
152
209
|
|
|
Binary file
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -1,8 +1,85 @@
|
|
|
1
1
|
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
2
2
|
import { EvaluationContext, JsonValue, Provider, ProviderMetadata, ProviderStatus, ResolutionDetails } from "@openfeature/server-sdk";
|
|
3
3
|
|
|
4
|
+
//#region src/proto/confidence/flags/types/v1/types.d.ts
|
|
5
|
+
/** Schema for the value of a flag. */
|
|
6
|
+
interface FlagSchema {
|
|
7
|
+
/** Schema if this is a struct */
|
|
8
|
+
structSchema?: FlagSchema_StructFlagSchema | undefined;
|
|
9
|
+
/** Schema if this is a list */
|
|
10
|
+
listSchema?: FlagSchema_ListFlagSchema | undefined;
|
|
11
|
+
/** Schema if this is an int */
|
|
12
|
+
intSchema?: FlagSchema_IntFlagSchema | undefined;
|
|
13
|
+
/** Schema if this is a double */
|
|
14
|
+
doubleSchema?: FlagSchema_DoubleFlagSchema | undefined;
|
|
15
|
+
/** Schema if this is a string */
|
|
16
|
+
stringSchema?: FlagSchema_StringFlagSchema | undefined;
|
|
17
|
+
/** Schema if this is a bool */
|
|
18
|
+
boolSchema?: FlagSchema_BoolFlagSchema | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** A schema of nested fields. */
|
|
21
|
+
interface FlagSchema_StructFlagSchema {
|
|
22
|
+
/** Map of field name to the schema for the field */
|
|
23
|
+
schema: {
|
|
24
|
+
[key: string]: FlagSchema;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** A number that has a decimal place. */
|
|
28
|
+
interface FlagSchema_DoubleFlagSchema {}
|
|
29
|
+
/** A whole number without a decimal point. */
|
|
30
|
+
interface FlagSchema_IntFlagSchema {}
|
|
31
|
+
/** A string. */
|
|
32
|
+
interface FlagSchema_StringFlagSchema {}
|
|
33
|
+
/** A boolean: true or false. */
|
|
34
|
+
interface FlagSchema_BoolFlagSchema {}
|
|
35
|
+
/** A list of values. */
|
|
36
|
+
interface FlagSchema_ListFlagSchema {
|
|
37
|
+
/** The schema for the elements in the list */
|
|
38
|
+
elementSchema?: FlagSchema | undefined;
|
|
39
|
+
}
|
|
40
|
+
declare const FlagSchema: MessageFns$5<FlagSchema>;
|
|
41
|
+
declare const FlagSchema_StructFlagSchema: MessageFns$5<FlagSchema_StructFlagSchema>;
|
|
42
|
+
declare const FlagSchema_DoubleFlagSchema: MessageFns$5<FlagSchema_DoubleFlagSchema>;
|
|
43
|
+
declare const FlagSchema_IntFlagSchema: MessageFns$5<FlagSchema_IntFlagSchema>;
|
|
44
|
+
declare const FlagSchema_StringFlagSchema: MessageFns$5<FlagSchema_StringFlagSchema>;
|
|
45
|
+
declare const FlagSchema_BoolFlagSchema: MessageFns$5<FlagSchema_BoolFlagSchema>;
|
|
46
|
+
declare const FlagSchema_ListFlagSchema: MessageFns$5<FlagSchema_ListFlagSchema>;
|
|
47
|
+
type Builtin$5 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
48
|
+
type DeepPartial$5<T> = T extends Builtin$5 ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial$5<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial$5<U>> : T extends {} ? { [K in keyof T]?: DeepPartial$5<T[K]> } : Partial<T>;
|
|
49
|
+
type KeysOfUnion$5<T> = T extends T ? keyof T : never;
|
|
50
|
+
type Exact$5<P, I extends P> = P extends Builtin$5 ? P : P & { [K in keyof P]: Exact$5<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion$5<P>>]: never };
|
|
51
|
+
interface MessageFns$5<T> {
|
|
52
|
+
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
|
53
|
+
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
|
54
|
+
fromJSON(object: any): T;
|
|
55
|
+
toJSON(message: T): unknown;
|
|
56
|
+
create<I extends Exact$5<DeepPartial$5<T>, I>>(base?: I): T;
|
|
57
|
+
fromPartial<I extends Exact$5<DeepPartial$5<T>, I>>(object: I): T;
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
4
60
|
//#region src/proto/confidence/flags/resolver/v1/types.d.ts
|
|
5
|
-
|
|
61
|
+
declare enum ResolveReason {
|
|
62
|
+
/** RESOLVE_REASON_UNSPECIFIED - Unspecified enum. */
|
|
63
|
+
RESOLVE_REASON_UNSPECIFIED = 0,
|
|
64
|
+
/** RESOLVE_REASON_MATCH - The flag was successfully resolved because one rule matched. */
|
|
65
|
+
RESOLVE_REASON_MATCH = 1,
|
|
66
|
+
/** RESOLVE_REASON_NO_SEGMENT_MATCH - The flag could not be resolved because no rule matched. */
|
|
67
|
+
RESOLVE_REASON_NO_SEGMENT_MATCH = 2,
|
|
68
|
+
/**
|
|
69
|
+
* RESOLVE_REASON_NO_TREATMENT_MATCH - The flag could not be resolved because the matching rule had no variant
|
|
70
|
+
* that could be assigned.
|
|
71
|
+
*
|
|
72
|
+
* @deprecated
|
|
73
|
+
*/
|
|
74
|
+
RESOLVE_REASON_NO_TREATMENT_MATCH = 3,
|
|
75
|
+
/** RESOLVE_REASON_FLAG_ARCHIVED - The flag could not be resolved because it was archived. */
|
|
76
|
+
RESOLVE_REASON_FLAG_ARCHIVED = 4,
|
|
77
|
+
/** RESOLVE_REASON_TARGETING_KEY_ERROR - The flag could not be resolved because the targeting key field was invalid */
|
|
78
|
+
RESOLVE_REASON_TARGETING_KEY_ERROR = 5,
|
|
79
|
+
/** RESOLVE_REASON_ERROR - Unknown error occurred during the resolve */
|
|
80
|
+
RESOLVE_REASON_ERROR = 6,
|
|
81
|
+
UNRECOGNIZED = -1,
|
|
82
|
+
}
|
|
6
83
|
declare enum SdkId {
|
|
7
84
|
SDK_ID_UNSPECIFIED = 0,
|
|
8
85
|
SDK_ID_JAVA_PROVIDER = 1,
|
|
@@ -29,10 +106,6 @@ declare enum SdkId {
|
|
|
29
106
|
SDK_ID_JS_LOCAL_SERVER_PROVIDER = 22,
|
|
30
107
|
UNRECOGNIZED = -1,
|
|
31
108
|
}
|
|
32
|
-
/**
|
|
33
|
-
* (-- api-linter: core::0123::resource-annotation=disabled
|
|
34
|
-
* aip.dev/not-precedent: SDKs are not internal Confidence resources. --)
|
|
35
|
-
*/
|
|
36
109
|
interface Sdk {
|
|
37
110
|
/** Name of a Confidence SDKs. */
|
|
38
111
|
id?: SdkId | undefined;
|
|
@@ -41,45 +114,21 @@ interface Sdk {
|
|
|
41
114
|
/** Version of the SDK. */
|
|
42
115
|
version: string;
|
|
43
116
|
}
|
|
44
|
-
declare const Sdk: MessageFns$
|
|
45
|
-
type Builtin$
|
|
46
|
-
type DeepPartial$
|
|
47
|
-
type KeysOfUnion$
|
|
48
|
-
type Exact$
|
|
49
|
-
interface MessageFns$
|
|
117
|
+
declare const Sdk: MessageFns$4<Sdk>;
|
|
118
|
+
type Builtin$4 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
119
|
+
type DeepPartial$4<T> = T extends Builtin$4 ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial$4<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial$4<U>> : T extends {} ? { [K in keyof T]?: DeepPartial$4<T[K]> } : Partial<T>;
|
|
120
|
+
type KeysOfUnion$4<T> = T extends T ? keyof T : never;
|
|
121
|
+
type Exact$4<P, I extends P> = P extends Builtin$4 ? P : P & { [K in keyof P]: Exact$4<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion$4<P>>]: never };
|
|
122
|
+
interface MessageFns$4<T> {
|
|
50
123
|
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
|
51
124
|
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
|
52
125
|
fromJSON(object: any): T;
|
|
53
126
|
toJSON(message: T): unknown;
|
|
54
|
-
create<I extends Exact$
|
|
55
|
-
fromPartial<I extends Exact$
|
|
56
|
-
}
|
|
57
|
-
//#endregion
|
|
58
|
-
//#region src/proto/types.d.ts
|
|
59
|
-
declare enum ResolveReason {
|
|
60
|
-
/** RESOLVE_REASON_UNSPECIFIED - Unspecified enum. */
|
|
61
|
-
RESOLVE_REASON_UNSPECIFIED = 0,
|
|
62
|
-
/** RESOLVE_REASON_MATCH - The flag was successfully resolved because one rule matched. */
|
|
63
|
-
RESOLVE_REASON_MATCH = 1,
|
|
64
|
-
/** RESOLVE_REASON_NO_SEGMENT_MATCH - The flag could not be resolved because no rule matched. */
|
|
65
|
-
RESOLVE_REASON_NO_SEGMENT_MATCH = 2,
|
|
66
|
-
/**
|
|
67
|
-
* RESOLVE_REASON_NO_TREATMENT_MATCH - The flag could not be resolved because the matching rule had no variant
|
|
68
|
-
* that could be assigned.
|
|
69
|
-
*
|
|
70
|
-
* @deprecated
|
|
71
|
-
*/
|
|
72
|
-
RESOLVE_REASON_NO_TREATMENT_MATCH = 3,
|
|
73
|
-
/** RESOLVE_REASON_FLAG_ARCHIVED - The flag could not be resolved because it was archived. */
|
|
74
|
-
RESOLVE_REASON_FLAG_ARCHIVED = 4,
|
|
75
|
-
/** RESOLVE_REASON_TARGETING_KEY_ERROR - The flag could not be resolved because the targeting key field was invalid */
|
|
76
|
-
RESOLVE_REASON_TARGETING_KEY_ERROR = 5,
|
|
77
|
-
/** RESOLVE_REASON_ERROR - Unknown error occurred during the resolve */
|
|
78
|
-
RESOLVE_REASON_ERROR = 6,
|
|
79
|
-
UNRECOGNIZED = -1,
|
|
127
|
+
create<I extends Exact$4<DeepPartial$4<T>, I>>(base?: I): T;
|
|
128
|
+
fromPartial<I extends Exact$4<DeepPartial$4<T>, I>>(object: I): T;
|
|
80
129
|
}
|
|
81
130
|
//#endregion
|
|
82
|
-
//#region src/proto/resolver/api.d.ts
|
|
131
|
+
//#region src/proto/confidence/flags/resolver/v1/api.d.ts
|
|
83
132
|
interface ResolveFlagsRequest {
|
|
84
133
|
/**
|
|
85
134
|
* If non-empty, the specific flags are resolved, otherwise all flags
|
|
@@ -104,6 +153,7 @@ interface ResolveFlagsRequest {
|
|
|
104
153
|
* resolve, or delayed until `ApplyFlag` is called. A flag is typically
|
|
105
154
|
* applied when it is used, if this occurs much later than the resolve, then
|
|
106
155
|
* `apply` should likely be set to false.
|
|
156
|
+
* In a local resolve case it is encouraged to set this to `true`
|
|
107
157
|
*/
|
|
108
158
|
apply: boolean;
|
|
109
159
|
/** Information about the SDK used to initiate the request. */
|
|
@@ -135,79 +185,105 @@ interface ResolvedFlag {
|
|
|
135
185
|
value?: {
|
|
136
186
|
[key: string]: any;
|
|
137
187
|
} | undefined;
|
|
188
|
+
/** The schema of the value that was returned. */
|
|
189
|
+
flagSchema?: FlagSchema_StructFlagSchema | undefined;
|
|
138
190
|
/** The reason to why the flag could be resolved or not. */
|
|
139
191
|
reason: ResolveReason;
|
|
140
192
|
}
|
|
193
|
+
declare const ResolveFlagsRequest: MessageFns$3<ResolveFlagsRequest>;
|
|
194
|
+
declare const ResolveFlagsResponse: MessageFns$3<ResolveFlagsResponse>;
|
|
195
|
+
declare const ResolvedFlag: MessageFns$3<ResolvedFlag>;
|
|
196
|
+
type Builtin$3 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
197
|
+
type DeepPartial$3<T> = T extends Builtin$3 ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial$3<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial$3<U>> : T extends {} ? { [K in keyof T]?: DeepPartial$3<T[K]> } : Partial<T>;
|
|
198
|
+
type KeysOfUnion$3<T> = T extends T ? keyof T : never;
|
|
199
|
+
type Exact$3<P, I extends P> = P extends Builtin$3 ? P : P & { [K in keyof P]: Exact$3<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion$3<P>>]: never };
|
|
200
|
+
interface MessageFns$3<T> {
|
|
201
|
+
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
|
202
|
+
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
|
203
|
+
fromJSON(object: any): T;
|
|
204
|
+
toJSON(message: T): unknown;
|
|
205
|
+
create<I extends Exact$3<DeepPartial$3<T>, I>>(base?: I): T;
|
|
206
|
+
fromPartial<I extends Exact$3<DeepPartial$3<T>, I>>(object: I): T;
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/proto/confidence/flags/resolver/v1/internal_api.d.ts
|
|
210
|
+
interface VariantReadOp {
|
|
211
|
+
unit: string;
|
|
212
|
+
materialization: string;
|
|
213
|
+
rule: string;
|
|
214
|
+
}
|
|
215
|
+
interface InclusionReadOp {
|
|
216
|
+
unit: string;
|
|
217
|
+
materialization: string;
|
|
218
|
+
}
|
|
219
|
+
interface ReadOp$1 {
|
|
220
|
+
variantReadOp?: VariantReadOp | undefined;
|
|
221
|
+
inclusionReadOp?: InclusionReadOp | undefined;
|
|
222
|
+
}
|
|
223
|
+
interface ReadOperationsRequest {
|
|
224
|
+
ops: ReadOp$1[];
|
|
225
|
+
}
|
|
226
|
+
interface VariantData {
|
|
227
|
+
unit: string;
|
|
228
|
+
materialization: string;
|
|
229
|
+
rule: string;
|
|
230
|
+
variant: string;
|
|
231
|
+
}
|
|
232
|
+
interface InclusionData {
|
|
233
|
+
unit: string;
|
|
234
|
+
materialization: string;
|
|
235
|
+
isIncluded: boolean;
|
|
236
|
+
}
|
|
237
|
+
interface ReadResult {
|
|
238
|
+
variantResult?: VariantData | undefined;
|
|
239
|
+
inclusionResult?: InclusionData | undefined;
|
|
240
|
+
}
|
|
241
|
+
declare const VariantReadOp: MessageFns$2<VariantReadOp>;
|
|
242
|
+
declare const InclusionReadOp: MessageFns$2<InclusionReadOp>;
|
|
243
|
+
declare const ReadOp$1: MessageFns$2<ReadOp$1>;
|
|
244
|
+
declare const ReadOperationsRequest: MessageFns$2<ReadOperationsRequest>;
|
|
245
|
+
declare const VariantData: MessageFns$2<VariantData>;
|
|
246
|
+
declare const InclusionData: MessageFns$2<InclusionData>;
|
|
247
|
+
declare const ReadResult: MessageFns$2<ReadResult>;
|
|
248
|
+
type Builtin$2 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
249
|
+
type DeepPartial$2<T> = T extends Builtin$2 ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial$2<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial$2<U>> : T extends {} ? { [K in keyof T]?: DeepPartial$2<T[K]> } : Partial<T>;
|
|
250
|
+
type KeysOfUnion$2<T> = T extends T ? keyof T : never;
|
|
251
|
+
type Exact$2<P, I extends P> = P extends Builtin$2 ? P : P & { [K in keyof P]: Exact$2<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion$2<P>>]: never };
|
|
252
|
+
interface MessageFns$2<T> {
|
|
253
|
+
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
|
254
|
+
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
|
255
|
+
fromJSON(object: any): T;
|
|
256
|
+
toJSON(message: T): unknown;
|
|
257
|
+
create<I extends Exact$2<DeepPartial$2<T>, I>>(base?: I): T;
|
|
258
|
+
fromPartial<I extends Exact$2<DeepPartial$2<T>, I>>(object: I): T;
|
|
259
|
+
}
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region src/proto/confidence/wasm/wasm_api.d.ts
|
|
141
262
|
/** Request for resolving flags with sticky (materialized) assignments */
|
|
142
263
|
interface ResolveWithStickyRequest {
|
|
143
264
|
/** The standard resolve request */
|
|
144
265
|
resolveRequest?: ResolveFlagsRequest | undefined;
|
|
145
|
-
/**
|
|
146
|
-
* Context about the materialization required for the resolve
|
|
147
|
-
* Map of targeting key (unit) to their materialization data
|
|
148
|
-
*/
|
|
149
|
-
materializationsPerUnit: {
|
|
150
|
-
[key: string]: MaterializationMap;
|
|
151
|
-
};
|
|
152
|
-
/** If a materialization info is missing, return to the caller immediately */
|
|
266
|
+
/** if a materialization info is missing, we want tor return to the caller immediately */
|
|
153
267
|
failFastOnSticky: boolean;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
infoMap: {
|
|
159
|
-
[key: string]: MaterializationInfo;
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
/** Information about a materialization for a specific unit */
|
|
163
|
-
interface MaterializationInfo {
|
|
164
|
-
/** Whether the unit is in this materialization/rollout */
|
|
165
|
-
unitInInfo: boolean;
|
|
166
|
-
/** Map of rule name to variant name for this unit */
|
|
167
|
-
ruleToVariant: {
|
|
168
|
-
[key: string]: string;
|
|
169
|
-
};
|
|
268
|
+
/** if we should support sticky or completely skip the flag if they had sticky rules */
|
|
269
|
+
notProcessSticky: boolean;
|
|
270
|
+
/** Context about the materialization required for the resolve */
|
|
271
|
+
materializations: ReadResult[];
|
|
170
272
|
}
|
|
171
273
|
/** Response from resolving with sticky assignments */
|
|
172
274
|
interface ResolveWithStickyResponse {
|
|
173
275
|
success?: ResolveWithStickyResponse_Success | undefined;
|
|
174
|
-
|
|
276
|
+
readOpsRequest?: ReadOperationsRequest | undefined;
|
|
175
277
|
}
|
|
176
278
|
/** Successful resolution with materialization updates */
|
|
177
279
|
interface ResolveWithStickyResponse_Success {
|
|
178
|
-
/** The resolved flags response */
|
|
179
280
|
response?: ResolveFlagsResponse | undefined;
|
|
180
281
|
/** New assignments that should be stored */
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
/** Information about missing materializations */
|
|
184
|
-
interface ResolveWithStickyResponse_MissingMaterializations {
|
|
185
|
-
items: ResolveWithStickyResponse_MissingMaterializationItem[];
|
|
186
|
-
}
|
|
187
|
-
/** A missing materialization item */
|
|
188
|
-
interface ResolveWithStickyResponse_MissingMaterializationItem {
|
|
189
|
-
unit: string;
|
|
190
|
-
rule: string;
|
|
191
|
-
readMaterialization: string;
|
|
192
|
-
}
|
|
193
|
-
/** A materialization update to be stored */
|
|
194
|
-
interface ResolveWithStickyResponse_MaterializationUpdate {
|
|
195
|
-
unit: string;
|
|
196
|
-
writeMaterialization: string;
|
|
197
|
-
rule: string;
|
|
198
|
-
variant: string;
|
|
282
|
+
materializationUpdates: VariantData[];
|
|
199
283
|
}
|
|
200
|
-
declare const ResolveFlagsRequest: MessageFns$1<ResolveFlagsRequest>;
|
|
201
|
-
declare const ResolveFlagsResponse: MessageFns$1<ResolveFlagsResponse>;
|
|
202
|
-
declare const ResolvedFlag: MessageFns$1<ResolvedFlag>;
|
|
203
284
|
declare const ResolveWithStickyRequest: MessageFns$1<ResolveWithStickyRequest>;
|
|
204
|
-
declare const MaterializationMap: MessageFns$1<MaterializationMap>;
|
|
205
|
-
declare const MaterializationInfo: MessageFns$1<MaterializationInfo>;
|
|
206
285
|
declare const ResolveWithStickyResponse: MessageFns$1<ResolveWithStickyResponse>;
|
|
207
286
|
declare const ResolveWithStickyResponse_Success: MessageFns$1<ResolveWithStickyResponse_Success>;
|
|
208
|
-
declare const ResolveWithStickyResponse_MissingMaterializations: MessageFns$1<ResolveWithStickyResponse_MissingMaterializations>;
|
|
209
|
-
declare const ResolveWithStickyResponse_MissingMaterializationItem: MessageFns$1<ResolveWithStickyResponse_MissingMaterializationItem>;
|
|
210
|
-
declare const ResolveWithStickyResponse_MaterializationUpdate: MessageFns$1<ResolveWithStickyResponse_MaterializationUpdate>;
|
|
211
287
|
type Builtin$1 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
212
288
|
type DeepPartial$1<T> = T extends Builtin$1 ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial$1<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial$1<U>> : T extends {} ? { [K in keyof T]?: DeepPartial$1<T[K]> } : Partial<T>;
|
|
213
289
|
type KeysOfUnion$1<T> = T extends T ? keyof T : never;
|
|
@@ -221,7 +297,7 @@ interface MessageFns$1<T> {
|
|
|
221
297
|
fromPartial<I extends Exact$1<DeepPartial$1<T>, I>>(object: I): T;
|
|
222
298
|
}
|
|
223
299
|
//#endregion
|
|
224
|
-
//#region src/proto/messages.d.ts
|
|
300
|
+
//#region src/proto/confidence/wasm/messages.d.ts
|
|
225
301
|
interface SetResolverStateRequest {
|
|
226
302
|
state: Uint8Array;
|
|
227
303
|
accountId: string;
|
|
@@ -248,12 +324,87 @@ interface LocalResolver {
|
|
|
248
324
|
flushAssigned(): Uint8Array;
|
|
249
325
|
}
|
|
250
326
|
//#endregion
|
|
327
|
+
//#region src/materialization.d.ts
|
|
328
|
+
declare namespace MaterializationStore {
|
|
329
|
+
namespace ReadOp {
|
|
330
|
+
interface Variant {
|
|
331
|
+
readonly op: "variant";
|
|
332
|
+
readonly unit: string;
|
|
333
|
+
readonly materialization: string;
|
|
334
|
+
readonly rule: string;
|
|
335
|
+
}
|
|
336
|
+
interface Inclusion {
|
|
337
|
+
readonly op: "inclusion";
|
|
338
|
+
readonly unit: string;
|
|
339
|
+
readonly materialization: string;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
type ReadOp = ReadOp.Variant | ReadOp.Inclusion;
|
|
343
|
+
namespace ReadResult {
|
|
344
|
+
interface Variant {
|
|
345
|
+
readonly op: "variant";
|
|
346
|
+
readonly unit: string;
|
|
347
|
+
readonly materialization: string;
|
|
348
|
+
readonly rule: string;
|
|
349
|
+
readonly variant?: string;
|
|
350
|
+
}
|
|
351
|
+
interface Inclusion {
|
|
352
|
+
readonly op: "inclusion";
|
|
353
|
+
readonly unit: string;
|
|
354
|
+
readonly materialization: string;
|
|
355
|
+
readonly included: boolean;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
type ReadResult = ReadResult.Inclusion | ReadResult.Variant;
|
|
359
|
+
namespace WriteOp {
|
|
360
|
+
interface Variant {
|
|
361
|
+
readonly op: "variant";
|
|
362
|
+
readonly unit: string;
|
|
363
|
+
readonly materialization: string;
|
|
364
|
+
readonly rule: string;
|
|
365
|
+
readonly variant: string;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
type WriteOp = WriteOp.Variant;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Interface for storing and retrieving materialization data.
|
|
372
|
+
*
|
|
373
|
+
* Implementations can use any storage backend (e.g., Redis, BigTable, Cassandra, DynamoDB,
|
|
374
|
+
* or simple key-value stores) as long as they fulfill this contract.
|
|
375
|
+
*
|
|
376
|
+
* @see The README for conceptual documentation on sticky assignments and materialized segments.
|
|
377
|
+
*/
|
|
378
|
+
interface MaterializationStore {
|
|
379
|
+
/**
|
|
380
|
+
* Reads materialization data for the given operations.
|
|
381
|
+
*
|
|
382
|
+
* For `variant` operations, returns the stored variant assignment (if any) for a unit/materialization/rule combination.
|
|
383
|
+
* For `inclusion` operations, returns whether a unit is included in a materialized segment.
|
|
384
|
+
*
|
|
385
|
+
* @param readOps - The read operations to perform.
|
|
386
|
+
* @returns Results for each operation. The order of results does not need to match the order of operations;
|
|
387
|
+
* callers match results to operations using the `unit`, `materialization`, and `op` fields.
|
|
388
|
+
*/
|
|
389
|
+
readMaterializations(readOps: MaterializationStore.ReadOp[]): Promise<MaterializationStore.ReadResult[]>;
|
|
390
|
+
/**
|
|
391
|
+
* Persists variant assignments for sticky bucketing.
|
|
392
|
+
*
|
|
393
|
+
* This method is optional. Omit it for read-only stores that only serve pre-populated
|
|
394
|
+
* materialized segments without supporting runtime sticky assignment writes.
|
|
395
|
+
*
|
|
396
|
+
* @param writeOps - The variant assignments to persist.
|
|
397
|
+
*/
|
|
398
|
+
writeMaterializations?(writeOps: MaterializationStore.WriteOp[]): Promise<void>;
|
|
399
|
+
}
|
|
400
|
+
//#endregion
|
|
251
401
|
//#region src/ConfidenceServerProviderLocal.d.ts
|
|
252
402
|
interface ProviderOptions {
|
|
253
403
|
flagClientSecret: string;
|
|
254
404
|
initializeTimeout?: number;
|
|
255
405
|
flushInterval?: number;
|
|
256
406
|
fetch?: typeof fetch;
|
|
407
|
+
materializationStore?: MaterializationStore | "CONFIDENCE_REMOTE_STORE";
|
|
257
408
|
}
|
|
258
409
|
/**
|
|
259
410
|
* OpenFeature Provider for Confidence Server SDK (Local Mode)
|
|
@@ -269,18 +420,13 @@ declare class ConfidenceServerProviderLocal implements Provider {
|
|
|
269
420
|
private readonly main;
|
|
270
421
|
private readonly fetch;
|
|
271
422
|
private readonly flushInterval;
|
|
423
|
+
private readonly materializationStore;
|
|
272
424
|
private stateEtag;
|
|
273
425
|
constructor(resolver: LocalResolver, options: ProviderOptions);
|
|
274
426
|
initialize(context?: EvaluationContext): Promise<void>;
|
|
275
427
|
onClose(): Promise<void>;
|
|
276
428
|
evaluate<T>(flagKey: string, defaultValue: T, context: EvaluationContext): Promise<ResolutionDetails<T>>;
|
|
277
|
-
|
|
278
|
-
* Internal recursive method for resolving with sticky assignments.
|
|
279
|
-
*
|
|
280
|
-
* @private
|
|
281
|
-
*/
|
|
282
|
-
private resolveWithStickyInternal;
|
|
283
|
-
private remoteResolve;
|
|
429
|
+
private resolveWithSticky;
|
|
284
430
|
/**
|
|
285
431
|
* Extract and validate the value from a resolved flag.
|
|
286
432
|
*/
|
|
@@ -289,6 +435,8 @@ declare class ConfidenceServerProviderLocal implements Provider {
|
|
|
289
435
|
flush(signal?: AbortSignal): Promise<void>;
|
|
290
436
|
private flushAssigned;
|
|
291
437
|
private sendFlagLogs;
|
|
438
|
+
private readMaterializations;
|
|
439
|
+
private writeMaterializations;
|
|
292
440
|
private static convertReason;
|
|
293
441
|
private static convertEvaluationContext;
|
|
294
442
|
/** Resolves with an evaluation of a Boolean flag */
|
|
@@ -304,4 +452,4 @@ declare class ConfidenceServerProviderLocal implements Provider {
|
|
|
304
452
|
//#region src/index.browser.d.ts
|
|
305
453
|
declare function createConfidenceServerProvider(options: ProviderOptions): ConfidenceServerProviderLocal;
|
|
306
454
|
//#endregion
|
|
307
|
-
export { createConfidenceServerProvider };
|
|
455
|
+
export { type MaterializationStore, createConfidenceServerProvider };
|