@datadog/openfeature-node-server 0.1.0-preview.10
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 +3 -0
- package/cjs/configuration/evaluateForSubject.d.ts +7 -0
- package/cjs/configuration/evaluateForSubject.d.ts.map +1 -0
- package/cjs/configuration/evaluateForSubject.js +159 -0
- package/cjs/configuration/evaluateForSubject.js.map +1 -0
- package/cjs/configuration/evaluation.d.ts +5 -0
- package/cjs/configuration/evaluation.d.ts.map +1 -0
- package/cjs/configuration/evaluation.js +40 -0
- package/cjs/configuration/evaluation.js.map +1 -0
- package/cjs/configuration/ufc-v1.d.ts +53 -0
- package/cjs/configuration/ufc-v1.d.ts.map +1 -0
- package/cjs/configuration/ufc-v1.js +19 -0
- package/cjs/configuration/ufc-v1.js.map +1 -0
- package/cjs/index.d.ts +3 -0
- package/cjs/index.d.ts.map +1 -0
- package/cjs/index.js +20 -0
- package/cjs/index.js.map +1 -0
- package/cjs/provider.d.ts +52 -0
- package/cjs/provider.d.ts.map +1 -0
- package/cjs/provider.js +128 -0
- package/cjs/provider.js.map +1 -0
- package/cjs/rules/rules.d.ts +51 -0
- package/cjs/rules/rules.d.ts.map +1 -0
- package/cjs/rules/rules.js +71 -0
- package/cjs/rules/rules.js.map +1 -0
- package/cjs/shards/matchesShard.d.ts +4 -0
- package/cjs/shards/matchesShard.d.ts.map +1 -0
- package/cjs/shards/matchesShard.js +16 -0
- package/cjs/shards/matchesShard.js.map +1 -0
- package/cjs/shards/sharders.d.ts +12 -0
- package/cjs/shards/sharders.d.ts.map +1 -0
- package/cjs/shards/sharders.js +30 -0
- package/cjs/shards/sharders.js.map +1 -0
- package/esm/configuration/evaluateForSubject.d.ts +7 -0
- package/esm/configuration/evaluateForSubject.d.ts.map +1 -0
- package/esm/configuration/evaluateForSubject.js +155 -0
- package/esm/configuration/evaluateForSubject.js.map +1 -0
- package/esm/configuration/evaluation.d.ts +5 -0
- package/esm/configuration/evaluation.d.ts.map +1 -0
- package/esm/configuration/evaluation.js +37 -0
- package/esm/configuration/evaluation.js.map +1 -0
- package/esm/configuration/ufc-v1.d.ts +53 -0
- package/esm/configuration/ufc-v1.d.ts.map +1 -0
- package/esm/configuration/ufc-v1.js +16 -0
- package/esm/configuration/ufc-v1.js.map +1 -0
- package/esm/index.d.ts +3 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +4 -0
- package/esm/index.js.map +1 -0
- package/esm/provider.d.ts +52 -0
- package/esm/provider.d.ts.map +1 -0
- package/esm/provider.js +124 -0
- package/esm/provider.js.map +1 -0
- package/esm/rules/rules.d.ts +51 -0
- package/esm/rules/rules.d.ts.map +1 -0
- package/esm/rules/rules.js +67 -0
- package/esm/rules/rules.js.map +1 -0
- package/esm/shards/matchesShard.d.ts +4 -0
- package/esm/shards/matchesShard.d.ts.map +1 -0
- package/esm/shards/matchesShard.js +13 -0
- package/esm/shards/matchesShard.js.map +1 -0
- package/esm/shards/sharders.d.ts +12 -0
- package/esm/shards/sharders.d.ts.map +1 -0
- package/esm/shards/sharders.js +24 -0
- package/esm/shards/sharders.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FlagTypeToValue } from '@datadog/flagging-core';
|
|
2
|
+
import { type EvaluationContext, type FlagValueType, type Logger, type ResolutionDetails } from '@openfeature/server-sdk';
|
|
3
|
+
import { type Rule } from '../rules/rules';
|
|
4
|
+
import { type Flag } from './ufc-v1';
|
|
5
|
+
export declare function evaluateForSubject<T extends FlagValueType>(flag: Flag | undefined, type: T, subjectKey: string, subjectAttributes: EvaluationContext, defaultValue: FlagTypeToValue<T>, logger: Logger): ResolutionDetails<FlagTypeToValue<T>>;
|
|
6
|
+
export declare function containsMatchingRule(rules: Rule[] | undefined, subjectAttributes: EvaluationContext, logger: Logger): boolean;
|
|
7
|
+
//# sourceMappingURL=evaluateForSubject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateForSubject.d.ts","sourceRoot":"","sources":["../../src/configuration/evaluateForSubject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA2B,MAAM,wBAAwB,CAAA;AACtF,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,iBAAiB,EAEvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAEvD,OAAO,EAAE,KAAK,IAAI,EAA4D,MAAM,UAAU,CAAA;AAE9F,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,aAAa,EACxD,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,IAAI,EAAE,CAAC,EACP,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,iBAAiB,EACpC,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,EAChC,MAAM,EAAE,MAAM,GACb,iBAAiB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CA8FvC;AAkBD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,EACzB,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,EAAE,MAAM,GACb,OAAO,CAST"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.evaluateForSubject = evaluateForSubject;
|
|
4
|
+
exports.containsMatchingRule = containsMatchingRule;
|
|
5
|
+
const server_sdk_1 = require("@openfeature/server-sdk");
|
|
6
|
+
const rules_1 = require("../rules/rules");
|
|
7
|
+
const matchesShard_1 = require("../shards/matchesShard");
|
|
8
|
+
const ufc_v1_1 = require("./ufc-v1");
|
|
9
|
+
function evaluateForSubject(flag, type, subjectKey, subjectAttributes, defaultValue, logger) {
|
|
10
|
+
if (!(flag === null || flag === void 0 ? void 0 : flag.enabled)) {
|
|
11
|
+
logger.debug(`returning default assignment because flag is disabled`, {
|
|
12
|
+
flagKey: flag ? flag.key : 'undefined',
|
|
13
|
+
subjectKey,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
value: defaultValue,
|
|
17
|
+
reason: server_sdk_1.StandardResolutionReasons.DISABLED,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const isValid = validateTypeMatch(type, flag.variationType);
|
|
21
|
+
if (!isValid) {
|
|
22
|
+
logger.debug(`variant value type mismatch, returning default value`, {
|
|
23
|
+
flagKey: flag.key,
|
|
24
|
+
subjectKey,
|
|
25
|
+
expectedType: type,
|
|
26
|
+
variantType: flag.variationType,
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
value: defaultValue,
|
|
30
|
+
reason: server_sdk_1.StandardResolutionReasons.ERROR,
|
|
31
|
+
errorCode: server_sdk_1.ErrorCode.TYPE_MISMATCH,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const now = new Date();
|
|
35
|
+
for (const allocation of flag.allocations) {
|
|
36
|
+
if (allocation.startAt && now < new Date(allocation.startAt)) {
|
|
37
|
+
logger.debug(`allocation before start date`, {
|
|
38
|
+
flagKey: flag.key,
|
|
39
|
+
subjectKey,
|
|
40
|
+
allocationKey: allocation.key,
|
|
41
|
+
startAt: allocation.startAt,
|
|
42
|
+
});
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (allocation.endAt && now >= new Date(allocation.endAt)) {
|
|
46
|
+
logger.debug(`allocation after end date`, {
|
|
47
|
+
flagKey: flag.key,
|
|
48
|
+
subjectKey,
|
|
49
|
+
allocationKey: allocation.key,
|
|
50
|
+
endAt: allocation.endAt,
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const matched = containsMatchingRule(allocation.rules, subjectAttributes, logger);
|
|
55
|
+
if (!matched) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const selectedSplit = selectSplitUsingSharding(allocation.splits, subjectKey, flag.key, logger);
|
|
59
|
+
if (selectedSplit) {
|
|
60
|
+
const variant = flag.variations[selectedSplit.variationKey];
|
|
61
|
+
if (variant) {
|
|
62
|
+
logger.debug(`evaluated a flag`, {
|
|
63
|
+
flagKey: flag.key,
|
|
64
|
+
subjectKey,
|
|
65
|
+
assignment: variant.value,
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
value: variant.value,
|
|
69
|
+
reason: server_sdk_1.StandardResolutionReasons.TARGETING_MATCH,
|
|
70
|
+
variant: variant.key,
|
|
71
|
+
flagMetadata: {
|
|
72
|
+
allocationKey: allocation.key,
|
|
73
|
+
variationType: (0, ufc_v1_1.variantTypeToFlagValueType)(flag.variationType),
|
|
74
|
+
doLog: !!allocation.doLog,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
logger.debug(`no matching split found for subject`, {
|
|
81
|
+
flagKey: flag.key,
|
|
82
|
+
subjectKey,
|
|
83
|
+
allocationKey: allocation.key,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// This shouldn't happen since a default allocation is generated by the server
|
|
88
|
+
logger.debug(`returning default assignment because no allocation matched`, {
|
|
89
|
+
flagKey: flag.key,
|
|
90
|
+
subjectKey,
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
value: defaultValue,
|
|
94
|
+
reason: server_sdk_1.StandardResolutionReasons.DEFAULT,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function validateTypeMatch(expectedType, variantType) {
|
|
98
|
+
if (expectedType === 'boolean') {
|
|
99
|
+
return variantType === 'BOOLEAN';
|
|
100
|
+
}
|
|
101
|
+
if (expectedType === 'string') {
|
|
102
|
+
return variantType === 'STRING';
|
|
103
|
+
}
|
|
104
|
+
if (expectedType === 'number') {
|
|
105
|
+
return variantType === 'INTEGER' || variantType === 'NUMERIC';
|
|
106
|
+
}
|
|
107
|
+
if (expectedType === 'object') {
|
|
108
|
+
return variantType === 'JSON';
|
|
109
|
+
}
|
|
110
|
+
throw new Error(`Invalid expected type: ${expectedType}`);
|
|
111
|
+
}
|
|
112
|
+
function containsMatchingRule(rules, subjectAttributes, logger) {
|
|
113
|
+
if (!(rules === null || rules === void 0 ? void 0 : rules.length)) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
logger.debug(`evaluating rules`, {
|
|
117
|
+
rules: JSON.stringify(rules),
|
|
118
|
+
subjectAttributes,
|
|
119
|
+
});
|
|
120
|
+
return rules.some((rule) => (0, rules_1.matchesRule)(rule, subjectAttributes));
|
|
121
|
+
}
|
|
122
|
+
function selectSplitUsingSharding(splits, subjectKey, flagKey, logger) {
|
|
123
|
+
if (!splits || splits.length === 0) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
for (const split of splits) {
|
|
127
|
+
logger.debug(`evaluating split sharding`, {
|
|
128
|
+
flagKey,
|
|
129
|
+
subjectKey,
|
|
130
|
+
variationKey: split.variationKey,
|
|
131
|
+
shards: split.shards,
|
|
132
|
+
});
|
|
133
|
+
const matches = split.shards.every((shard) => {
|
|
134
|
+
const shardMatches = (0, matchesShard_1.matchesShard)(shard, subjectKey);
|
|
135
|
+
logger.debug(`shard match result`, {
|
|
136
|
+
flagKey,
|
|
137
|
+
subjectKey,
|
|
138
|
+
variationKey: split.variationKey,
|
|
139
|
+
shard: shard,
|
|
140
|
+
matches: shardMatches,
|
|
141
|
+
});
|
|
142
|
+
return shardMatches;
|
|
143
|
+
});
|
|
144
|
+
if (matches) {
|
|
145
|
+
logger.debug(`subject matches split`, {
|
|
146
|
+
flagKey,
|
|
147
|
+
subjectKey,
|
|
148
|
+
variationKey: split.variationKey,
|
|
149
|
+
});
|
|
150
|
+
return split;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
logger.debug(`subject matches no splits`, {
|
|
154
|
+
flagKey,
|
|
155
|
+
subjectKey,
|
|
156
|
+
});
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=evaluateForSubject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateForSubject.js","sourceRoot":"","sources":["../../src/configuration/evaluateForSubject.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FlagTypeToValue } from '@datadog/flagging-core';
|
|
2
|
+
import { type EvaluationContext, type FlagValueType, type Logger, type ResolutionDetails } from '@openfeature/server-sdk';
|
|
3
|
+
import type { UniversalFlagConfigurationV1 } from './ufc-v1';
|
|
4
|
+
export declare function evaluate<T extends FlagValueType>(config: UniversalFlagConfigurationV1 | undefined, type: T, flagKey: string, defaultValue: FlagTypeToValue<T>, context: EvaluationContext, logger: Logger): ResolutionDetails<FlagTypeToValue<T>>;
|
|
5
|
+
//# sourceMappingURL=evaluation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluation.d.ts","sourceRoot":"","sources":["../../src/configuration/evaluation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,iBAAiB,EAEvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAA;AAE5D,wBAAgB,QAAQ,CAAC,CAAC,SAAS,aAAa,EAC9C,MAAM,EAAE,4BAA4B,GAAG,SAAS,EAChD,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,EAChC,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,MAAM,GACb,iBAAiB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAyCvC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.evaluate = evaluate;
|
|
4
|
+
const server_sdk_1 = require("@openfeature/server-sdk");
|
|
5
|
+
const evaluateForSubject_1 = require("./evaluateForSubject");
|
|
6
|
+
function evaluate(config, type, flagKey, defaultValue, context, logger) {
|
|
7
|
+
if (!config) {
|
|
8
|
+
return {
|
|
9
|
+
value: defaultValue,
|
|
10
|
+
reason: 'ERROR',
|
|
11
|
+
errorCode: server_sdk_1.ErrorCode.PROVIDER_NOT_READY,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const { targetingKey: subjectKey, ...remainingContext } = context;
|
|
15
|
+
if (!subjectKey) {
|
|
16
|
+
return {
|
|
17
|
+
value: defaultValue,
|
|
18
|
+
reason: 'ERROR',
|
|
19
|
+
errorCode: server_sdk_1.ErrorCode.TARGETING_KEY_MISSING,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Include the subjectKey as an "id" attribute for rule matching
|
|
23
|
+
const subjectAttributes = {
|
|
24
|
+
id: subjectKey,
|
|
25
|
+
...remainingContext,
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
const resultWithDetails = (0, evaluateForSubject_1.evaluateForSubject)(config.flags[flagKey], type, subjectKey, subjectAttributes, defaultValue, logger);
|
|
29
|
+
return resultWithDetails;
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
logger.error('Error evaluating flag', { error });
|
|
33
|
+
return {
|
|
34
|
+
value: defaultValue,
|
|
35
|
+
reason: server_sdk_1.StandardResolutionReasons.ERROR,
|
|
36
|
+
errorCode: server_sdk_1.ErrorCode.GENERAL,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=evaluation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluation.js","sourceRoot":"","sources":["../../src/configuration/evaluation.ts"],"names":[],"mappings":";;AAYA,4BAgDC;AA3DD,wDAOgC;AAChC,6DAAyD;AAGzD,SAAgB,QAAQ,CACtB,MAAgD,EAChD,IAAO,EACP,OAAe,EACf,YAAgC,EAChC,OAA0B,EAC1B,MAAc;IAEd,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,OAAO;YACf,SAAS,EAAE,sBAAS,CAAC,kBAAkB;SACxC,CAAA;IACH,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAA;IACjE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,OAAO;YACf,SAAS,EAAE,sBAAS,CAAC,qBAAqB;SAC3C,CAAA;IACH,CAAC;IAED,gEAAgE;IAChE,MAAM,iBAAiB,GAAG;QACxB,EAAE,EAAE,UAAU;QACd,GAAG,gBAAgB;KACpB,CAAA;IACD,IAAI,CAAC;QACH,MAAM,iBAAiB,GAAG,IAAA,uCAAkB,EAC1C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EACrB,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,MAAM,CACP,CAAA;QACD,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAChD,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,sCAAyB,CAAC,KAAK;YACvC,SAAS,EAAE,sBAAS,CAAC,OAAO;SAC7B,CAAA;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { FlagValue, FlagValueType } from '@openfeature/core';
|
|
2
|
+
import type { Rule } from '../rules/rules';
|
|
3
|
+
export type VariantType = 'BOOLEAN' | 'INTEGER' | 'NUMERIC' | 'STRING' | 'JSON';
|
|
4
|
+
export interface VariantConfiguration {
|
|
5
|
+
key: string;
|
|
6
|
+
value: FlagValue;
|
|
7
|
+
}
|
|
8
|
+
export interface ShardRange {
|
|
9
|
+
start: number;
|
|
10
|
+
end: number;
|
|
11
|
+
}
|
|
12
|
+
export interface Shard {
|
|
13
|
+
salt: string;
|
|
14
|
+
ranges: ShardRange[];
|
|
15
|
+
totalShards: number;
|
|
16
|
+
}
|
|
17
|
+
export interface Split {
|
|
18
|
+
variationKey: string;
|
|
19
|
+
shards: Shard[];
|
|
20
|
+
extraLogging?: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
export interface Allocation {
|
|
23
|
+
key: string;
|
|
24
|
+
rules?: Rule[];
|
|
25
|
+
startAt?: Date;
|
|
26
|
+
endAt?: Date;
|
|
27
|
+
splits: Split[];
|
|
28
|
+
doLog?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface Flag {
|
|
31
|
+
key: string;
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
variationType: VariantType;
|
|
34
|
+
variations: Record<string, VariantConfiguration>;
|
|
35
|
+
allocations: Allocation[];
|
|
36
|
+
}
|
|
37
|
+
export interface UniversalFlagConfigurationV1 {
|
|
38
|
+
createdAt: string;
|
|
39
|
+
format: string;
|
|
40
|
+
environment: {
|
|
41
|
+
name: string;
|
|
42
|
+
};
|
|
43
|
+
flags: Record<string, Flag>;
|
|
44
|
+
}
|
|
45
|
+
export interface UniversalFlagConfigurationV1Response {
|
|
46
|
+
data: {
|
|
47
|
+
type: 'universal-flag-configuration';
|
|
48
|
+
id: string;
|
|
49
|
+
attributes: UniversalFlagConfigurationV1;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export declare function variantTypeToFlagValueType(variantType: VariantType): FlagValueType;
|
|
53
|
+
//# sourceMappingURL=ufc-v1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ufc-v1.d.ts","sourceRoot":"","sources":["../../src/configuration/ufc-v1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE/E,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,WAAW,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IAChD,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;CAC5B;AAED,MAAM,WAAW,oCAAoC;IACnD,IAAI,EAAE;QACJ,IAAI,EAAE,8BAA8B,CAAA;QACpC,EAAE,EAAE,MAAM,CAAA;QACV,UAAU,EAAE,4BAA4B,CAAA;KACzC,CAAA;CACF;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,CAclF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.variantTypeToFlagValueType = variantTypeToFlagValueType;
|
|
4
|
+
function variantTypeToFlagValueType(variantType) {
|
|
5
|
+
if (variantType === 'BOOLEAN') {
|
|
6
|
+
return 'boolean';
|
|
7
|
+
}
|
|
8
|
+
if (variantType === 'STRING') {
|
|
9
|
+
return 'string';
|
|
10
|
+
}
|
|
11
|
+
if (variantType === 'INTEGER' || variantType === 'NUMERIC') {
|
|
12
|
+
return 'number';
|
|
13
|
+
}
|
|
14
|
+
if (variantType === 'JSON') {
|
|
15
|
+
return 'object';
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`Cannot convert variant type to flag value type: ${variantType}`);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ufc-v1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ufc-v1.js","sourceRoot":"","sources":["../../src/configuration/ufc-v1.ts"],"names":[],"mappings":";;AA6DA,gEAcC;AAdD,SAAgB,0BAA0B,CAAC,WAAwB;IACjE,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,mDAAmD,WAAW,EAAE,CAAC,CAAA;AACnF,CAAC"}
|
package/cjs/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAA;AAC1E,cAAc,YAAY,CAAA"}
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./provider"), exports);
|
|
18
|
+
// Build environment placeholder for testing
|
|
19
|
+
const _SDK_VERSION = "dev";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
package/cjs/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,6CAA0B;AAE1B,4CAA4C;AAC5C,MAAM,YAAY,GAAG,0BAA0B,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Channel } from 'node:diagnostics_channel';
|
|
2
|
+
import { type ExposureEvent } from '@datadog/flagging-core';
|
|
3
|
+
import type { EvaluationContext } from '@openfeature/core';
|
|
4
|
+
import type { Hook, JsonValue, Logger, Paradigm, Provider, ProviderEventEmitter, ProviderMetadata, ResolutionDetails } from '@openfeature/server-sdk';
|
|
5
|
+
import { ProviderEvents } from '@openfeature/server-sdk';
|
|
6
|
+
import type { UniversalFlagConfigurationV1 } from './configuration/ufc-v1';
|
|
7
|
+
export interface DatadogNodeServerProviderOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Log experiment exposures
|
|
10
|
+
*/
|
|
11
|
+
exposureChannel: Channel<ExposureEvent>;
|
|
12
|
+
}
|
|
13
|
+
export declare class DatadogNodeServerProvider implements Provider {
|
|
14
|
+
private readonly options;
|
|
15
|
+
readonly metadata: ProviderMetadata;
|
|
16
|
+
readonly runsOn: Paradigm;
|
|
17
|
+
readonly hooks?: Hook[];
|
|
18
|
+
private resolveInitialization?;
|
|
19
|
+
private rejectInitialization?;
|
|
20
|
+
readonly events: ProviderEventEmitter<ProviderEvents>;
|
|
21
|
+
private readonly exposureCache;
|
|
22
|
+
private configuration?;
|
|
23
|
+
constructor(options: DatadogNodeServerProviderOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Used by dd-source-js
|
|
26
|
+
*/
|
|
27
|
+
getConfiguration(): UniversalFlagConfigurationV1 | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Used by dd-source-js
|
|
30
|
+
*/
|
|
31
|
+
setConfiguration(configuration: UniversalFlagConfigurationV1): void;
|
|
32
|
+
/**
|
|
33
|
+
* Used by dd-source-js
|
|
34
|
+
*/
|
|
35
|
+
setError(error: unknown): void;
|
|
36
|
+
/**
|
|
37
|
+
* Used by the OpenFeature SDK to set the status based on initialization.
|
|
38
|
+
* Status of 'PROVIDER_READY' is emitted with a resolved promise.
|
|
39
|
+
* Status of 'PROVIDER_ERROR' is emitted with a rejected promise.
|
|
40
|
+
*
|
|
41
|
+
* Since we aren't loading the configuration in this Provider, we will simulate
|
|
42
|
+
* loading functionality via resolveInitialization and rejectInitialization.
|
|
43
|
+
* See setConfiguration and setError for more details.
|
|
44
|
+
*/
|
|
45
|
+
initialize(): Promise<void>;
|
|
46
|
+
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, _logger: Logger): Promise<ResolutionDetails<boolean>>;
|
|
47
|
+
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, _logger: Logger): Promise<ResolutionDetails<string>>;
|
|
48
|
+
resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, _logger: Logger): Promise<ResolutionDetails<number>>;
|
|
49
|
+
resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext, _logger: Logger): Promise<ResolutionDetails<T>>;
|
|
50
|
+
private handleExposure;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,KAAK,EAGV,IAAI,EACJ,SAAS,EACT,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAA2B,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAEjF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAA;AAE1E,MAAM,WAAW,gCAAgC;IAC/C;;OAEG;IACH,eAAe,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;CACxC;AAED,qBAAa,yBAA0B,YAAW,QAAQ;IAc5C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAbpC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAElC;IACD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAW;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IAEvB,OAAO,CAAC,qBAAqB,CAAC,CAA4C;IAC1E,OAAO,CAAC,oBAAoB,CAAC,CAA4B;IACzD,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC,cAAc,CAAC,CAAA;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAE3D,OAAO,CAAC,aAAa,CAAC,CAA0C;gBAEnC,OAAO,EAAE,gCAAgC;IAMtE;;OAEG;IACH,gBAAgB;IAIhB;;OAEG;IACH,gBAAgB,CAAC,aAAa,EAAE,4BAA4B;IAmB5D;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO;IAUvB;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,wBAAwB,CAC5B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAMhC,uBAAuB,CAC3B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAM/B,uBAAuB,CAC3B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAM/B,uBAAuB,CAAC,CAAC,SAAS,SAAS,EAC/C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAmBhC,OAAO,CAAC,cAAc;CAwBvB"}
|
package/cjs/provider.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DatadogNodeServerProvider = void 0;
|
|
4
|
+
const flagging_core_1 = require("@datadog/flagging-core");
|
|
5
|
+
const server_sdk_1 = require("@openfeature/server-sdk");
|
|
6
|
+
const evaluation_1 = require("./configuration/evaluation");
|
|
7
|
+
class DatadogNodeServerProvider {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.metadata = {
|
|
11
|
+
name: 'datadog-node-server',
|
|
12
|
+
};
|
|
13
|
+
this.runsOn = 'server';
|
|
14
|
+
this.hooks = [];
|
|
15
|
+
this.events = new server_sdk_1.OpenFeatureEventEmitter();
|
|
16
|
+
this.exposureCache = new flagging_core_1.LRUInMemoryAssignmentCache(50000);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Used by dd-source-js
|
|
20
|
+
*/
|
|
21
|
+
getConfiguration() {
|
|
22
|
+
return this.configuration;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Used by dd-source-js
|
|
26
|
+
*/
|
|
27
|
+
setConfiguration(configuration) {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const prevCreatedAt = (_a = this.configuration) === null || _a === void 0 ? void 0 : _a.createdAt;
|
|
30
|
+
if (this.configuration && this.configuration !== configuration) {
|
|
31
|
+
this.events.emit(server_sdk_1.ProviderEvents.ConfigurationChanged);
|
|
32
|
+
const newCreatedAt = configuration === null || configuration === void 0 ? void 0 : configuration.createdAt;
|
|
33
|
+
if (prevCreatedAt !== newCreatedAt) {
|
|
34
|
+
(_b = this.exposureCache) === null || _b === void 0 ? void 0 : _b.clear();
|
|
35
|
+
}
|
|
36
|
+
this.configuration = configuration;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.configuration = configuration;
|
|
40
|
+
if (this.resolveInitialization) {
|
|
41
|
+
this.resolveInitialization();
|
|
42
|
+
this.resolveInitialization = undefined;
|
|
43
|
+
this.rejectInitialization = undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Used by dd-source-js
|
|
48
|
+
*/
|
|
49
|
+
setError(error) {
|
|
50
|
+
if (this.rejectInitialization) {
|
|
51
|
+
this.rejectInitialization(error);
|
|
52
|
+
this.resolveInitialization = undefined;
|
|
53
|
+
this.rejectInitialization = undefined;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.events.emit(server_sdk_1.ProviderEvents.Error, { error });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Used by the OpenFeature SDK to set the status based on initialization.
|
|
61
|
+
* Status of 'PROVIDER_READY' is emitted with a resolved promise.
|
|
62
|
+
* Status of 'PROVIDER_ERROR' is emitted with a rejected promise.
|
|
63
|
+
*
|
|
64
|
+
* Since we aren't loading the configuration in this Provider, we will simulate
|
|
65
|
+
* loading functionality via resolveInitialization and rejectInitialization.
|
|
66
|
+
* See setConfiguration and setError for more details.
|
|
67
|
+
*/
|
|
68
|
+
async initialize() {
|
|
69
|
+
var _a;
|
|
70
|
+
if (this.configuration) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
await new Promise((resolve, reject) => {
|
|
74
|
+
this.resolveInitialization = resolve;
|
|
75
|
+
this.rejectInitialization = reject;
|
|
76
|
+
});
|
|
77
|
+
await ((_a = this.exposureCache) === null || _a === void 0 ? void 0 : _a.init());
|
|
78
|
+
}
|
|
79
|
+
async resolveBooleanEvaluation(flagKey, defaultValue, context, _logger) {
|
|
80
|
+
const resolutionDetails = (0, evaluation_1.evaluate)(this.configuration, 'boolean', flagKey, defaultValue, context, _logger);
|
|
81
|
+
this.handleExposure(flagKey, context, resolutionDetails);
|
|
82
|
+
return resolutionDetails;
|
|
83
|
+
}
|
|
84
|
+
async resolveStringEvaluation(flagKey, defaultValue, context, _logger) {
|
|
85
|
+
const resolutionDetails = (0, evaluation_1.evaluate)(this.configuration, 'string', flagKey, defaultValue, context, _logger);
|
|
86
|
+
this.handleExposure(flagKey, context, resolutionDetails);
|
|
87
|
+
return resolutionDetails;
|
|
88
|
+
}
|
|
89
|
+
async resolveNumberEvaluation(flagKey, defaultValue, context, _logger) {
|
|
90
|
+
const resolutionDetails = (0, evaluation_1.evaluate)(this.configuration, 'number', flagKey, defaultValue, context, _logger);
|
|
91
|
+
this.handleExposure(flagKey, context, resolutionDetails);
|
|
92
|
+
return resolutionDetails;
|
|
93
|
+
}
|
|
94
|
+
async resolveObjectEvaluation(flagKey, defaultValue, context, _logger) {
|
|
95
|
+
// type safety: OpenFeature interface requires us to return a
|
|
96
|
+
// specific T for *any* value of T (which could be any subtype of
|
|
97
|
+
// JsonValue). We can't even theoretically implement it in a
|
|
98
|
+
// type-sound way because there's no runtime information passed to
|
|
99
|
+
// learn what type the user expects. So it's up to the user to
|
|
100
|
+
// make sure they pass the appropriate type.
|
|
101
|
+
const resolutionDetails = (0, evaluation_1.evaluate)(this.configuration, 'object', flagKey, defaultValue, context, _logger);
|
|
102
|
+
this.handleExposure(flagKey, context, resolutionDetails);
|
|
103
|
+
return resolutionDetails;
|
|
104
|
+
}
|
|
105
|
+
handleExposure(flagKey, context, resolutionDetails) {
|
|
106
|
+
var _a, _b, _c;
|
|
107
|
+
const timestamp = Date.now();
|
|
108
|
+
const evalutationDetails = {
|
|
109
|
+
...resolutionDetails,
|
|
110
|
+
flagKey: flagKey,
|
|
111
|
+
flagMetadata: (_a = resolutionDetails.flagMetadata) !== null && _a !== void 0 ? _a : {},
|
|
112
|
+
};
|
|
113
|
+
const exposureEvent = (0, flagging_core_1.createExposureEvent)(context, evalutationDetails);
|
|
114
|
+
if (!exposureEvent) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const hasLoggedAssignment = (_b = this.exposureCache) === null || _b === void 0 ? void 0 : _b.has(exposureEvent);
|
|
118
|
+
if (hasLoggedAssignment) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (this.options.exposureChannel.hasSubscribers) {
|
|
122
|
+
this.options.exposureChannel.publish({ ...exposureEvent, timestamp });
|
|
123
|
+
(_c = this.exposureCache) === null || _c === void 0 ? void 0 : _c.set(exposureEvent);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.DatadogNodeServerProvider = DatadogNodeServerProvider;
|
|
128
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":";;;AACA,0DAK+B;AAc/B,wDAAiF;AACjF,2DAAqD;AAUrD,MAAa,yBAAyB;IAcpC,YAA6B,OAAyC;QAAzC,YAAO,GAAP,OAAO,CAAkC;QAb7D,aAAQ,GAAqB;YACpC,IAAI,EAAE,qBAAqB;SAC5B,CAAA;QACQ,WAAM,GAAa,QAAQ,CAAA;QAWlC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QACf,IAAI,CAAC,MAAM,GAAG,IAAI,oCAAuB,EAAE,CAAA;QAC3C,IAAI,CAAC,aAAa,GAAG,IAAI,0CAA0B,CAAC,KAAM,CAAC,CAAA;IAC7D,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,aAAa,CAAA;IAC3B,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,aAA2C;;QAC1D,MAAM,aAAa,GAAG,MAAA,IAAI,CAAC,aAAa,0CAAE,SAAS,CAAA;QACnD,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,KAAK,aAAa,EAAE,CAAC;YAC/D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAAc,CAAC,oBAAoB,CAAC,CAAA;YACrD,MAAM,YAAY,GAAG,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,SAAS,CAAA;YAC7C,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;gBACnC,MAAA,IAAI,CAAC,aAAa,0CAAE,KAAK,EAAE,CAAA;YAC7B,CAAC;YACD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;YAClC,OAAM;QACR,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;QAClC,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC/B,IAAI,CAAC,qBAAqB,EAAE,CAAA;YAC5B,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAA;YACtC,IAAI,CAAC,oBAAoB,GAAG,SAAS,CAAA;QACvC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,KAAc;QACrB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;YAChC,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAA;YACtC,IAAI,CAAC,oBAAoB,GAAG,SAAS,CAAA;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAAc,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,UAAU;;QACd,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACpC,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAA;YACpC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAA;QACpC,CAAC,CAAC,CAAA;QACF,MAAM,CAAA,MAAA,IAAI,CAAC,aAAa,0CAAE,IAAI,EAAE,CAAA,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,wBAAwB,CAC5B,OAAe,EACf,YAAqB,EACrB,OAA0B,EAC1B,OAAe;QAEf,MAAM,iBAAiB,GAAG,IAAA,qBAAQ,EAAC,IAAI,CAAC,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QAC1G,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAA;QACxD,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,uBAAuB,CAC3B,OAAe,EACf,YAAoB,EACpB,OAA0B,EAC1B,OAAe;QAEf,MAAM,iBAAiB,GAAG,IAAA,qBAAQ,EAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QACzG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAA;QACxD,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,uBAAuB,CAC3B,OAAe,EACf,YAAoB,EACpB,OAA0B,EAC1B,OAAe;QAEf,MAAM,iBAAiB,GAAG,IAAA,qBAAQ,EAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QACzG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAA;QACxD,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,uBAAuB,CAC3B,OAAe,EACf,YAAe,EACf,OAA0B,EAC1B,OAAe;QAEf,6DAA6D;QAC7D,iEAAiE;QACjE,4DAA4D;QAC5D,kEAAkE;QAClE,8DAA8D;QAC9D,4CAA4C;QAC5C,MAAM,iBAAiB,GAAG,IAAA,qBAAQ,EAChC,IAAI,CAAC,aAAa,EAClB,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,OAAO,EACP,OAAO,CACgB,CAAA;QACzB,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAA;QACxD,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAEO,cAAc,CACpB,OAAe,EACf,OAA0B,EAC1B,iBAAuC;;QAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,MAAM,kBAAkB,GAAyB;YAC/C,GAAG,iBAAiB;YACpB,OAAO,EAAE,OAAO;YAChB,YAAY,EAAE,MAAA,iBAAiB,CAAC,YAAY,mCAAI,EAAE;SACnD,CAAA;QACD,MAAM,aAAa,GAAG,IAAA,mCAAmB,EAAC,OAAO,EAAE,kBAAkB,CAAC,CAAA;QACtE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAM;QACR,CAAC;QACD,MAAM,mBAAmB,GAAG,MAAA,IAAI,CAAC,aAAa,0CAAE,GAAG,CAAC,aAAa,CAAC,CAAA;QAClE,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAM;QACR,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC;YAChD,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,GAAG,aAAa,EAAE,SAAS,EAAE,CAAC,CAAA;YACrE,MAAA,IAAI,CAAC,aAAa,0CAAE,GAAG,CAAC,aAAa,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;CACF;AAnKD,8DAmKC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { EvaluationContext, EvaluationContextValue } from '@openfeature/server-sdk';
|
|
2
|
+
export type ConditionValueType = EvaluationContextValue | EvaluationContextValue[];
|
|
3
|
+
export declare enum OperatorType {
|
|
4
|
+
MATCHES = "MATCHES",
|
|
5
|
+
NOT_MATCHES = "NOT_MATCHES",
|
|
6
|
+
GTE = "GTE",
|
|
7
|
+
GT = "GT",
|
|
8
|
+
LTE = "LTE",
|
|
9
|
+
LT = "LT",
|
|
10
|
+
ONE_OF = "ONE_OF",
|
|
11
|
+
NOT_ONE_OF = "NOT_ONE_OF",
|
|
12
|
+
IS_NULL = "IS_NULL"
|
|
13
|
+
}
|
|
14
|
+
type NumericOperator = OperatorType.GTE | OperatorType.GT | OperatorType.LTE | OperatorType.LT;
|
|
15
|
+
type MatchesCondition = {
|
|
16
|
+
operator: OperatorType.MATCHES;
|
|
17
|
+
attribute: string;
|
|
18
|
+
value: string;
|
|
19
|
+
};
|
|
20
|
+
type NotMatchesCondition = {
|
|
21
|
+
operator: OperatorType.NOT_MATCHES;
|
|
22
|
+
attribute: string;
|
|
23
|
+
value: string;
|
|
24
|
+
};
|
|
25
|
+
type OneOfCondition = {
|
|
26
|
+
operator: OperatorType.ONE_OF;
|
|
27
|
+
attribute: string;
|
|
28
|
+
value: string[];
|
|
29
|
+
};
|
|
30
|
+
type NotOneOfCondition = {
|
|
31
|
+
operator: OperatorType.NOT_ONE_OF;
|
|
32
|
+
attribute: string;
|
|
33
|
+
value: string[];
|
|
34
|
+
};
|
|
35
|
+
type NumericCondition = {
|
|
36
|
+
operator: NumericOperator;
|
|
37
|
+
attribute: string;
|
|
38
|
+
value: number;
|
|
39
|
+
};
|
|
40
|
+
type NullCondition = {
|
|
41
|
+
operator: OperatorType.IS_NULL;
|
|
42
|
+
attribute: string;
|
|
43
|
+
value: boolean;
|
|
44
|
+
};
|
|
45
|
+
export type Condition = MatchesCondition | NotMatchesCondition | OneOfCondition | NotOneOfCondition | NumericCondition | NullCondition;
|
|
46
|
+
export interface Rule {
|
|
47
|
+
conditions: Condition[];
|
|
48
|
+
}
|
|
49
|
+
export declare function matchesRule(rule: Rule, subjectAttributes: EvaluationContext): boolean;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAExF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,sBAAsB,EAAE,CAAA;AAElF,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,GAAG,QAAQ;IACX,EAAE,OAAO;IACT,GAAG,QAAQ;IACX,EAAE,OAAO;IACT,MAAM,WAAW;IACjB,UAAU,eAAe;IACzB,OAAO,YAAY;CACpB;AAED,KAAK,eAAe,GAAG,YAAY,CAAC,GAAG,GAAG,YAAY,CAAC,EAAE,GAAG,YAAY,CAAC,GAAG,GAAG,YAAY,CAAC,EAAE,CAAA;AAE9F,KAAK,gBAAgB,GAAG;IACtB,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,YAAY,CAAC,WAAW,CAAA;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,mBAAmB,GACnB,cAAc,GACd,iBAAiB,GACjB,gBAAgB,GAChB,aAAa,CAAA;AAEjB,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,SAAS,EAAE,CAAA;CACxB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,EAAE,iBAAiB,GAAG,OAAO,CAIrF"}
|