@splitsoftware/openfeature-js-split-provider 1.0.3 → 1.0.4
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/CHANGES.txt +4 -1
- package/README.md +16 -2
- package/package.json +7 -6
- package/src/__tests__/nodeSuites/client.spec.js +2 -2
- package/src/lib/js-split-provider.ts +56 -30
- package/types/index.d.ts +0 -17
package/CHANGES.txt
CHANGED
|
@@ -8,4 +8,7 @@
|
|
|
8
8
|
- Up to date with spec 0.4.0 and @openfeature/js-sdk 0.4.0
|
|
9
9
|
1.0.3
|
|
10
10
|
- Adds types definitions for TypeScript
|
|
11
|
-
- Up to date with spec 0.4.0 and @openfeature/js-sdk 0.4.0
|
|
11
|
+
- Up to date with spec 0.4.0 and @openfeature/js-sdk 0.4.0
|
|
12
|
+
1.0.4
|
|
13
|
+
- Fixes issue with TS build
|
|
14
|
+
- Up to date with spec 0.5.0 and @openfeature/js-sdk 0.5.0
|
package/README.md
CHANGED
|
@@ -10,13 +10,27 @@ This Provider is designed to allow the use of OpenFeature with Split, the platfo
|
|
|
10
10
|
## Getting started
|
|
11
11
|
Below is a simple example that describes the instantiation of the Split Provider. Please see the [OpenFeature Documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api) for details on how to use the OpenFeature SDK.
|
|
12
12
|
|
|
13
|
+
### Add the Split provider
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install @splitsoftware/openfeature-js-split-provider
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Confirm peer dependencies are installed
|
|
20
|
+
```sh
|
|
21
|
+
npm install @splitsoftware/splitio
|
|
22
|
+
npm install @openfeature/js-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Register the Split provider with OpenFeature
|
|
13
26
|
```js
|
|
14
27
|
const OpenFeature = require('@openfeature/js-sdk').OpenFeature;
|
|
15
28
|
const SplitFactory = require('@splitsoftware/splitio').SplitFactory;
|
|
16
29
|
const OpenFeatureSplitProvider = require('@splitsoftware/openfeature-js-split-provider').OpenFeatureSplitProvider;
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
31
|
+
const authorizationKey = 'your auth key'
|
|
32
|
+
const splitClient = SplitFactory({core: {authorizationKey}}).client();
|
|
33
|
+
const provider = new OpenFeatureSplitProvider({splitClient});
|
|
20
34
|
openFeature.setProvider(provider);
|
|
21
35
|
```
|
|
22
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@splitsoftware/openfeature-js-split-provider",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Split OpenFeature Provider",
|
|
5
5
|
"files": [
|
|
6
6
|
"README.md",
|
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
"bugs": "https://github.com/splitio/openfeature-split-provider-js/issues",
|
|
18
18
|
"license": "Apache-2.0",
|
|
19
19
|
"author": "Josh Sirota <josh.sirota@split.io>",
|
|
20
|
-
"contributors": [
|
|
21
|
-
],
|
|
22
20
|
"main": "lib/index.js",
|
|
23
21
|
"module": "es/index.js",
|
|
24
22
|
"types": "types",
|
|
@@ -26,11 +24,14 @@
|
|
|
26
24
|
"npm": ">=3",
|
|
27
25
|
"node": ">=6"
|
|
28
26
|
},
|
|
29
|
-
"dependencies": {
|
|
30
|
-
|
|
27
|
+
"dependencies": {},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@openfeature/js-sdk": "^0.5.0",
|
|
31
30
|
"@splitsoftware/splitio": "^10.21.1"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
33
|
+
"@openfeature/js-sdk": "^0.5.0",
|
|
34
|
+
"@splitsoftware/splitio": "^10.21.1",
|
|
34
35
|
"copyfiles": "^2.4.1",
|
|
35
36
|
"cross-env": "^7.0.3",
|
|
36
37
|
"replace": "^1.2.1",
|
|
@@ -63,4 +64,4 @@
|
|
|
63
64
|
"karma-webpack"
|
|
64
65
|
]
|
|
65
66
|
}
|
|
66
|
-
}
|
|
67
|
+
}
|
|
@@ -37,8 +37,8 @@ export default async function(assert) {
|
|
|
37
37
|
const getControlVariantNonExistentSplit = async (client) => {
|
|
38
38
|
let details = await client.getBooleanDetails('non-existent-feature', false);
|
|
39
39
|
assert.equals(details.value, false);
|
|
40
|
-
assert.equals(details.
|
|
41
|
-
assert.equals(details.reason, '
|
|
40
|
+
assert.equals(details.errorCode, 'FLAG_NOT_FOUND');
|
|
41
|
+
assert.equals(details.reason, 'ERROR');
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const getBooleanSplitTest = async (client) => {
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
EvaluationContext,
|
|
3
|
+
Provider,
|
|
4
|
+
ResolutionDetails,
|
|
5
|
+
ParseError,
|
|
6
|
+
FlagNotFoundError,
|
|
7
|
+
JsonValue,
|
|
8
|
+
TargetingKeyMissingError,
|
|
9
|
+
StandardResolutionReasons,
|
|
10
|
+
} from "@openfeature/js-sdk";
|
|
11
|
+
import type SplitIO from "@splitsoftware/splitio/types/splitio";
|
|
3
12
|
|
|
4
13
|
export interface SplitProviderOptions {
|
|
5
14
|
splitClient: SplitIO.IClient;
|
|
@@ -10,9 +19,11 @@ type Consumer = {
|
|
|
10
19
|
attributes: SplitIO.Attributes;
|
|
11
20
|
};
|
|
12
21
|
|
|
22
|
+
const CONTROL_VALUE_ERROR_MESSAGE = "Received the 'control' value from Split.";
|
|
23
|
+
|
|
13
24
|
export class OpenFeatureSplitProvider implements Provider {
|
|
14
25
|
metadata = {
|
|
15
|
-
name:
|
|
26
|
+
name: "split",
|
|
16
27
|
};
|
|
17
28
|
private initialized: Promise<void>;
|
|
18
29
|
private client: SplitIO.IClient;
|
|
@@ -29,23 +40,26 @@ export class OpenFeatureSplitProvider implements Provider {
|
|
|
29
40
|
|
|
30
41
|
async resolveBooleanEvaluation(
|
|
31
42
|
flagKey: string,
|
|
32
|
-
|
|
43
|
+
_: boolean,
|
|
33
44
|
context: EvaluationContext
|
|
34
45
|
): Promise<ResolutionDetails<boolean>> {
|
|
35
|
-
const details = await this.evaluateTreatment(
|
|
46
|
+
const details = await this.evaluateTreatment(
|
|
47
|
+
flagKey,
|
|
48
|
+
this.transformContext(context)
|
|
49
|
+
);
|
|
36
50
|
|
|
37
51
|
let value: boolean;
|
|
38
52
|
switch (details.value as unknown) {
|
|
39
|
-
case
|
|
53
|
+
case "on":
|
|
40
54
|
value = true;
|
|
41
55
|
break;
|
|
42
|
-
case
|
|
56
|
+
case "off":
|
|
43
57
|
value = false;
|
|
44
58
|
break;
|
|
45
|
-
case
|
|
59
|
+
case "true":
|
|
46
60
|
value = true;
|
|
47
61
|
break;
|
|
48
|
-
case
|
|
62
|
+
case "false":
|
|
49
63
|
value = false;
|
|
50
64
|
break;
|
|
51
65
|
case true:
|
|
@@ -54,10 +68,8 @@ export class OpenFeatureSplitProvider implements Provider {
|
|
|
54
68
|
case false:
|
|
55
69
|
value = false;
|
|
56
70
|
break;
|
|
57
|
-
case
|
|
58
|
-
|
|
59
|
-
details.reason = 'FLAG_NOT_FOUND';
|
|
60
|
-
break;
|
|
71
|
+
case "control":
|
|
72
|
+
throw new FlagNotFoundError(CONTROL_VALUE_ERROR_MESSAGE);
|
|
61
73
|
default:
|
|
62
74
|
throw new ParseError(`Invalid boolean value for ${details.value}`);
|
|
63
75
|
}
|
|
@@ -69,9 +81,12 @@ export class OpenFeatureSplitProvider implements Provider {
|
|
|
69
81
|
_: string,
|
|
70
82
|
context: EvaluationContext
|
|
71
83
|
): Promise<ResolutionDetails<string>> {
|
|
72
|
-
const details = await this.evaluateTreatment(
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
const details = await this.evaluateTreatment(
|
|
85
|
+
flagKey,
|
|
86
|
+
this.transformContext(context)
|
|
87
|
+
);
|
|
88
|
+
if (details.value === "control") {
|
|
89
|
+
throw new FlagNotFoundError(CONTROL_VALUE_ERROR_MESSAGE);
|
|
75
90
|
}
|
|
76
91
|
return details;
|
|
77
92
|
}
|
|
@@ -81,7 +96,10 @@ export class OpenFeatureSplitProvider implements Provider {
|
|
|
81
96
|
_: number,
|
|
82
97
|
context: EvaluationContext
|
|
83
98
|
): Promise<ResolutionDetails<number>> {
|
|
84
|
-
const details = await this.evaluateTreatment(
|
|
99
|
+
const details = await this.evaluateTreatment(
|
|
100
|
+
flagKey,
|
|
101
|
+
this.transformContext(context)
|
|
102
|
+
);
|
|
85
103
|
return { ...details, value: this.parseValidNumber(details.value) };
|
|
86
104
|
}
|
|
87
105
|
|
|
@@ -90,26 +108,32 @@ export class OpenFeatureSplitProvider implements Provider {
|
|
|
90
108
|
_: U,
|
|
91
109
|
context: EvaluationContext
|
|
92
110
|
): Promise<ResolutionDetails<U>> {
|
|
93
|
-
const details = await this.evaluateTreatment(
|
|
111
|
+
const details = await this.evaluateTreatment(
|
|
112
|
+
flagKey,
|
|
113
|
+
this.transformContext(context)
|
|
114
|
+
);
|
|
94
115
|
return { ...details, value: this.parseValidJsonObject(details.value) };
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
private async evaluateTreatment(
|
|
118
|
+
private async evaluateTreatment(
|
|
119
|
+
flagKey: string,
|
|
120
|
+
consumer: Consumer
|
|
121
|
+
): Promise<ResolutionDetails<string>> {
|
|
98
122
|
if (!consumer.key) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
reason: StandardResolutionReasons.ERROR,
|
|
103
|
-
errorCode: 'TARGETING_KEY_MISSING'
|
|
104
|
-
}
|
|
105
|
-
return details;
|
|
123
|
+
throw new TargetingKeyMissingError(
|
|
124
|
+
"The Split provider requires a targeting key."
|
|
125
|
+
);
|
|
106
126
|
} else {
|
|
107
127
|
await this.initialized;
|
|
108
|
-
const value = this.client.getTreatment(
|
|
128
|
+
const value = this.client.getTreatment(
|
|
129
|
+
consumer.key,
|
|
130
|
+
flagKey,
|
|
131
|
+
consumer.attributes
|
|
132
|
+
);
|
|
109
133
|
const details: ResolutionDetails<string> = {
|
|
110
134
|
value: value,
|
|
111
135
|
variant: value,
|
|
112
|
-
reason: StandardResolutionReasons.TARGETING_MATCH
|
|
136
|
+
reason: StandardResolutionReasons.TARGETING_MATCH,
|
|
113
137
|
};
|
|
114
138
|
return details;
|
|
115
139
|
}
|
|
@@ -136,14 +160,16 @@ export class OpenFeatureSplitProvider implements Provider {
|
|
|
136
160
|
return result;
|
|
137
161
|
}
|
|
138
162
|
|
|
139
|
-
private parseValidJsonObject<T extends JsonValue>(
|
|
163
|
+
private parseValidJsonObject<T extends JsonValue>(
|
|
164
|
+
stringValue: string | undefined
|
|
165
|
+
): T {
|
|
140
166
|
if (stringValue === undefined) {
|
|
141
167
|
throw new ParseError(`Invalid 'undefined' JSON value.`);
|
|
142
168
|
}
|
|
143
169
|
// we may want to allow the parsing to be customized.
|
|
144
170
|
try {
|
|
145
171
|
const value = JSON.parse(stringValue);
|
|
146
|
-
if (typeof value !==
|
|
172
|
+
if (typeof value !== "object") {
|
|
147
173
|
throw new ParseError(
|
|
148
174
|
`Flag value ${stringValue} had unexpected type ${typeof value}, expected "object"`
|
|
149
175
|
);
|
package/types/index.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Declaration file for Javascript and Node OpenFeature Split Provider
|
|
2
|
-
// Project: http://www.split.io/
|
|
3
|
-
|
|
4
|
-
import { Provider } from "@openfeature/js-sdk";
|
|
5
|
-
|
|
6
|
-
export = SplitProvider;
|
|
7
|
-
|
|
8
|
-
declare module SplitProvider {
|
|
9
|
-
export interface SplitProviderOptions {
|
|
10
|
-
splitClient: SplitIO.IClient;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* OpenFeature Split Provider constructor.
|
|
15
|
-
*/
|
|
16
|
-
export function OpenFeatureSplitProvider(options: SplitProviderOptions): Provider;
|
|
17
|
-
}
|