@spotify-confidence/openfeature-server-provider-local 0.10.0 → 0.11.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 +30 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +10 -0
- package/dist/confidence_resolver.wasm +0 -0
- package/dist/index.fetch.d.ts +26 -2
- package/dist/index.fetch.js +235 -6
- package/dist/index.inlined.d.ts +26 -2
- package/dist/index.inlined.js +236 -7
- package/dist/index.node.d.ts +26 -2
- package/dist/index.node.js +235 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.0](https://github.com/spotify/confidence-resolver/compare/openfeature-provider-js-v0.10.1...openfeature-provider-js-v0.11.0) (2026-03-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add register_resolve WASM export for SDK-side telemetry ([#354](https://github.com/spotify/confidence-resolver/issues/354)) ([31499bc](https://github.com/spotify/confidence-resolver/commit/31499bc911942ecd751b4a4a702f35ded41e9776))
|
|
9
|
+
* add resolver_version field to TelemetryData ([#346](https://github.com/spotify/confidence-resolver/issues/346)) ([10ab1c6](https://github.com/spotify/confidence-resolver/commit/10ab1c657cb830dc36f433d1dca0af73beecaa27))
|
|
10
|
+
* local prometheus sdk metrics ([#322](https://github.com/spotify/confidence-resolver/issues/322)) ([8b18119](https://github.com/spotify/confidence-resolver/commit/8b18119eae449afbe4a0815e8aab5f82888a8621))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
* The following workspace dependencies were updated
|
|
16
|
+
* dependencies
|
|
17
|
+
* rust-guest bumped from 0.1.19 to 0.1.20
|
|
18
|
+
|
|
19
|
+
## [0.10.1](https://github.com/spotify/confidence-resolver/compare/openfeature-provider-js-v0.10.0...openfeature-provider-js-v0.10.1) (2026-03-12)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* pass the sdk with the state to get it into telemetry ([#332](https://github.com/spotify/confidence-resolver/issues/332)) ([1f22c5f](https://github.com/spotify/confidence-resolver/commit/1f22c5fa38c4e8a7d56ea4616db94f9b991d41ab))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* rust-guest bumped from 0.1.18 to 0.1.19
|
|
32
|
+
|
|
3
33
|
## [0.10.0](https://github.com/spotify/confidence-resolver/compare/openfeature-provider-js-v0.9.1...openfeature-provider-js-v0.10.0) (2026-03-06)
|
|
4
34
|
|
|
5
35
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EvaluationDetails, FlagValue } from "@openfeature/core";
|
|
2
2
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
|
-
type ResolutionReason = "ERROR" | "FLAG_ARCHIVED" | "MATCH" | "NO_SEGMENT_MATCH" | "TARGETING_KEY_ERROR" | "NO_TREATMENT_MATCH" | "UNSPECIFIED";
|
|
4
|
+
type ResolutionReason = "ERROR" | "FLAG_ARCHIVED" | "MATCH" | "NO_SEGMENT_MATCH" | "TARGETING_KEY_ERROR" | "NO_TREATMENT_MATCH" | "MATERIALIZATION_NOT_SUPPORTED" | "UNSPECIFIED";
|
|
5
5
|
declare enum ErrorCode {
|
|
6
6
|
PROVIDER_NOT_READY = "PROVIDER_NOT_READY",
|
|
7
7
|
PROVIDER_FATAL = "PROVIDER_FATAL",
|
package/dist/client.js
CHANGED
|
@@ -92,6 +92,16 @@ function resolve(bundle, flagKey, defaultValue, logger$1) {
|
|
|
92
92
|
shouldApply: false
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
|
+
if (flag.reason === "MATERIALIZATION_NOT_SUPPORTED") {
|
|
96
|
+
logger$1?.warn("Flag '%s' requires materializations but no materialization store is configured. Pass a MaterializationStore implementation or: 'CONFIDENCE_REMOTE_STORE' to createConfidenceServerProvider()", flagName);
|
|
97
|
+
return {
|
|
98
|
+
reason: "ERROR",
|
|
99
|
+
errorCode: ErrorCode.GENERAL,
|
|
100
|
+
errorMessage: `Flag '${flagName}' requires materializations. Configure a materialization store.`,
|
|
101
|
+
value: defaultValue,
|
|
102
|
+
shouldApply: false
|
|
103
|
+
};
|
|
104
|
+
}
|
|
95
105
|
let value = flag.value;
|
|
96
106
|
for (let i = 0; i < path.length; i++) {
|
|
97
107
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return {
|
|
Binary file
|
package/dist/index.fetch.d.ts
CHANGED
|
@@ -82,6 +82,10 @@ declare enum ResolveReason {
|
|
|
82
82
|
RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE = 7,
|
|
83
83
|
/** RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED - The flag could not be resolved because a rule is using materialization */
|
|
84
84
|
RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED = 8,
|
|
85
|
+
/** RESOLVE_REASON_TYPE_MISMATCH - The resolved value type does not match the type requested by the SDK */
|
|
86
|
+
RESOLVE_REASON_TYPE_MISMATCH = 9,
|
|
87
|
+
/** RESOLVE_REASON_FLAG_NOT_FOUND - The flag was not found in the resolve response */
|
|
88
|
+
RESOLVE_REASON_FLAG_NOT_FOUND = 10,
|
|
85
89
|
UNRECOGNIZED = -1,
|
|
86
90
|
}
|
|
87
91
|
declare enum SdkId {
|
|
@@ -273,6 +277,10 @@ interface MaterializationRecord {
|
|
|
273
277
|
rule: string;
|
|
274
278
|
variant: string;
|
|
275
279
|
}
|
|
280
|
+
interface RegisterResolveRequest {
|
|
281
|
+
reason: ResolveReason;
|
|
282
|
+
latencyUs: number;
|
|
283
|
+
}
|
|
276
284
|
declare const ResolveProcessRequest: MessageFns$2<ResolveProcessRequest>;
|
|
277
285
|
declare const ResolveProcessRequest_StaticMaterializations: MessageFns$2<ResolveProcessRequest_StaticMaterializations>;
|
|
278
286
|
declare const ResolveProcessRequest_Resume: MessageFns$2<ResolveProcessRequest_Resume>;
|
|
@@ -280,6 +288,7 @@ declare const ResolveProcessResponse: MessageFns$2<ResolveProcessResponse>;
|
|
|
280
288
|
declare const ResolveProcessResponse_Resolved: MessageFns$2<ResolveProcessResponse_Resolved>;
|
|
281
289
|
declare const ResolveProcessResponse_Suspended: MessageFns$2<ResolveProcessResponse_Suspended>;
|
|
282
290
|
declare const MaterializationRecord: MessageFns$2<MaterializationRecord>;
|
|
291
|
+
declare const RegisterResolveRequest: MessageFns$2<RegisterResolveRequest>;
|
|
283
292
|
type Builtin$2 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
284
293
|
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>;
|
|
285
294
|
type KeysOfUnion$2<T> = T extends T ? keyof T : never;
|
|
@@ -297,6 +306,7 @@ interface MessageFns$2<T> {
|
|
|
297
306
|
interface SetResolverStateRequest {
|
|
298
307
|
state: Uint8Array;
|
|
299
308
|
accountId: string;
|
|
309
|
+
sdk?: Sdk | undefined;
|
|
300
310
|
}
|
|
301
311
|
declare const SetResolverStateRequest: MessageFns$1<SetResolverStateRequest>;
|
|
302
312
|
type Builtin$1 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
@@ -315,10 +325,12 @@ interface MessageFns$1<T> {
|
|
|
315
325
|
//#region src/LocalResolver.d.ts
|
|
316
326
|
interface LocalResolver {
|
|
317
327
|
resolveProcess(request: ResolveProcessRequest): ResolveProcessResponse;
|
|
328
|
+
registerResolve(request: RegisterResolveRequest): void;
|
|
318
329
|
setResolverState(request: SetResolverStateRequest): void;
|
|
319
330
|
flushLogs(): Uint8Array;
|
|
320
331
|
flushAssigned(): Uint8Array;
|
|
321
332
|
applyFlags(request: ApplyFlagsRequest): void;
|
|
333
|
+
prometheusSnapshot(instance: string): string;
|
|
322
334
|
}
|
|
323
335
|
//#endregion
|
|
324
336
|
//#region src/proto/confidence/flags/resolver/v1/internal_api.d.ts
|
|
@@ -428,7 +440,7 @@ interface MaterializationStore {
|
|
|
428
440
|
}
|
|
429
441
|
//#endregion
|
|
430
442
|
//#region src/types.d.ts
|
|
431
|
-
type ResolutionReason = "ERROR" | "FLAG_ARCHIVED" | "MATCH" | "NO_SEGMENT_MATCH" | "TARGETING_KEY_ERROR" | "NO_TREATMENT_MATCH" | "UNSPECIFIED";
|
|
443
|
+
type ResolutionReason = "ERROR" | "FLAG_ARCHIVED" | "MATCH" | "NO_SEGMENT_MATCH" | "TARGETING_KEY_ERROR" | "NO_TREATMENT_MATCH" | "MATERIALIZATION_NOT_SUPPORTED" | "UNSPECIFIED";
|
|
432
444
|
declare enum ErrorCode {
|
|
433
445
|
PROVIDER_NOT_READY = "PROVIDER_NOT_READY",
|
|
434
446
|
PROVIDER_FATAL = "PROVIDER_FATAL",
|
|
@@ -461,6 +473,12 @@ interface FlagBundle {
|
|
|
461
473
|
//#endregion
|
|
462
474
|
//#region src/ConfidenceServerProviderLocal.d.ts
|
|
463
475
|
type FlagBundle$1 = FlagBundle;
|
|
476
|
+
/**
|
|
477
|
+
* Configuration for {@link ConfidenceServerProviderLocal.getPrometheusMetrics}.
|
|
478
|
+
*
|
|
479
|
+
* @experimental This API is subject to change.
|
|
480
|
+
*/
|
|
481
|
+
interface SnapshotConfig {}
|
|
464
482
|
interface ProviderOptions {
|
|
465
483
|
flagClientSecret: string;
|
|
466
484
|
initializeTimeout?: number;
|
|
@@ -512,6 +530,12 @@ declare class ConfidenceServerProviderLocal implements Provider {
|
|
|
512
530
|
/** Resolves with an evaluation of a String flag */
|
|
513
531
|
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext): Promise<ResolutionDetails<string>>;
|
|
514
532
|
/**
|
|
533
|
+
* Returns a Prometheus metrics snapshot from the WASM resolver.
|
|
534
|
+
*
|
|
535
|
+
* @experimental This API is subject to change.
|
|
536
|
+
*/
|
|
537
|
+
getPrometheusMetrics(_request?: SnapshotConfig): string;
|
|
538
|
+
/**
|
|
515
539
|
* Applies a previously resolved flag, logging that it was used/exposed.
|
|
516
540
|
* Call this when a flag value is actually rendered or used in the client.
|
|
517
541
|
* @param resolveToken - Base64-encoded resolve token from the flag bundle
|
|
@@ -529,4 +553,4 @@ declare function createConfidenceServerProvider({
|
|
|
529
553
|
...options
|
|
530
554
|
}: ProviderOptionsExt): ConfidenceServerProviderLocal;
|
|
531
555
|
//#endregion
|
|
532
|
-
export { type MaterializationStore, ProviderOptionsExt, createConfidenceServerProvider };
|
|
556
|
+
export { type MaterializationStore, ProviderOptionsExt, type SnapshotConfig, createConfidenceServerProvider };
|
package/dist/index.fetch.js
CHANGED
|
@@ -774,6 +774,8 @@ let ResolveReason = /* @__PURE__ */ function(ResolveReason$1) {
|
|
|
774
774
|
ResolveReason$1[ResolveReason$1["RESOLVE_REASON_ERROR"] = 6] = "RESOLVE_REASON_ERROR";
|
|
775
775
|
ResolveReason$1[ResolveReason$1["RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE"] = 7] = "RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE";
|
|
776
776
|
ResolveReason$1[ResolveReason$1["RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED"] = 8] = "RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED";
|
|
777
|
+
ResolveReason$1[ResolveReason$1["RESOLVE_REASON_TYPE_MISMATCH"] = 9] = "RESOLVE_REASON_TYPE_MISMATCH";
|
|
778
|
+
ResolveReason$1[ResolveReason$1["RESOLVE_REASON_FLAG_NOT_FOUND"] = 10] = "RESOLVE_REASON_FLAG_NOT_FOUND";
|
|
777
779
|
ResolveReason$1[ResolveReason$1["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
|
778
780
|
return ResolveReason$1;
|
|
779
781
|
}({});
|
|
@@ -797,6 +799,10 @@ function resolveReasonFromJSON(object) {
|
|
|
797
799
|
case "RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE": return ResolveReason.RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE;
|
|
798
800
|
case 8:
|
|
799
801
|
case "RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED": return ResolveReason.RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED;
|
|
802
|
+
case 9:
|
|
803
|
+
case "RESOLVE_REASON_TYPE_MISMATCH": return ResolveReason.RESOLVE_REASON_TYPE_MISMATCH;
|
|
804
|
+
case 10:
|
|
805
|
+
case "RESOLVE_REASON_FLAG_NOT_FOUND": return ResolveReason.RESOLVE_REASON_FLAG_NOT_FOUND;
|
|
800
806
|
case -1:
|
|
801
807
|
case "UNRECOGNIZED":
|
|
802
808
|
default: return ResolveReason.UNRECOGNIZED;
|
|
@@ -813,6 +819,8 @@ function resolveReasonToJSON(object) {
|
|
|
813
819
|
case ResolveReason.RESOLVE_REASON_ERROR: return "RESOLVE_REASON_ERROR";
|
|
814
820
|
case ResolveReason.RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE: return "RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE";
|
|
815
821
|
case ResolveReason.RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED: return "RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED";
|
|
822
|
+
case ResolveReason.RESOLVE_REASON_TYPE_MISMATCH: return "RESOLVE_REASON_TYPE_MISMATCH";
|
|
823
|
+
case ResolveReason.RESOLVE_REASON_FLAG_NOT_FOUND: return "RESOLVE_REASON_FLAG_NOT_FOUND";
|
|
816
824
|
case ResolveReason.UNRECOGNIZED:
|
|
817
825
|
default: return "UNRECOGNIZED";
|
|
818
826
|
}
|
|
@@ -1410,7 +1418,7 @@ function isObject(value) {
|
|
|
1410
1418
|
function isSet$3(value) {
|
|
1411
1419
|
return value !== null && value !== void 0;
|
|
1412
1420
|
}
|
|
1413
|
-
const VERSION = "0.
|
|
1421
|
+
const VERSION = "0.11.0";
|
|
1414
1422
|
const NOOP_LOG_FN = Object.assign(() => {}, { enabled: false });
|
|
1415
1423
|
const debugBackend = loadDebug();
|
|
1416
1424
|
const logger$2 = new class LoggerImpl {
|
|
@@ -2392,13 +2400,15 @@ const Void = {
|
|
|
2392
2400
|
function createBaseSetResolverStateRequest() {
|
|
2393
2401
|
return {
|
|
2394
2402
|
state: new Uint8Array(0),
|
|
2395
|
-
accountId: ""
|
|
2403
|
+
accountId: "",
|
|
2404
|
+
sdk: void 0
|
|
2396
2405
|
};
|
|
2397
2406
|
}
|
|
2398
2407
|
const SetResolverStateRequest = {
|
|
2399
2408
|
encode(message, writer = new BinaryWriter()) {
|
|
2400
2409
|
if (message.state.length !== 0) writer.uint32(10).bytes(message.state);
|
|
2401
2410
|
if (message.accountId !== "") writer.uint32(18).string(message.accountId);
|
|
2411
|
+
if (message.sdk !== void 0) Sdk.encode(message.sdk, writer.uint32(26).fork()).join();
|
|
2402
2412
|
return writer;
|
|
2403
2413
|
},
|
|
2404
2414
|
decode(input, length) {
|
|
@@ -2416,6 +2426,10 @@ const SetResolverStateRequest = {
|
|
|
2416
2426
|
if (tag !== 18) break;
|
|
2417
2427
|
message.accountId = reader.string();
|
|
2418
2428
|
continue;
|
|
2429
|
+
case 3:
|
|
2430
|
+
if (tag !== 26) break;
|
|
2431
|
+
message.sdk = Sdk.decode(reader, reader.uint32());
|
|
2432
|
+
continue;
|
|
2419
2433
|
}
|
|
2420
2434
|
if ((tag & 7) === 4 || tag === 0) break;
|
|
2421
2435
|
reader.skip(tag & 7);
|
|
@@ -2425,13 +2439,15 @@ const SetResolverStateRequest = {
|
|
|
2425
2439
|
fromJSON(object) {
|
|
2426
2440
|
return {
|
|
2427
2441
|
state: isSet$1(object.state) ? bytesFromBase64$2(object.state) : new Uint8Array(0),
|
|
2428
|
-
accountId: isSet$1(object.accountId) ? globalThis.String(object.accountId) : ""
|
|
2442
|
+
accountId: isSet$1(object.accountId) ? globalThis.String(object.accountId) : "",
|
|
2443
|
+
sdk: isSet$1(object.sdk) ? Sdk.fromJSON(object.sdk) : void 0
|
|
2429
2444
|
};
|
|
2430
2445
|
},
|
|
2431
2446
|
toJSON(message) {
|
|
2432
2447
|
const obj = {};
|
|
2433
2448
|
if (message.state.length !== 0) obj.state = base64FromBytes$2(message.state);
|
|
2434
2449
|
if (message.accountId !== "") obj.accountId = message.accountId;
|
|
2450
|
+
if (message.sdk !== void 0) obj.sdk = Sdk.toJSON(message.sdk);
|
|
2435
2451
|
return obj;
|
|
2436
2452
|
},
|
|
2437
2453
|
create(base) {
|
|
@@ -2441,6 +2457,7 @@ const SetResolverStateRequest = {
|
|
|
2441
2457
|
const message = createBaseSetResolverStateRequest();
|
|
2442
2458
|
message.state = object.state ?? new Uint8Array(0);
|
|
2443
2459
|
message.accountId = object.accountId ?? "";
|
|
2460
|
+
message.sdk = object.sdk !== void 0 && object.sdk !== null ? Sdk.fromPartial(object.sdk) : void 0;
|
|
2444
2461
|
return message;
|
|
2445
2462
|
}
|
|
2446
2463
|
};
|
|
@@ -2541,6 +2558,90 @@ const Response$1 = {
|
|
|
2541
2558
|
return message;
|
|
2542
2559
|
}
|
|
2543
2560
|
};
|
|
2561
|
+
function createBasePrometheusSnapshotRequest() {
|
|
2562
|
+
return { instance: "" };
|
|
2563
|
+
}
|
|
2564
|
+
const PrometheusSnapshotRequest = {
|
|
2565
|
+
encode(message, writer = new BinaryWriter()) {
|
|
2566
|
+
if (message.instance !== "") writer.uint32(10).string(message.instance);
|
|
2567
|
+
return writer;
|
|
2568
|
+
},
|
|
2569
|
+
decode(input, length) {
|
|
2570
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
2571
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
2572
|
+
const message = createBasePrometheusSnapshotRequest();
|
|
2573
|
+
while (reader.pos < end) {
|
|
2574
|
+
const tag = reader.uint32();
|
|
2575
|
+
switch (tag >>> 3) {
|
|
2576
|
+
case 1:
|
|
2577
|
+
if (tag !== 10) break;
|
|
2578
|
+
message.instance = reader.string();
|
|
2579
|
+
continue;
|
|
2580
|
+
}
|
|
2581
|
+
if ((tag & 7) === 4 || tag === 0) break;
|
|
2582
|
+
reader.skip(tag & 7);
|
|
2583
|
+
}
|
|
2584
|
+
return message;
|
|
2585
|
+
},
|
|
2586
|
+
fromJSON(object) {
|
|
2587
|
+
return { instance: isSet$1(object.instance) ? globalThis.String(object.instance) : "" };
|
|
2588
|
+
},
|
|
2589
|
+
toJSON(message) {
|
|
2590
|
+
const obj = {};
|
|
2591
|
+
if (message.instance !== "") obj.instance = message.instance;
|
|
2592
|
+
return obj;
|
|
2593
|
+
},
|
|
2594
|
+
create(base) {
|
|
2595
|
+
return PrometheusSnapshotRequest.fromPartial(base ?? {});
|
|
2596
|
+
},
|
|
2597
|
+
fromPartial(object) {
|
|
2598
|
+
const message = createBasePrometheusSnapshotRequest();
|
|
2599
|
+
message.instance = object.instance ?? "";
|
|
2600
|
+
return message;
|
|
2601
|
+
}
|
|
2602
|
+
};
|
|
2603
|
+
function createBasePrometheusSnapshotResponse() {
|
|
2604
|
+
return { text: "" };
|
|
2605
|
+
}
|
|
2606
|
+
const PrometheusSnapshotResponse = {
|
|
2607
|
+
encode(message, writer = new BinaryWriter()) {
|
|
2608
|
+
if (message.text !== "") writer.uint32(10).string(message.text);
|
|
2609
|
+
return writer;
|
|
2610
|
+
},
|
|
2611
|
+
decode(input, length) {
|
|
2612
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
2613
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
2614
|
+
const message = createBasePrometheusSnapshotResponse();
|
|
2615
|
+
while (reader.pos < end) {
|
|
2616
|
+
const tag = reader.uint32();
|
|
2617
|
+
switch (tag >>> 3) {
|
|
2618
|
+
case 1:
|
|
2619
|
+
if (tag !== 10) break;
|
|
2620
|
+
message.text = reader.string();
|
|
2621
|
+
continue;
|
|
2622
|
+
}
|
|
2623
|
+
if ((tag & 7) === 4 || tag === 0) break;
|
|
2624
|
+
reader.skip(tag & 7);
|
|
2625
|
+
}
|
|
2626
|
+
return message;
|
|
2627
|
+
},
|
|
2628
|
+
fromJSON(object) {
|
|
2629
|
+
return { text: isSet$1(object.text) ? globalThis.String(object.text) : "" };
|
|
2630
|
+
},
|
|
2631
|
+
toJSON(message) {
|
|
2632
|
+
const obj = {};
|
|
2633
|
+
if (message.text !== "") obj.text = message.text;
|
|
2634
|
+
return obj;
|
|
2635
|
+
},
|
|
2636
|
+
create(base) {
|
|
2637
|
+
return PrometheusSnapshotResponse.fromPartial(base ?? {});
|
|
2638
|
+
},
|
|
2639
|
+
fromPartial(object) {
|
|
2640
|
+
const message = createBasePrometheusSnapshotResponse();
|
|
2641
|
+
message.text = object.text ?? "";
|
|
2642
|
+
return message;
|
|
2643
|
+
}
|
|
2644
|
+
};
|
|
2544
2645
|
function bytesFromBase64$2(b64) {
|
|
2545
2646
|
if (globalThis.Buffer) return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
|
|
2546
2647
|
else {
|
|
@@ -2620,6 +2721,16 @@ function resolve(bundle, flagKey, defaultValue, logger$4) {
|
|
|
2620
2721
|
shouldApply: false
|
|
2621
2722
|
};
|
|
2622
2723
|
}
|
|
2724
|
+
if (flag.reason === "MATERIALIZATION_NOT_SUPPORTED") {
|
|
2725
|
+
logger$4?.warn("Flag '%s' requires materializations but no materialization store is configured. Pass a MaterializationStore implementation or: 'CONFIDENCE_REMOTE_STORE' to createConfidenceServerProvider()", flagName);
|
|
2726
|
+
return {
|
|
2727
|
+
reason: "ERROR",
|
|
2728
|
+
errorCode: ErrorCode.GENERAL,
|
|
2729
|
+
errorMessage: `Flag '${flagName}' requires materializations. Configure a materialization store.`,
|
|
2730
|
+
value: defaultValue,
|
|
2731
|
+
shouldApply: false
|
|
2732
|
+
};
|
|
2733
|
+
}
|
|
2623
2734
|
let value = flag.value;
|
|
2624
2735
|
for (let i = 0; i < path.length; i++) {
|
|
2625
2736
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return {
|
|
@@ -2673,6 +2784,7 @@ function convertReason(reason) {
|
|
|
2673
2784
|
case ResolveReason.RESOLVE_REASON_TARGETING_KEY_ERROR: return "TARGETING_KEY_ERROR";
|
|
2674
2785
|
case ResolveReason.RESOLVE_REASON_NO_TREATMENT_MATCH: return "NO_TREATMENT_MATCH";
|
|
2675
2786
|
case ResolveReason.RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE: return "ERROR";
|
|
2787
|
+
case ResolveReason.RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED: return "MATERIALIZATION_NOT_SUPPORTED";
|
|
2676
2788
|
default: return "UNSPECIFIED";
|
|
2677
2789
|
}
|
|
2678
2790
|
}
|
|
@@ -2768,10 +2880,28 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
|
|
|
2768
2880
|
}
|
|
2769
2881
|
}
|
|
2770
2882
|
async evaluate(flagKey, defaultValue, context) {
|
|
2883
|
+
const startMs = performance.now();
|
|
2771
2884
|
try {
|
|
2772
2885
|
const [flagName] = flagKey.split(".", 1);
|
|
2773
2886
|
const resolution = await this.resolve(context, [flagName], true);
|
|
2774
|
-
|
|
2887
|
+
const result = resolve(resolution, flagKey, defaultValue, logger$1);
|
|
2888
|
+
const latencyUs = Math.round((performance.now() - startMs) * 1e3);
|
|
2889
|
+
let reason;
|
|
2890
|
+
if (resolution.errorCode) reason = ResolveReason.RESOLVE_REASON_ERROR;
|
|
2891
|
+
else {
|
|
2892
|
+
const [flagNameForTelemetry] = flagKey.split(".", 1);
|
|
2893
|
+
if (resolution.flags[flagNameForTelemetry]?.reason === "MATERIALIZATION_NOT_SUPPORTED") reason = ResolveReason.RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED;
|
|
2894
|
+
else if (result.errorCode === ErrorCode.FLAG_NOT_FOUND) reason = ResolveReason.RESOLVE_REASON_FLAG_NOT_FOUND;
|
|
2895
|
+
else if (result.errorCode === ErrorCode.TYPE_MISMATCH) reason = ResolveReason.RESOLVE_REASON_TYPE_MISMATCH;
|
|
2896
|
+
else reason = reasonStringToEnum(result.reason);
|
|
2897
|
+
}
|
|
2898
|
+
try {
|
|
2899
|
+
this.resolver.registerResolve({
|
|
2900
|
+
reason,
|
|
2901
|
+
latencyUs
|
|
2902
|
+
});
|
|
2903
|
+
} catch {}
|
|
2904
|
+
return result;
|
|
2775
2905
|
} finally {
|
|
2776
2906
|
this.flushAssigned();
|
|
2777
2907
|
}
|
|
@@ -2813,7 +2943,12 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
|
|
|
2813
2943
|
if (!resp.ok) throw new Error(`Failed to fetch state: ${resp.status} ${resp.statusText}`);
|
|
2814
2944
|
this.stateEtag = resp.headers.get("etag");
|
|
2815
2945
|
const bytes = new Uint8Array(await resp.arrayBuffer());
|
|
2816
|
-
|
|
2946
|
+
const stateRequest = SetResolverStateRequest.decode(bytes);
|
|
2947
|
+
stateRequest.sdk = {
|
|
2948
|
+
id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER,
|
|
2949
|
+
version: VERSION
|
|
2950
|
+
};
|
|
2951
|
+
this.resolver.setResolverState(stateRequest);
|
|
2817
2952
|
}
|
|
2818
2953
|
async flush(signal) {
|
|
2819
2954
|
const writeFlagLogRequest = this.resolver.flushLogs();
|
|
@@ -2873,6 +3008,9 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
|
|
|
2873
3008
|
resolveStringEvaluation(flagKey, defaultValue, context) {
|
|
2874
3009
|
return Promise.resolve(this.evaluate(flagKey, defaultValue, context));
|
|
2875
3010
|
}
|
|
3011
|
+
getPrometheusMetrics(_request) {
|
|
3012
|
+
return this.resolver.prometheusSnapshot("0");
|
|
3013
|
+
}
|
|
2876
3014
|
applyFlag(resolveToken, flagName) {
|
|
2877
3015
|
const request = {
|
|
2878
3016
|
flags: [{
|
|
@@ -2890,6 +3028,17 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
|
|
|
2890
3028
|
this.resolver.applyFlags(request);
|
|
2891
3029
|
}
|
|
2892
3030
|
};
|
|
3031
|
+
function reasonStringToEnum(reason) {
|
|
3032
|
+
switch (reason) {
|
|
3033
|
+
case "MATCH": return ResolveReason.RESOLVE_REASON_MATCH;
|
|
3034
|
+
case "NO_SEGMENT_MATCH": return ResolveReason.RESOLVE_REASON_NO_SEGMENT_MATCH;
|
|
3035
|
+
case "NO_TREATMENT_MATCH": return ResolveReason.RESOLVE_REASON_NO_TREATMENT_MATCH;
|
|
3036
|
+
case "FLAG_ARCHIVED": return ResolveReason.RESOLVE_REASON_FLAG_ARCHIVED;
|
|
3037
|
+
case "TARGETING_KEY_ERROR": return ResolveReason.RESOLVE_REASON_TARGETING_KEY_ERROR;
|
|
3038
|
+
case "ERROR": return ResolveReason.RESOLVE_REASON_ERROR;
|
|
3039
|
+
default: return ResolveReason.RESOLVE_REASON_UNSPECIFIED;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
2893
3042
|
function createBaseResolveProcessRequest() {
|
|
2894
3043
|
return {
|
|
2895
3044
|
deferredMaterializations: void 0,
|
|
@@ -3311,6 +3460,61 @@ const MaterializationRecord = {
|
|
|
3311
3460
|
return message;
|
|
3312
3461
|
}
|
|
3313
3462
|
};
|
|
3463
|
+
function createBaseRegisterResolveRequest() {
|
|
3464
|
+
return {
|
|
3465
|
+
reason: 0,
|
|
3466
|
+
latencyUs: 0
|
|
3467
|
+
};
|
|
3468
|
+
}
|
|
3469
|
+
const RegisterResolveRequest = {
|
|
3470
|
+
encode(message, writer = new BinaryWriter()) {
|
|
3471
|
+
if (message.reason !== 0) writer.uint32(8).int32(message.reason);
|
|
3472
|
+
if (message.latencyUs !== 0) writer.uint32(16).uint32(message.latencyUs);
|
|
3473
|
+
return writer;
|
|
3474
|
+
},
|
|
3475
|
+
decode(input, length) {
|
|
3476
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
3477
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
3478
|
+
const message = createBaseRegisterResolveRequest();
|
|
3479
|
+
while (reader.pos < end) {
|
|
3480
|
+
const tag = reader.uint32();
|
|
3481
|
+
switch (tag >>> 3) {
|
|
3482
|
+
case 1:
|
|
3483
|
+
if (tag !== 8) break;
|
|
3484
|
+
message.reason = reader.int32();
|
|
3485
|
+
continue;
|
|
3486
|
+
case 2:
|
|
3487
|
+
if (tag !== 16) break;
|
|
3488
|
+
message.latencyUs = reader.uint32();
|
|
3489
|
+
continue;
|
|
3490
|
+
}
|
|
3491
|
+
if ((tag & 7) === 4 || tag === 0) break;
|
|
3492
|
+
reader.skip(tag & 7);
|
|
3493
|
+
}
|
|
3494
|
+
return message;
|
|
3495
|
+
},
|
|
3496
|
+
fromJSON(object) {
|
|
3497
|
+
return {
|
|
3498
|
+
reason: isSet(object.reason) ? resolveReasonFromJSON(object.reason) : 0,
|
|
3499
|
+
latencyUs: isSet(object.latencyUs) ? globalThis.Number(object.latencyUs) : 0
|
|
3500
|
+
};
|
|
3501
|
+
},
|
|
3502
|
+
toJSON(message) {
|
|
3503
|
+
const obj = {};
|
|
3504
|
+
if (message.reason !== 0) obj.reason = resolveReasonToJSON(message.reason);
|
|
3505
|
+
if (message.latencyUs !== 0) obj.latencyUs = Math.round(message.latencyUs);
|
|
3506
|
+
return obj;
|
|
3507
|
+
},
|
|
3508
|
+
create(base) {
|
|
3509
|
+
return RegisterResolveRequest.fromPartial(base ?? {});
|
|
3510
|
+
},
|
|
3511
|
+
fromPartial(object) {
|
|
3512
|
+
const message = createBaseRegisterResolveRequest();
|
|
3513
|
+
message.reason = object.reason ?? 0;
|
|
3514
|
+
message.latencyUs = object.latencyUs ?? 0;
|
|
3515
|
+
return message;
|
|
3516
|
+
}
|
|
3517
|
+
};
|
|
3314
3518
|
function bytesFromBase64(b64) {
|
|
3315
3519
|
if (globalThis.Buffer) return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
|
|
3316
3520
|
else {
|
|
@@ -3338,10 +3542,12 @@ const EXPORT_FN_NAMES = [
|
|
|
3338
3542
|
"wasm_msg_alloc",
|
|
3339
3543
|
"wasm_msg_free",
|
|
3340
3544
|
"wasm_msg_guest_resolve_flags",
|
|
3545
|
+
"wasm_msg_guest_register_resolve",
|
|
3341
3546
|
"wasm_msg_guest_set_resolver_state",
|
|
3342
3547
|
"wasm_msg_guest_bounded_flush_logs",
|
|
3343
3548
|
"wasm_msg_guest_bounded_flush_assign",
|
|
3344
|
-
"wasm_msg_guest_apply_flags"
|
|
3549
|
+
"wasm_msg_guest_apply_flags",
|
|
3550
|
+
"wasm_msg_guest_prometheus_snapshot"
|
|
3345
3551
|
];
|
|
3346
3552
|
function verifyExports(exports) {
|
|
3347
3553
|
for (const fnName of EXPORT_FN_NAMES) if (typeof exports[fnName] !== "function") throw new Error(`Expected Function export "${fnName}" found ${exports[fnName]}`);
|
|
@@ -3368,6 +3574,11 @@ var UnsafeWasmResolver = class {
|
|
|
3368
3574
|
const resPtr = this.exports.wasm_msg_guest_resolve_flags(reqPtr);
|
|
3369
3575
|
return this.consumeResponse(resPtr, ResolveProcessResponse);
|
|
3370
3576
|
}
|
|
3577
|
+
registerResolve(request) {
|
|
3578
|
+
const reqPtr = this.transferRequest(request, RegisterResolveRequest);
|
|
3579
|
+
const resPtr = this.exports.wasm_msg_guest_register_resolve(reqPtr);
|
|
3580
|
+
this.consumeResponse(resPtr, Void);
|
|
3581
|
+
}
|
|
3371
3582
|
setResolverState(request) {
|
|
3372
3583
|
const reqPtr = this.transferRequest(request, SetResolverStateRequest);
|
|
3373
3584
|
const resPtr = this.exports.wasm_msg_guest_set_resolver_state(reqPtr);
|
|
@@ -3390,6 +3601,11 @@ var UnsafeWasmResolver = class {
|
|
|
3390
3601
|
const resPtr = this.exports.wasm_msg_guest_apply_flags(reqPtr);
|
|
3391
3602
|
this.consumeResponse(resPtr, Void);
|
|
3392
3603
|
}
|
|
3604
|
+
prometheusSnapshot(instance) {
|
|
3605
|
+
const reqPtr = this.transferRequest({ instance }, PrometheusSnapshotRequest);
|
|
3606
|
+
const resPtr = this.exports.wasm_msg_guest_prometheus_snapshot(reqPtr);
|
|
3607
|
+
return this.consumeResponse(resPtr, PrometheusSnapshotResponse).text;
|
|
3608
|
+
}
|
|
3393
3609
|
transferRequest(value, codec) {
|
|
3394
3610
|
const data = codec.encode(value).finish();
|
|
3395
3611
|
return this.transfer({ data }, Request);
|
|
@@ -3447,6 +3663,11 @@ var WasmResolver = class {
|
|
|
3447
3663
|
throw error$1;
|
|
3448
3664
|
}
|
|
3449
3665
|
}
|
|
3666
|
+
registerResolve(request) {
|
|
3667
|
+
try {
|
|
3668
|
+
this.delegate.registerResolve(request);
|
|
3669
|
+
} catch {}
|
|
3670
|
+
}
|
|
3450
3671
|
setResolverState(request) {
|
|
3451
3672
|
this.currentState = request;
|
|
3452
3673
|
try {
|
|
@@ -3484,6 +3705,14 @@ var WasmResolver = class {
|
|
|
3484
3705
|
throw error$1;
|
|
3485
3706
|
}
|
|
3486
3707
|
}
|
|
3708
|
+
prometheusSnapshot(instance) {
|
|
3709
|
+
try {
|
|
3710
|
+
return this.delegate.prometheusSnapshot(instance);
|
|
3711
|
+
} catch (error$1) {
|
|
3712
|
+
logger.error("prometheus snapshot failed:", error$1);
|
|
3713
|
+
return "";
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3487
3716
|
};
|
|
3488
3717
|
let resolver = null;
|
|
3489
3718
|
function createConfidenceServerProvider({ wasmUrl,...options }) {
|
package/dist/index.inlined.d.ts
CHANGED
|
@@ -82,6 +82,10 @@ declare enum ResolveReason {
|
|
|
82
82
|
RESOLVE_REASON_UNRECOGNIZED_TARGETING_RULE = 7,
|
|
83
83
|
/** RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED - The flag could not be resolved because a rule is using materialization */
|
|
84
84
|
RESOLVE_REASON_MATERIALIZATION_NOT_SUPPORTED = 8,
|
|
85
|
+
/** RESOLVE_REASON_TYPE_MISMATCH - The resolved value type does not match the type requested by the SDK */
|
|
86
|
+
RESOLVE_REASON_TYPE_MISMATCH = 9,
|
|
87
|
+
/** RESOLVE_REASON_FLAG_NOT_FOUND - The flag was not found in the resolve response */
|
|
88
|
+
RESOLVE_REASON_FLAG_NOT_FOUND = 10,
|
|
85
89
|
UNRECOGNIZED = -1,
|
|
86
90
|
}
|
|
87
91
|
declare enum SdkId {
|
|
@@ -273,6 +277,10 @@ interface MaterializationRecord {
|
|
|
273
277
|
rule: string;
|
|
274
278
|
variant: string;
|
|
275
279
|
}
|
|
280
|
+
interface RegisterResolveRequest {
|
|
281
|
+
reason: ResolveReason;
|
|
282
|
+
latencyUs: number;
|
|
283
|
+
}
|
|
276
284
|
declare const ResolveProcessRequest: MessageFns$2<ResolveProcessRequest>;
|
|
277
285
|
declare const ResolveProcessRequest_StaticMaterializations: MessageFns$2<ResolveProcessRequest_StaticMaterializations>;
|
|
278
286
|
declare const ResolveProcessRequest_Resume: MessageFns$2<ResolveProcessRequest_Resume>;
|
|
@@ -280,6 +288,7 @@ declare const ResolveProcessResponse: MessageFns$2<ResolveProcessResponse>;
|
|
|
280
288
|
declare const ResolveProcessResponse_Resolved: MessageFns$2<ResolveProcessResponse_Resolved>;
|
|
281
289
|
declare const ResolveProcessResponse_Suspended: MessageFns$2<ResolveProcessResponse_Suspended>;
|
|
282
290
|
declare const MaterializationRecord: MessageFns$2<MaterializationRecord>;
|
|
291
|
+
declare const RegisterResolveRequest: MessageFns$2<RegisterResolveRequest>;
|
|
283
292
|
type Builtin$2 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
284
293
|
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>;
|
|
285
294
|
type KeysOfUnion$2<T> = T extends T ? keyof T : never;
|
|
@@ -297,6 +306,7 @@ interface MessageFns$2<T> {
|
|
|
297
306
|
interface SetResolverStateRequest {
|
|
298
307
|
state: Uint8Array;
|
|
299
308
|
accountId: string;
|
|
309
|
+
sdk?: Sdk | undefined;
|
|
300
310
|
}
|
|
301
311
|
declare const SetResolverStateRequest: MessageFns$1<SetResolverStateRequest>;
|
|
302
312
|
type Builtin$1 = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
@@ -315,10 +325,12 @@ interface MessageFns$1<T> {
|
|
|
315
325
|
//#region src/LocalResolver.d.ts
|
|
316
326
|
interface LocalResolver {
|
|
317
327
|
resolveProcess(request: ResolveProcessRequest): ResolveProcessResponse;
|
|
328
|
+
registerResolve(request: RegisterResolveRequest): void;
|
|
318
329
|
setResolverState(request: SetResolverStateRequest): void;
|
|
319
330
|
flushLogs(): Uint8Array;
|
|
320
331
|
flushAssigned(): Uint8Array;
|
|
321
332
|
applyFlags(request: ApplyFlagsRequest): void;
|
|
333
|
+
prometheusSnapshot(instance: string): string;
|
|
322
334
|
}
|
|
323
335
|
//#endregion
|
|
324
336
|
//#region src/proto/confidence/flags/resolver/v1/internal_api.d.ts
|
|
@@ -428,7 +440,7 @@ interface MaterializationStore {
|
|
|
428
440
|
}
|
|
429
441
|
//#endregion
|
|
430
442
|
//#region src/types.d.ts
|
|
431
|
-
type ResolutionReason = "ERROR" | "FLAG_ARCHIVED" | "MATCH" | "NO_SEGMENT_MATCH" | "TARGETING_KEY_ERROR" | "NO_TREATMENT_MATCH" | "UNSPECIFIED";
|
|
443
|
+
type ResolutionReason = "ERROR" | "FLAG_ARCHIVED" | "MATCH" | "NO_SEGMENT_MATCH" | "TARGETING_KEY_ERROR" | "NO_TREATMENT_MATCH" | "MATERIALIZATION_NOT_SUPPORTED" | "UNSPECIFIED";
|
|
432
444
|
declare enum ErrorCode {
|
|
433
445
|
PROVIDER_NOT_READY = "PROVIDER_NOT_READY",
|
|
434
446
|
PROVIDER_FATAL = "PROVIDER_FATAL",
|
|
@@ -461,6 +473,12 @@ interface FlagBundle {
|
|
|
461
473
|
//#endregion
|
|
462
474
|
//#region src/ConfidenceServerProviderLocal.d.ts
|
|
463
475
|
type FlagBundle$1 = FlagBundle;
|
|
476
|
+
/**
|
|
477
|
+
* Configuration for {@link ConfidenceServerProviderLocal.getPrometheusMetrics}.
|
|
478
|
+
*
|
|
479
|
+
* @experimental This API is subject to change.
|
|
480
|
+
*/
|
|
481
|
+
interface SnapshotConfig {}
|
|
464
482
|
interface ProviderOptions {
|
|
465
483
|
flagClientSecret: string;
|
|
466
484
|
initializeTimeout?: number;
|
|
@@ -512,6 +530,12 @@ declare class ConfidenceServerProviderLocal implements Provider {
|
|
|
512
530
|
/** Resolves with an evaluation of a String flag */
|
|
513
531
|
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext): Promise<ResolutionDetails<string>>;
|
|
514
532
|
/**
|
|
533
|
+
* Returns a Prometheus metrics snapshot from the WASM resolver.
|
|
534
|
+
*
|
|
535
|
+
* @experimental This API is subject to change.
|
|
536
|
+
*/
|
|
537
|
+
getPrometheusMetrics(_request?: SnapshotConfig): string;
|
|
538
|
+
/**
|
|
515
539
|
* Applies a previously resolved flag, logging that it was used/exposed.
|
|
516
540
|
* Call this when a flag value is actually rendered or used in the client.
|
|
517
541
|
* @param resolveToken - Base64-encoded resolve token from the flag bundle
|
|
@@ -524,4 +548,4 @@ declare class ConfidenceServerProviderLocal implements Provider {
|
|
|
524
548
|
type ProviderOptionsExt = ProviderOptions;
|
|
525
549
|
declare function createConfidenceServerProvider(options: ProviderOptions): ConfidenceServerProviderLocal;
|
|
526
550
|
//#endregion
|
|
527
|
-
export { type MaterializationStore, ProviderOptionsExt, createConfidenceServerProvider };
|
|
551
|
+
export { type MaterializationStore, ProviderOptionsExt, type SnapshotConfig, createConfidenceServerProvider };
|