@replanejs/sdk 0.9.4 → 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/README.md +22 -11
- package/dist/index.cjs +277 -4
- package/dist/index.d.cts +165 -9
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +165 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +277 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">Replane JavaScript SDK</h1>
|
|
2
|
+
<p align="center">Dynamic configuration for Node.js, Deno, Bun, and browsers.</p>
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://cloud.replane.dev"><img src="https://img.shields.io/badge/Try-Replane%20Cloud-blue" alt="Replane Cloud"></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@replanejs/sdk"><img src="https://img.shields.io/npm/v/@replanejs/sdk" alt="npm"></a>
|
|
7
|
+
<a href="https://github.com/replane-dev/replane-javascript/blob/main/LICENSE"><img src="https://img.shields.io/github/license/replane-dev/replane-javascript" alt="License"></a>
|
|
8
|
+
<a href="https://github.com/orgs/replane-dev/discussions"><img src="https://img.shields.io/badge/discussions-join-blue?logo=github" alt="Community"></a>
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
>
|
|
11
|
+
<picture>
|
|
12
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/replane-dev/replane/main/public/replane-window-screenshot-dark-v1.png">
|
|
13
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/replane-dev/replane/main/public/replane-window-screenshot-light-with-border-v2.jpg">
|
|
14
|
+
<img alt="Replane Screenshot" src="https://raw.githubusercontent.com/replane-dev/replane/main/public/replane-window-screenshot-light-with-border-v2.jpg">
|
|
15
|
+
</picture>
|
|
8
16
|
|
|
9
|
-
|
|
17
|
+
[Replane](https://github.com/replane-dev/replane) is a dynamic configuration manager. Store feature flags, app settings, and operational config in one place—with version history, optional approvals, and realtime sync to your services. No redeploys needed.
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
## Why Dynamic Configuration?
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
- **Feature flags** – toggle features, run A/B tests, roll out to user segments
|
|
22
|
+
- **Operational tuning** – adjust limits, TTLs, and timeouts without redeploying
|
|
23
|
+
- **Per-environment settings** – different values for production, staging, dev
|
|
24
|
+
- **Incident response** – instantly revert to a known-good version
|
|
25
|
+
- **Cross-service configuration** – share settings with realtime sync
|
|
26
|
+
- **Non-engineer access** – safe editing with schema validation
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
## Features
|
|
16
29
|
|
|
17
30
|
- Works in ESM and CJS (dual build)
|
|
18
31
|
- Zero runtime deps (uses native `fetch` — bring a polyfill if your runtime lacks it)
|
|
@@ -33,8 +46,6 @@ yarn add @replanejs/sdk
|
|
|
33
46
|
|
|
34
47
|
## Quick start
|
|
35
48
|
|
|
36
|
-
> **Important:** Each SDK key is tied to a specific project. The client can only access configs from the project that the SDK key belongs to. If you need configs from multiple projects, create separate SDK keys and initialize separate clients—one per project.
|
|
37
|
-
|
|
38
49
|
```ts
|
|
39
50
|
import { Replane } from "@replanejs/sdk";
|
|
40
51
|
|
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,20 @@ var ReplaneError = class extends Error {
|
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region src/utils.ts
|
|
33
33
|
/**
|
|
34
|
+
* Generates a random UUID using the Web Crypto API.
|
|
35
|
+
* Falls back to a simple implementation if crypto.randomUUID is not available.
|
|
36
|
+
*
|
|
37
|
+
* @returns A random UUID string
|
|
38
|
+
*/
|
|
39
|
+
function generateClientId() {
|
|
40
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
41
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
42
|
+
const r = Math.random() * 16 | 0;
|
|
43
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
44
|
+
return v.toString(16);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
34
48
|
* Returns a promise that resolves after the specified delay
|
|
35
49
|
*
|
|
36
50
|
* @param ms - Delay in milliseconds
|
|
@@ -482,11 +496,17 @@ function castToContextType(expectedValue, contextValue) {
|
|
|
482
496
|
|
|
483
497
|
//#endregion
|
|
484
498
|
//#region src/version.ts
|
|
485
|
-
const VERSION = "0.
|
|
499
|
+
const VERSION = "1.0.0";
|
|
486
500
|
const DEFAULT_AGENT = `replane-js-sdk/${VERSION}`;
|
|
487
501
|
|
|
488
502
|
//#endregion
|
|
489
503
|
//#region src/client.ts
|
|
504
|
+
/**
|
|
505
|
+
* The context key for the auto-generated client ID.
|
|
506
|
+
* This key is automatically set by the SDK and can be used for segmentation.
|
|
507
|
+
* User-provided values for this key take precedence over the auto-generated value.
|
|
508
|
+
*/
|
|
509
|
+
const REPLANE_CLIENT_ID_KEY = "replaneClientId";
|
|
490
510
|
function asReplaneHandle(replane) {
|
|
491
511
|
return replane;
|
|
492
512
|
}
|
|
@@ -564,7 +584,11 @@ var ReplaneImpl = class {
|
|
|
564
584
|
*/
|
|
565
585
|
constructor(options = {}) {
|
|
566
586
|
this.logger = options.logger ?? console;
|
|
567
|
-
|
|
587
|
+
const autoGeneratedContext = { [REPLANE_CLIENT_ID_KEY]: generateClientId() };
|
|
588
|
+
this.context = {
|
|
589
|
+
...autoGeneratedContext,
|
|
590
|
+
...options.context ?? {}
|
|
591
|
+
};
|
|
568
592
|
const initialConfigs = [];
|
|
569
593
|
if (options.snapshot) for (const config of options.snapshot.configs) initialConfigs.push({
|
|
570
594
|
name: config.name,
|
|
@@ -745,8 +769,13 @@ var ReplaneImpl = class {
|
|
|
745
769
|
})
|
|
746
770
|
});
|
|
747
771
|
for await (const event of replicationStream) {
|
|
748
|
-
|
|
749
|
-
|
|
772
|
+
if (event.type === "init") {
|
|
773
|
+
this.processConfigUpdates(event.configs);
|
|
774
|
+
this.logger.info(`Replane: initialized with ${event.configs.length} config(s)`);
|
|
775
|
+
} else {
|
|
776
|
+
this.processConfigUpdates([event.config]);
|
|
777
|
+
this.logger.info(`Replane: config "${event.config.name}" updated`);
|
|
778
|
+
}
|
|
750
779
|
clientReady.resolve();
|
|
751
780
|
}
|
|
752
781
|
} catch (error) {
|
|
@@ -854,6 +883,250 @@ async function getReplaneSnapshot(options) {
|
|
|
854
883
|
}
|
|
855
884
|
|
|
856
885
|
//#endregion
|
|
886
|
+
//#region src/in-memory.ts
|
|
887
|
+
function asHandle(client) {
|
|
888
|
+
return client;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* An in-memory Replane client for testing.
|
|
892
|
+
*
|
|
893
|
+
* This client provides the same interface as `Replane` but stores
|
|
894
|
+
* all configs in memory. It's useful for unit tests where you don't want
|
|
895
|
+
* to connect to a real Replane server.
|
|
896
|
+
*
|
|
897
|
+
* @example
|
|
898
|
+
* ```typescript
|
|
899
|
+
* // Basic usage
|
|
900
|
+
* const client = new InMemoryReplaneClient({
|
|
901
|
+
* defaults: { "feature-enabled": true, "rate-limit": 100 },
|
|
902
|
+
* });
|
|
903
|
+
* expect(client.get("feature-enabled")).toBe(true);
|
|
904
|
+
*
|
|
905
|
+
* // Update config at runtime
|
|
906
|
+
* client.set("feature-enabled", false);
|
|
907
|
+
* expect(client.get("feature-enabled")).toBe(false);
|
|
908
|
+
*
|
|
909
|
+
* // With overrides
|
|
910
|
+
* client.setConfig("rate-limit", 100, {
|
|
911
|
+
* overrides: [{
|
|
912
|
+
* name: "premium-users",
|
|
913
|
+
* conditions: [{ operator: "equals", property: "plan", value: "premium" }],
|
|
914
|
+
* value: 1000,
|
|
915
|
+
* }],
|
|
916
|
+
* });
|
|
917
|
+
* expect(client.get("rate-limit")).toBe(100);
|
|
918
|
+
* expect(client.get("rate-limit", { context: { plan: "premium" } })).toBe(1000);
|
|
919
|
+
* ```
|
|
920
|
+
*
|
|
921
|
+
* @typeParam T - Type definition for config keys and values
|
|
922
|
+
*/
|
|
923
|
+
var InMemoryReplaneClient = class {
|
|
924
|
+
constructor(options = {}) {
|
|
925
|
+
asHandle(this)._impl = new InMemoryReplaneClientImpl(options);
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Get a config value by name.
|
|
929
|
+
*
|
|
930
|
+
* Evaluates any overrides based on the client context and per-call context.
|
|
931
|
+
*
|
|
932
|
+
* @param configName - The name of the config to retrieve
|
|
933
|
+
* @param options - Optional settings for this call
|
|
934
|
+
* @returns The config value
|
|
935
|
+
* @throws {ReplaneError} If config not found and no default provided
|
|
936
|
+
*/
|
|
937
|
+
get(configName, options) {
|
|
938
|
+
return asHandle(this)._impl.get(configName, options);
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Subscribe to a specific config's changes.
|
|
942
|
+
*
|
|
943
|
+
* @param configName - The config to watch
|
|
944
|
+
* @param callback - Function called when the config changes
|
|
945
|
+
* @returns Unsubscribe function
|
|
946
|
+
*/
|
|
947
|
+
subscribe(configName, callback) {
|
|
948
|
+
return asHandle(this)._impl.subscribe(configName, callback);
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Get a serializable snapshot of the current client state.
|
|
952
|
+
*
|
|
953
|
+
* @returns Snapshot object that can be serialized to JSON
|
|
954
|
+
*/
|
|
955
|
+
getSnapshot() {
|
|
956
|
+
return asHandle(this)._impl.getSnapshot();
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Set a config value (simple form without overrides).
|
|
960
|
+
*
|
|
961
|
+
* @param name - Config name
|
|
962
|
+
* @param value - Config value
|
|
963
|
+
*
|
|
964
|
+
* @example
|
|
965
|
+
* ```typescript
|
|
966
|
+
* client.set("feature-enabled", true);
|
|
967
|
+
* client.set("rate-limit", 500);
|
|
968
|
+
* ```
|
|
969
|
+
*/
|
|
970
|
+
set(name, value) {
|
|
971
|
+
asHandle(this)._impl.set(name, value);
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Set a config with optional overrides.
|
|
975
|
+
*
|
|
976
|
+
* @param name - Config name
|
|
977
|
+
* @param value - Base config value
|
|
978
|
+
* @param options - Optional settings including overrides
|
|
979
|
+
*
|
|
980
|
+
* @example
|
|
981
|
+
* ```typescript
|
|
982
|
+
* client.setConfig("rate-limit", 100, {
|
|
983
|
+
* overrides: [{
|
|
984
|
+
* name: "premium-users",
|
|
985
|
+
* conditions: [
|
|
986
|
+
* { operator: "in", property: "plan", value: ["pro", "enterprise"] }
|
|
987
|
+
* ],
|
|
988
|
+
* value: 1000,
|
|
989
|
+
* }],
|
|
990
|
+
* });
|
|
991
|
+
* ```
|
|
992
|
+
*/
|
|
993
|
+
setConfig(name, value, options) {
|
|
994
|
+
asHandle(this)._impl.setConfig(name, value, options);
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Delete a config.
|
|
998
|
+
*
|
|
999
|
+
* @param name - Config name to delete
|
|
1000
|
+
* @returns True if config was deleted, false if it didn't exist
|
|
1001
|
+
*/
|
|
1002
|
+
delete(name) {
|
|
1003
|
+
return asHandle(this)._impl.delete(name);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Clear all configs.
|
|
1007
|
+
*/
|
|
1008
|
+
clear() {
|
|
1009
|
+
asHandle(this)._impl.clear();
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Check if a config exists.
|
|
1013
|
+
*
|
|
1014
|
+
* @param name - Config name to check
|
|
1015
|
+
* @returns True if config exists
|
|
1016
|
+
*/
|
|
1017
|
+
has(name) {
|
|
1018
|
+
return asHandle(this)._impl.has(name);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Get all config names.
|
|
1022
|
+
*
|
|
1023
|
+
* @returns Array of config names
|
|
1024
|
+
*/
|
|
1025
|
+
keys() {
|
|
1026
|
+
return asHandle(this)._impl.keys();
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
var InMemoryReplaneClientImpl = class {
|
|
1030
|
+
configs;
|
|
1031
|
+
context;
|
|
1032
|
+
logger;
|
|
1033
|
+
configSubscriptions = new Map();
|
|
1034
|
+
constructor(options = {}) {
|
|
1035
|
+
this.logger = options.logger ?? console;
|
|
1036
|
+
this.context = options.context ?? {};
|
|
1037
|
+
const initialConfigs = [];
|
|
1038
|
+
if (options.defaults) {
|
|
1039
|
+
for (const [name, value] of Object.entries(options.defaults)) if (value !== void 0) initialConfigs.push({
|
|
1040
|
+
name,
|
|
1041
|
+
value,
|
|
1042
|
+
overrides: []
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
this.configs = new Map(initialConfigs.map((config) => [config.name, config]));
|
|
1046
|
+
}
|
|
1047
|
+
get(configName, options = {}) {
|
|
1048
|
+
const config = this.configs.get(String(configName));
|
|
1049
|
+
if (config === void 0) {
|
|
1050
|
+
if ("default" in options) return options.default;
|
|
1051
|
+
throw new ReplaneError({
|
|
1052
|
+
message: `Config not found: ${String(configName)}`,
|
|
1053
|
+
code: ReplaneErrorCode.NotFound
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
try {
|
|
1057
|
+
return evaluateOverrides(config.value, config.overrides, {
|
|
1058
|
+
...this.context,
|
|
1059
|
+
...options?.context ?? {}
|
|
1060
|
+
}, this.logger);
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
this.logger.error(`Replane: error evaluating overrides for config ${String(configName)}:`, error);
|
|
1063
|
+
return config.value;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
subscribe(configName, callback) {
|
|
1067
|
+
const wrappedCallback = (config) => {
|
|
1068
|
+
callback(config);
|
|
1069
|
+
};
|
|
1070
|
+
if (!this.configSubscriptions.has(configName)) this.configSubscriptions.set(configName, new Set());
|
|
1071
|
+
this.configSubscriptions.get(configName).add(wrappedCallback);
|
|
1072
|
+
return () => {
|
|
1073
|
+
this.configSubscriptions.get(configName)?.delete(wrappedCallback);
|
|
1074
|
+
if (this.configSubscriptions.get(configName)?.size === 0) this.configSubscriptions.delete(configName);
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
getSnapshot() {
|
|
1078
|
+
return { configs: [...this.configs.values()].map((config) => ({
|
|
1079
|
+
name: config.name,
|
|
1080
|
+
value: config.value,
|
|
1081
|
+
overrides: config.overrides.map((override) => ({
|
|
1082
|
+
name: override.name,
|
|
1083
|
+
conditions: override.conditions,
|
|
1084
|
+
value: override.value
|
|
1085
|
+
}))
|
|
1086
|
+
})) };
|
|
1087
|
+
}
|
|
1088
|
+
set(name, value) {
|
|
1089
|
+
this.setConfig(name, value);
|
|
1090
|
+
}
|
|
1091
|
+
setConfig(name, value, options) {
|
|
1092
|
+
const overrides = options?.overrides ?? [];
|
|
1093
|
+
const config = {
|
|
1094
|
+
name: String(name),
|
|
1095
|
+
value,
|
|
1096
|
+
overrides
|
|
1097
|
+
};
|
|
1098
|
+
this.configs.set(String(name), config);
|
|
1099
|
+
this.notifySubscribers(name, value);
|
|
1100
|
+
}
|
|
1101
|
+
delete(name) {
|
|
1102
|
+
const existed = this.configs.has(String(name));
|
|
1103
|
+
this.configs.delete(String(name));
|
|
1104
|
+
return existed;
|
|
1105
|
+
}
|
|
1106
|
+
clear() {
|
|
1107
|
+
this.configs.clear();
|
|
1108
|
+
}
|
|
1109
|
+
has(name) {
|
|
1110
|
+
return this.configs.has(String(name));
|
|
1111
|
+
}
|
|
1112
|
+
keys() {
|
|
1113
|
+
return [...this.configs.keys()];
|
|
1114
|
+
}
|
|
1115
|
+
notifySubscribers(name, value) {
|
|
1116
|
+
const change = {
|
|
1117
|
+
name,
|
|
1118
|
+
value
|
|
1119
|
+
};
|
|
1120
|
+
for (const callback of this.configSubscriptions.get(name) ?? []) try {
|
|
1121
|
+
callback(change);
|
|
1122
|
+
} catch (error) {
|
|
1123
|
+
this.logger.error(`Replane: error in subscription callback for ${String(name)}:`, error);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
|
|
1128
|
+
//#endregion
|
|
1129
|
+
exports.InMemoryReplaneClient = InMemoryReplaneClient;
|
|
857
1130
|
exports.Replane = Replane;
|
|
858
1131
|
exports.ReplaneError = ReplaneError;
|
|
859
1132
|
exports.ReplaneErrorCode = ReplaneErrorCode;
|
package/dist/index.d.cts
CHANGED
|
@@ -14,20 +14,20 @@ interface SegmentationCondition {
|
|
|
14
14
|
}
|
|
15
15
|
interface AndCondition {
|
|
16
16
|
operator: "and";
|
|
17
|
-
conditions:
|
|
17
|
+
conditions: Condition[];
|
|
18
18
|
}
|
|
19
19
|
interface OrCondition {
|
|
20
20
|
operator: "or";
|
|
21
|
-
conditions:
|
|
21
|
+
conditions: Condition[];
|
|
22
22
|
}
|
|
23
23
|
interface NotCondition {
|
|
24
24
|
operator: "not";
|
|
25
|
-
condition:
|
|
25
|
+
condition: Condition;
|
|
26
26
|
}
|
|
27
|
-
type
|
|
28
|
-
interface
|
|
27
|
+
type Condition = PropertyCondition | SegmentationCondition | AndCondition | OrCondition | NotCondition;
|
|
28
|
+
interface Override {
|
|
29
29
|
name: string;
|
|
30
|
-
conditions:
|
|
30
|
+
conditions: Condition[];
|
|
31
31
|
value: unknown;
|
|
32
32
|
}
|
|
33
33
|
//#endregion
|
|
@@ -73,7 +73,7 @@ interface ReplaneSnapshot<_T extends object = object> {
|
|
|
73
73
|
configs: Array<{
|
|
74
74
|
name: string;
|
|
75
75
|
value: unknown;
|
|
76
|
-
overrides:
|
|
76
|
+
overrides: Override[];
|
|
77
77
|
}>;
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
@@ -278,7 +278,163 @@ declare function getReplaneSnapshot<T extends object>(options: GetReplaneSnapsho
|
|
|
278
278
|
* Clears the client cache used by getReplaneSnapshot.
|
|
279
279
|
* Useful for testing or when you need to force re-initialization.
|
|
280
280
|
*/
|
|
281
|
-
|
|
282
281
|
//#endregion
|
|
283
|
-
|
|
282
|
+
//#region src/in-memory.d.ts
|
|
283
|
+
/**
|
|
284
|
+
* Options for setting a config with overrides.
|
|
285
|
+
*/
|
|
286
|
+
interface SetConfigOptions {
|
|
287
|
+
/** Override rules for context-based value selection */
|
|
288
|
+
overrides?: Override[];
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Options for InMemoryReplaneClient constructor.
|
|
292
|
+
*/
|
|
293
|
+
interface InMemoryReplaneClientOptions<T extends object> {
|
|
294
|
+
/**
|
|
295
|
+
* Optional logger (defaults to console).
|
|
296
|
+
*/
|
|
297
|
+
logger?: ReplaneLogger;
|
|
298
|
+
/**
|
|
299
|
+
* Default context for all config evaluations.
|
|
300
|
+
* Can be overridden per-request in `client.get()`.
|
|
301
|
+
*/
|
|
302
|
+
context?: ReplaneContext;
|
|
303
|
+
/**
|
|
304
|
+
* Initial config values.
|
|
305
|
+
* @example
|
|
306
|
+
* {
|
|
307
|
+
* defaults: {
|
|
308
|
+
* "feature-enabled": true,
|
|
309
|
+
* "rate-limit": 100,
|
|
310
|
+
* },
|
|
311
|
+
* }
|
|
312
|
+
*/
|
|
313
|
+
defaults?: { [K in keyof T]?: T[K] };
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* An in-memory Replane client for testing.
|
|
317
|
+
*
|
|
318
|
+
* This client provides the same interface as `Replane` but stores
|
|
319
|
+
* all configs in memory. It's useful for unit tests where you don't want
|
|
320
|
+
* to connect to a real Replane server.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* // Basic usage
|
|
325
|
+
* const client = new InMemoryReplaneClient({
|
|
326
|
+
* defaults: { "feature-enabled": true, "rate-limit": 100 },
|
|
327
|
+
* });
|
|
328
|
+
* expect(client.get("feature-enabled")).toBe(true);
|
|
329
|
+
*
|
|
330
|
+
* // Update config at runtime
|
|
331
|
+
* client.set("feature-enabled", false);
|
|
332
|
+
* expect(client.get("feature-enabled")).toBe(false);
|
|
333
|
+
*
|
|
334
|
+
* // With overrides
|
|
335
|
+
* client.setConfig("rate-limit", 100, {
|
|
336
|
+
* overrides: [{
|
|
337
|
+
* name: "premium-users",
|
|
338
|
+
* conditions: [{ operator: "equals", property: "plan", value: "premium" }],
|
|
339
|
+
* value: 1000,
|
|
340
|
+
* }],
|
|
341
|
+
* });
|
|
342
|
+
* expect(client.get("rate-limit")).toBe(100);
|
|
343
|
+
* expect(client.get("rate-limit", { context: { plan: "premium" } })).toBe(1000);
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* @typeParam T - Type definition for config keys and values
|
|
347
|
+
*/
|
|
348
|
+
declare class InMemoryReplaneClient<T extends object = Record<string, unknown>> {
|
|
349
|
+
constructor(options?: InMemoryReplaneClientOptions<T>);
|
|
350
|
+
/**
|
|
351
|
+
* Get a config value by name.
|
|
352
|
+
*
|
|
353
|
+
* Evaluates any overrides based on the client context and per-call context.
|
|
354
|
+
*
|
|
355
|
+
* @param configName - The name of the config to retrieve
|
|
356
|
+
* @param options - Optional settings for this call
|
|
357
|
+
* @returns The config value
|
|
358
|
+
* @throws {ReplaneError} If config not found and no default provided
|
|
359
|
+
*/
|
|
360
|
+
get<K extends keyof T>(configName: K, options?: GetConfigOptions<T[K]>): T[K];
|
|
361
|
+
/**
|
|
362
|
+
* Subscribe to a specific config's changes.
|
|
363
|
+
*
|
|
364
|
+
* @param configName - The config to watch
|
|
365
|
+
* @param callback - Function called when the config changes
|
|
366
|
+
* @returns Unsubscribe function
|
|
367
|
+
*/
|
|
368
|
+
subscribe<K extends keyof T>(configName: K, callback: (config: {
|
|
369
|
+
name: K;
|
|
370
|
+
value: T[K];
|
|
371
|
+
}) => void): () => void;
|
|
372
|
+
/**
|
|
373
|
+
* Get a serializable snapshot of the current client state.
|
|
374
|
+
*
|
|
375
|
+
* @returns Snapshot object that can be serialized to JSON
|
|
376
|
+
*/
|
|
377
|
+
getSnapshot(): ReplaneSnapshot<T>;
|
|
378
|
+
/**
|
|
379
|
+
* Set a config value (simple form without overrides).
|
|
380
|
+
*
|
|
381
|
+
* @param name - Config name
|
|
382
|
+
* @param value - Config value
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* ```typescript
|
|
386
|
+
* client.set("feature-enabled", true);
|
|
387
|
+
* client.set("rate-limit", 500);
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
set<K extends keyof T>(name: K, value: T[K]): void;
|
|
391
|
+
/**
|
|
392
|
+
* Set a config with optional overrides.
|
|
393
|
+
*
|
|
394
|
+
* @param name - Config name
|
|
395
|
+
* @param value - Base config value
|
|
396
|
+
* @param options - Optional settings including overrides
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```typescript
|
|
400
|
+
* client.setConfig("rate-limit", 100, {
|
|
401
|
+
* overrides: [{
|
|
402
|
+
* name: "premium-users",
|
|
403
|
+
* conditions: [
|
|
404
|
+
* { operator: "in", property: "plan", value: ["pro", "enterprise"] }
|
|
405
|
+
* ],
|
|
406
|
+
* value: 1000,
|
|
407
|
+
* }],
|
|
408
|
+
* });
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
setConfig<K extends keyof T>(name: K, value: T[K], options?: SetConfigOptions): void;
|
|
412
|
+
/**
|
|
413
|
+
* Delete a config.
|
|
414
|
+
*
|
|
415
|
+
* @param name - Config name to delete
|
|
416
|
+
* @returns True if config was deleted, false if it didn't exist
|
|
417
|
+
*/
|
|
418
|
+
delete<K extends keyof T>(name: K): boolean;
|
|
419
|
+
/**
|
|
420
|
+
* Clear all configs.
|
|
421
|
+
*/
|
|
422
|
+
clear(): void;
|
|
423
|
+
/**
|
|
424
|
+
* Check if a config exists.
|
|
425
|
+
*
|
|
426
|
+
* @param name - Config name to check
|
|
427
|
+
* @returns True if config exists
|
|
428
|
+
*/
|
|
429
|
+
has<K extends keyof T>(name: K): boolean;
|
|
430
|
+
/**
|
|
431
|
+
* Get all config names.
|
|
432
|
+
*
|
|
433
|
+
* @returns Array of config names
|
|
434
|
+
*/
|
|
435
|
+
keys(): (keyof T)[];
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=in-memory.d.ts.map
|
|
438
|
+
//#endregion
|
|
439
|
+
export { type Condition, type ConnectOptions, type GetConfigOptions, type GetReplaneSnapshotOptions, InMemoryReplaneClient, type InMemoryReplaneClientOptions, type Override, Replane, type ReplaneContext, ReplaneError, ReplaneErrorCode, type ReplaneLogger, type ReplaneOptions, type ReplaneSnapshot, type SetConfigOptions, getReplaneSnapshot };
|
|
284
440
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/client-types.ts","../src/client.ts","../src/error.ts","../src/snapshot.ts"],"sourcesContent":[],"mappings":";;UAqBU,iBAAA;;ECfE,QAAA,EAAA,MAAA;EAKK,KAAA,EAAA,OAAA;AAUjB;UDaU,qBAAA,CCbuB;EAAA,QAIrB,EAAA,cAAA;EAAc,QAKd,EAAA,MAAA;EAAC,cAAA,EAAA,MAAA;EAiBI,YAAA,EAAA,MAAe;EAAA,IAAA,EAAA,MAAA;;UDLtB,YAAA,CCOC;EAAK,QAAA,EAAA,KAAA;EAUC,UAAA,EDfH,
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/client-types.ts","../src/client.ts","../src/error.ts","../src/snapshot.ts","../src/in-memory.ts"],"sourcesContent":[],"mappings":"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"}
|