@microsoft/feature-management 2.0.0-preview.3 → 2.0.1

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.
@@ -6,7 +6,7 @@ class TargetingFilter {
6
6
  name = "Microsoft.Targeting";
7
7
  async evaluate(context, appContext) {
8
8
  const { featureName, parameters } = context;
9
- TargetingFilter.#validateParameters(parameters);
9
+ TargetingFilter.#validateParameters(featureName, parameters);
10
10
  if (appContext === undefined) {
11
11
  throw new Error("The app context is required for targeting filter.");
12
12
  }
@@ -49,15 +49,15 @@ class TargetingFilter {
49
49
  const hint = featureName;
50
50
  return isTargetedPercentile(appContext?.userId, hint, 0, parameters.Audience.DefaultRolloutPercentage);
51
51
  }
52
- static #validateParameters(parameters) {
52
+ static #validateParameters(featureName, parameters) {
53
53
  if (parameters.Audience.DefaultRolloutPercentage < 0 || parameters.Audience.DefaultRolloutPercentage > 100) {
54
- throw new Error("Audience.DefaultRolloutPercentage must be a number between 0 and 100.");
54
+ throw new Error(`Invalid feature flag: ${featureName}. Audience.DefaultRolloutPercentage must be a number between 0 and 100.`);
55
55
  }
56
56
  // validate RolloutPercentage for each group
57
57
  if (parameters.Audience.Groups !== undefined) {
58
58
  for (const group of parameters.Audience.Groups) {
59
59
  if (group.RolloutPercentage < 0 || group.RolloutPercentage > 100) {
60
- throw new Error(`RolloutPercentage of group ${group.Name} must be a number between 0 and 100.`);
60
+ throw new Error(`Invalid feature flag: ${featureName}. RolloutPercentage of group ${group.Name} must be a number between 0 and 100.`);
61
61
  }
62
62
  }
63
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TargetingFilter.js","sources":["../../../src/filter/TargetingFilter.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { IFeatureFilter } from \"./FeatureFilter.js\";\nimport { isTargetedPercentile } from \"../common/targetingEvaluator.js\";\nimport { ITargetingContext } from \"../common/ITargetingContext.js\";\n\ntype TargetingFilterParameters = {\n Audience: {\n DefaultRolloutPercentage: number;\n Users?: string[];\n Groups?: {\n Name: string;\n RolloutPercentage: number;\n }[];\n Exclusion?: {\n Users?: string[];\n Groups?: string[];\n };\n }\n}\n\ntype TargetingFilterEvaluationContext = {\n featureName: string;\n parameters: TargetingFilterParameters;\n}\n\nexport class TargetingFilter implements IFeatureFilter {\n name: string = \"Microsoft.Targeting\";\n\n async evaluate(context: TargetingFilterEvaluationContext, appContext?: ITargetingContext): Promise<boolean> {\n const { featureName, parameters } = context;\n TargetingFilter.#validateParameters(parameters);\n\n if (appContext === undefined) {\n throw new Error(\"The app context is required for targeting filter.\");\n }\n\n if (parameters.Audience.Exclusion !== undefined) {\n // check if the user is in the exclusion list\n if (appContext?.userId !== undefined &&\n parameters.Audience.Exclusion.Users !== undefined &&\n parameters.Audience.Exclusion.Users.includes(appContext.userId)) {\n return false;\n }\n // check if the user is in a group within exclusion list\n if (appContext?.groups !== undefined &&\n parameters.Audience.Exclusion.Groups !== undefined) {\n for (const excludedGroup of parameters.Audience.Exclusion.Groups) {\n if (appContext.groups.includes(excludedGroup)) {\n return false;\n }\n }\n }\n }\n\n // check if the user is being targeted directly\n if (appContext?.userId !== undefined &&\n parameters.Audience.Users !== undefined &&\n parameters.Audience.Users.includes(appContext.userId)) {\n return true;\n }\n\n // check if the user is in a group that is being targeted\n if (appContext?.groups !== undefined &&\n parameters.Audience.Groups !== undefined) {\n for (const group of parameters.Audience.Groups) {\n if (appContext.groups.includes(group.Name)) {\n const hint = `${featureName}\\n${group.Name}`;\n if (await isTargetedPercentile(appContext.userId, hint, 0, group.RolloutPercentage)) {\n return true;\n }\n }\n }\n }\n\n // check if the user is being targeted by a default rollout percentage\n const hint = featureName;\n return isTargetedPercentile(appContext?.userId, hint, 0, parameters.Audience.DefaultRolloutPercentage);\n }\n\n static #validateParameters(parameters: TargetingFilterParameters): void {\n if (parameters.Audience.DefaultRolloutPercentage < 0 || parameters.Audience.DefaultRolloutPercentage > 100) {\n throw new Error(\"Audience.DefaultRolloutPercentage must be a number between 0 and 100.\");\n }\n // validate RolloutPercentage for each group\n if (parameters.Audience.Groups !== undefined) {\n for (const group of parameters.Audience.Groups) {\n if (group.RolloutPercentage < 0 || group.RolloutPercentage > 100) {\n throw new Error(`RolloutPercentage of group ${group.Name} must be a number between 0 and 100.`);\n }\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TargetingFilter.js","sources":["../../../src/filter/TargetingFilter.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { IFeatureFilter } from \"./FeatureFilter.js\";\nimport { isTargetedPercentile } from \"../common/targetingEvaluator.js\";\nimport { ITargetingContext } from \"../common/ITargetingContext.js\";\n\ntype TargetingFilterParameters = {\n Audience: {\n DefaultRolloutPercentage: number;\n Users?: string[];\n Groups?: {\n Name: string;\n RolloutPercentage: number;\n }[];\n Exclusion?: {\n Users?: string[];\n Groups?: string[];\n };\n }\n}\n\ntype TargetingFilterEvaluationContext = {\n featureName: string;\n parameters: TargetingFilterParameters;\n}\n\nexport class TargetingFilter implements IFeatureFilter {\n name: string = \"Microsoft.Targeting\";\n\n async evaluate(context: TargetingFilterEvaluationContext, appContext?: ITargetingContext): Promise<boolean> {\n const { featureName, parameters } = context;\n TargetingFilter.#validateParameters(featureName, parameters);\n\n if (appContext === undefined) {\n throw new Error(\"The app context is required for targeting filter.\");\n }\n\n if (parameters.Audience.Exclusion !== undefined) {\n // check if the user is in the exclusion list\n if (appContext?.userId !== undefined &&\n parameters.Audience.Exclusion.Users !== undefined &&\n parameters.Audience.Exclusion.Users.includes(appContext.userId)) {\n return false;\n }\n // check if the user is in a group within exclusion list\n if (appContext?.groups !== undefined &&\n parameters.Audience.Exclusion.Groups !== undefined) {\n for (const excludedGroup of parameters.Audience.Exclusion.Groups) {\n if (appContext.groups.includes(excludedGroup)) {\n return false;\n }\n }\n }\n }\n\n // check if the user is being targeted directly\n if (appContext?.userId !== undefined &&\n parameters.Audience.Users !== undefined &&\n parameters.Audience.Users.includes(appContext.userId)) {\n return true;\n }\n\n // check if the user is in a group that is being targeted\n if (appContext?.groups !== undefined &&\n parameters.Audience.Groups !== undefined) {\n for (const group of parameters.Audience.Groups) {\n if (appContext.groups.includes(group.Name)) {\n const hint = `${featureName}\\n${group.Name}`;\n if (await isTargetedPercentile(appContext.userId, hint, 0, group.RolloutPercentage)) {\n return true;\n }\n }\n }\n }\n\n // check if the user is being targeted by a default rollout percentage\n const hint = featureName;\n return isTargetedPercentile(appContext?.userId, hint, 0, parameters.Audience.DefaultRolloutPercentage);\n }\n\n static #validateParameters(featureName: string, parameters: TargetingFilterParameters): void {\n if (parameters.Audience.DefaultRolloutPercentage < 0 || parameters.Audience.DefaultRolloutPercentage > 100) {\n throw new Error(`Invalid feature flag: ${featureName}. Audience.DefaultRolloutPercentage must be a number between 0 and 100.`);\n }\n // validate RolloutPercentage for each group\n if (parameters.Audience.Groups !== undefined) {\n for (const group of parameters.Audience.Groups) {\n if (group.RolloutPercentage < 0 || group.RolloutPercentage > 100) {\n throw new Error(`Invalid feature flag: ${featureName}. RolloutPercentage of group ${group.Name} must be a number between 0 and 100.`);\n }\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -15,157 +15,157 @@ function validateFeatureFlag(featureFlag) {
15
15
  throw new TypeError("Feature flag 'id' must be a string.");
16
16
  }
17
17
  if (featureFlag.enabled !== undefined && typeof featureFlag.enabled !== "boolean") {
18
- throw new TypeError("Feature flag 'enabled' must be a boolean.");
18
+ throw new TypeError(`Invalid feature flag: ${featureFlag.id}. Feature flag 'enabled' must be a boolean.`);
19
19
  }
20
20
  if (featureFlag.conditions !== undefined) {
21
- validateFeatureEnablementConditions(featureFlag.conditions);
21
+ validateFeatureEnablementConditions(featureFlag.id, featureFlag.conditions);
22
22
  }
23
23
  if (featureFlag.variants !== undefined) {
24
- validateVariants(featureFlag.variants);
24
+ validateVariants(featureFlag.id, featureFlag.variants);
25
25
  }
26
26
  if (featureFlag.allocation !== undefined) {
27
- validateVariantAllocation(featureFlag.allocation);
27
+ validateVariantAllocation(featureFlag.id, featureFlag.allocation);
28
28
  }
29
29
  if (featureFlag.telemetry !== undefined) {
30
- validateTelemetryOptions(featureFlag.telemetry);
30
+ validateTelemetryOptions(featureFlag.id, featureFlag.telemetry);
31
31
  }
32
32
  }
33
- function validateFeatureEnablementConditions(conditions) {
33
+ function validateFeatureEnablementConditions(id, conditions) {
34
34
  if (typeof conditions !== "object") {
35
- throw new TypeError("Feature flag 'conditions' must be an object.");
35
+ throw new TypeError(`Invalid feature flag: ${id}. Feature flag 'conditions' must be an object.`);
36
36
  }
37
37
  if (conditions.requirement_type !== undefined && conditions.requirement_type !== "Any" && conditions.requirement_type !== "All") {
38
- throw new TypeError("'requirement_type' must be 'Any' or 'All'.");
38
+ throw new TypeError(`Invalid feature flag: ${id}. 'requirement_type' must be 'Any' or 'All'.`);
39
39
  }
40
40
  if (conditions.client_filters !== undefined) {
41
- validateClientFilters(conditions.client_filters);
41
+ validateClientFilters(id, conditions.client_filters);
42
42
  }
43
43
  }
44
- function validateClientFilters(client_filters) {
44
+ function validateClientFilters(id, client_filters) {
45
45
  if (!Array.isArray(client_filters)) {
46
- throw new TypeError("Feature flag conditions 'client_filters' must be an array.");
46
+ throw new TypeError(`Invalid feature flag: ${id}. Feature flag conditions 'client_filters' must be an array.`);
47
47
  }
48
48
  for (const filter of client_filters) {
49
49
  if (typeof filter.name !== "string") {
50
- throw new TypeError("Client filter 'name' must be a string.");
50
+ throw new TypeError(`Invalid feature flag: ${id}. Client filter 'name' must be a string.`);
51
51
  }
52
52
  if (filter.parameters !== undefined && typeof filter.parameters !== "object") {
53
- throw new TypeError("Client filter 'parameters' must be an object.");
53
+ throw new TypeError(`Invalid feature flag: ${id}. Client filter 'parameters' must be an object.`);
54
54
  }
55
55
  }
56
56
  }
57
- function validateVariants(variants) {
57
+ function validateVariants(id, variants) {
58
58
  if (!Array.isArray(variants)) {
59
- throw new TypeError("Feature flag 'variants' must be an array.");
59
+ throw new TypeError(`Invalid feature flag: ${id}. Feature flag 'variants' must be an array.`);
60
60
  }
61
61
  for (const variant of variants) {
62
62
  if (typeof variant.name !== "string") {
63
- throw new TypeError("Variant 'name' must be a string.");
63
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'name' must be a string.`);
64
64
  }
65
65
  // skip configuration_value validation as it accepts any type
66
66
  if (variant.status_override !== undefined && typeof variant.status_override !== "string") {
67
- throw new TypeError("Variant 'status_override' must be a string.");
67
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'status_override' must be a string.`);
68
68
  }
69
69
  if (variant.status_override !== undefined && variant.status_override !== "None" && variant.status_override !== "Enabled" && variant.status_override !== "Disabled") {
70
- throw new TypeError("Variant 'status_override' must be 'None', 'Enabled', or 'Disabled'.");
70
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'status_override' must be 'None', 'Enabled', or 'Disabled'.`);
71
71
  }
72
72
  }
73
73
  }
74
- function validateVariantAllocation(allocation) {
74
+ function validateVariantAllocation(id, allocation) {
75
75
  if (typeof allocation !== "object") {
76
- throw new TypeError("Variant 'allocation' must be an object.");
76
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'allocation' must be an object.`);
77
77
  }
78
78
  if (allocation.default_when_disabled !== undefined && typeof allocation.default_when_disabled !== "string") {
79
- throw new TypeError("Variant allocation 'default_when_disabled' must be a string.");
79
+ throw new TypeError(`Invalid feature flag: ${id}. Variant allocation 'default_when_disabled' must be a string.`);
80
80
  }
81
81
  if (allocation.default_when_enabled !== undefined && typeof allocation.default_when_enabled !== "string") {
82
- throw new TypeError("Variant allocation 'default_when_enabled' must be a string.");
82
+ throw new TypeError(`Invalid feature flag: ${id}. Variant allocation 'default_when_enabled' must be a string.`);
83
83
  }
84
84
  if (allocation.user !== undefined) {
85
- validateUserVariantAllocation(allocation.user);
85
+ validateUserVariantAllocation(id, allocation.user);
86
86
  }
87
87
  if (allocation.group !== undefined) {
88
- validateGroupVariantAllocation(allocation.group);
88
+ validateGroupVariantAllocation(id, allocation.group);
89
89
  }
90
90
  if (allocation.percentile !== undefined) {
91
- validatePercentileVariantAllocation(allocation.percentile);
91
+ validatePercentileVariantAllocation(id, allocation.percentile);
92
92
  }
93
93
  if (allocation.seed !== undefined && typeof allocation.seed !== "string") {
94
- throw new TypeError("Variant allocation 'seed' must be a string.");
94
+ throw new TypeError(`Invalid feature flag: ${id}. Variant allocation 'seed' must be a string.`);
95
95
  }
96
96
  }
97
- function validateUserVariantAllocation(UserAllocations) {
97
+ function validateUserVariantAllocation(id, UserAllocations) {
98
98
  if (!Array.isArray(UserAllocations)) {
99
- throw new TypeError("Variant 'user' allocation must be an array.");
99
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'user' allocation must be an array.`);
100
100
  }
101
101
  for (const allocation of UserAllocations) {
102
102
  if (typeof allocation !== "object") {
103
- throw new TypeError("Elements in variant 'user' allocation must be an object.");
103
+ throw new TypeError(`Invalid feature flag: ${id}. Elements in variant 'user' allocation must be an object.`);
104
104
  }
105
105
  if (typeof allocation.variant !== "string") {
106
- throw new TypeError("User allocation 'variant' must be a string.");
106
+ throw new TypeError(`Invalid feature flag: ${id}. User allocation 'variant' must be a string.`);
107
107
  }
108
108
  if (!Array.isArray(allocation.users)) {
109
- throw new TypeError("User allocation 'users' must be an array.");
109
+ throw new TypeError(`Invalid feature flag: ${id}. User allocation 'users' must be an array.`);
110
110
  }
111
111
  for (const user of allocation.users) {
112
112
  if (typeof user !== "string") {
113
- throw new TypeError("Elements in user allocation 'users' must be strings.");
113
+ throw new TypeError(`Invalid feature flag: ${id}. Elements in user allocation 'users' must be strings.`);
114
114
  }
115
115
  }
116
116
  }
117
117
  }
118
- function validateGroupVariantAllocation(groupAllocations) {
118
+ function validateGroupVariantAllocation(id, groupAllocations) {
119
119
  if (!Array.isArray(groupAllocations)) {
120
- throw new TypeError("Variant 'group' allocation must be an array.");
120
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'group' allocation must be an array.`);
121
121
  }
122
122
  for (const allocation of groupAllocations) {
123
123
  if (typeof allocation !== "object") {
124
- throw new TypeError("Elements in variant 'group' allocation must be an object.");
124
+ throw new TypeError(`Invalid feature flag: ${id}. Elements in variant 'group' allocation must be an object.`);
125
125
  }
126
126
  if (typeof allocation.variant !== "string") {
127
- throw new TypeError("Group allocation 'variant' must be a string.");
127
+ throw new TypeError(`Invalid feature flag: ${id}. Group allocation 'variant' must be a string.`);
128
128
  }
129
129
  if (!Array.isArray(allocation.groups)) {
130
- throw new TypeError("Group allocation 'groups' must be an array.");
130
+ throw new TypeError(`Invalid feature flag: ${id}. Group allocation 'groups' must be an array.`);
131
131
  }
132
132
  for (const group of allocation.groups) {
133
133
  if (typeof group !== "string") {
134
- throw new TypeError("Elements in group allocation 'groups' must be strings.");
134
+ throw new TypeError(`Invalid feature flag: ${id}. Elements in group allocation 'groups' must be strings.`);
135
135
  }
136
136
  }
137
137
  }
138
138
  }
139
- function validatePercentileVariantAllocation(percentileAllocations) {
139
+ function validatePercentileVariantAllocation(id, percentileAllocations) {
140
140
  if (!Array.isArray(percentileAllocations)) {
141
- throw new TypeError("Variant 'percentile' allocation must be an array.");
141
+ throw new TypeError(`Invalid feature flag: ${id}. Variant 'percentile' allocation must be an array.`);
142
142
  }
143
143
  for (const allocation of percentileAllocations) {
144
144
  if (typeof allocation !== "object") {
145
- throw new TypeError("Elements in variant 'percentile' allocation must be an object.");
145
+ throw new TypeError(`Invalid feature flag: ${id}. Elements in variant 'percentile' allocation must be an object.`);
146
146
  }
147
147
  if (typeof allocation.variant !== "string") {
148
- throw new TypeError("Percentile allocation 'variant' must be a string.");
148
+ throw new TypeError(`Invalid feature flag: ${id}. Percentile allocation 'variant' must be a string.`);
149
149
  }
150
150
  if (typeof allocation.from !== "number" || allocation.from < 0 || allocation.from > 100) {
151
- throw new TypeError("Percentile allocation 'from' must be a number between 0 and 100.");
151
+ throw new TypeError(`Invalid feature flag: ${id}. Percentile allocation 'from' must be a number between 0 and 100.`);
152
152
  }
153
153
  if (typeof allocation.to !== "number" || allocation.to < 0 || allocation.to > 100) {
154
- throw new TypeError("Percentile allocation 'to' must be a number between 0 and 100.");
154
+ throw new TypeError(`Invalid feature flag: ${id}. Percentile allocation 'to' must be a number between 0 and 100.`);
155
155
  }
156
156
  }
157
157
  }
158
158
  // #endregion
159
159
  // #region Telemetry
160
- function validateTelemetryOptions(telemetry) {
160
+ function validateTelemetryOptions(id, telemetry) {
161
161
  if (typeof telemetry !== "object") {
162
- throw new TypeError("Feature flag 'telemetry' must be an object.");
162
+ throw new TypeError(`Invalid feature flag: ${id}. Feature flag 'telemetry' must be an object.`);
163
163
  }
164
164
  if (telemetry.enabled !== undefined && typeof telemetry.enabled !== "boolean") {
165
- throw new TypeError("Telemetry 'enabled' must be a boolean.");
165
+ throw new TypeError(`Invalid feature flag: ${id}. Telemetry 'enabled' must be a boolean.`);
166
166
  }
167
167
  if (telemetry.metadata !== undefined && typeof telemetry.metadata !== "object") {
168
- throw new TypeError("Telemetry 'metadata' must be an object.");
168
+ throw new TypeError(`Invalid feature flag: ${id}. Telemetry 'metadata' must be an object.`);
169
169
  }
170
170
  }
171
171
  // #endregion
@@ -1 +1 @@
1
- {"version":3,"file":"validator.js","sources":["../../../src/schema/validator.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Validates a feature flag object, checking if it conforms to the schema.\n * @param featureFlag The feature flag object to validate.\n */\nexport function validateFeatureFlag(featureFlag: any): void {\n if (featureFlag === undefined) {\n return; // no-op if feature flag is undefined, indicating that the feature flag is not found\n }\n if (featureFlag === null || typeof featureFlag !== \"object\") { // Note: typeof null = \"object\"\n throw new TypeError(\"Feature flag must be an object.\");\n }\n if (typeof featureFlag.id !== \"string\") {\n throw new TypeError(\"Feature flag 'id' must be a string.\");\n }\n if (featureFlag.enabled !== undefined && typeof featureFlag.enabled !== \"boolean\") {\n throw new TypeError(\"Feature flag 'enabled' must be a boolean.\");\n }\n if (featureFlag.conditions !== undefined) {\n validateFeatureEnablementConditions(featureFlag.conditions);\n }\n if (featureFlag.variants !== undefined) {\n validateVariants(featureFlag.variants);\n }\n if (featureFlag.allocation !== undefined) {\n validateVariantAllocation(featureFlag.allocation);\n }\n if (featureFlag.telemetry !== undefined) {\n validateTelemetryOptions(featureFlag.telemetry);\n }\n}\n\nfunction validateFeatureEnablementConditions(conditions: any) {\n if (typeof conditions !== \"object\") {\n throw new TypeError(\"Feature flag 'conditions' must be an object.\");\n }\n if (conditions.requirement_type !== undefined && conditions.requirement_type !== \"Any\" && conditions.requirement_type !== \"All\") {\n throw new TypeError(\"'requirement_type' must be 'Any' or 'All'.\");\n }\n if (conditions.client_filters !== undefined) {\n validateClientFilters(conditions.client_filters);\n }\n}\n\nfunction validateClientFilters(client_filters: any) {\n if (!Array.isArray(client_filters)) {\n throw new TypeError(\"Feature flag conditions 'client_filters' must be an array.\");\n }\n\n for (const filter of client_filters) {\n if (typeof filter.name !== \"string\") {\n throw new TypeError(\"Client filter 'name' must be a string.\");\n }\n if (filter.parameters !== undefined && typeof filter.parameters !== \"object\") {\n throw new TypeError(\"Client filter 'parameters' must be an object.\");\n }\n }\n}\n\nfunction validateVariants(variants: any) {\n if (!Array.isArray(variants)) {\n throw new TypeError(\"Feature flag 'variants' must be an array.\");\n }\n\n for (const variant of variants) {\n if (typeof variant.name !== \"string\") {\n throw new TypeError(\"Variant 'name' must be a string.\");\n }\n // skip configuration_value validation as it accepts any type\n if (variant.status_override !== undefined && typeof variant.status_override !== \"string\") {\n throw new TypeError(\"Variant 'status_override' must be a string.\");\n }\n if (variant.status_override !== undefined && variant.status_override !== \"None\" && variant.status_override !== \"Enabled\" && variant.status_override !== \"Disabled\") {\n throw new TypeError(\"Variant 'status_override' must be 'None', 'Enabled', or 'Disabled'.\");\n }\n }\n}\n\nfunction validateVariantAllocation(allocation: any) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(\"Variant 'allocation' must be an object.\");\n }\n\n if (allocation.default_when_disabled !== undefined && typeof allocation.default_when_disabled !== \"string\") {\n throw new TypeError(\"Variant allocation 'default_when_disabled' must be a string.\");\n }\n if (allocation.default_when_enabled !== undefined && typeof allocation.default_when_enabled !== \"string\") {\n throw new TypeError(\"Variant allocation 'default_when_enabled' must be a string.\");\n }\n if (allocation.user !== undefined) {\n validateUserVariantAllocation(allocation.user);\n }\n if (allocation.group !== undefined) {\n validateGroupVariantAllocation(allocation.group);\n }\n if (allocation.percentile !== undefined) {\n validatePercentileVariantAllocation(allocation.percentile);\n }\n if (allocation.seed !== undefined && typeof allocation.seed !== \"string\") {\n throw new TypeError(\"Variant allocation 'seed' must be a string.\");\n }\n}\n\nfunction validateUserVariantAllocation(UserAllocations: any) {\n if (!Array.isArray(UserAllocations)) {\n throw new TypeError(\"Variant 'user' allocation must be an array.\");\n }\n\n for (const allocation of UserAllocations) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(\"Elements in variant 'user' allocation must be an object.\");\n }\n if (typeof allocation.variant !== \"string\") {\n throw new TypeError(\"User allocation 'variant' must be a string.\");\n }\n if (!Array.isArray(allocation.users)) {\n throw new TypeError(\"User allocation 'users' must be an array.\");\n }\n for (const user of allocation.users) {\n if (typeof user !== \"string\") {\n throw new TypeError(\"Elements in user allocation 'users' must be strings.\");\n }\n }\n }\n}\n\nfunction validateGroupVariantAllocation(groupAllocations: any) {\n if (!Array.isArray(groupAllocations)) {\n throw new TypeError(\"Variant 'group' allocation must be an array.\");\n }\n\n for (const allocation of groupAllocations) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(\"Elements in variant 'group' allocation must be an object.\");\n }\n if (typeof allocation.variant !== \"string\") {\n throw new TypeError(\"Group allocation 'variant' must be a string.\");\n }\n if (!Array.isArray(allocation.groups)) {\n throw new TypeError(\"Group allocation 'groups' must be an array.\");\n }\n for (const group of allocation.groups) {\n if (typeof group !== \"string\") {\n throw new TypeError(\"Elements in group allocation 'groups' must be strings.\");\n }\n }\n }\n}\n\nfunction validatePercentileVariantAllocation(percentileAllocations: any) {\n if (!Array.isArray(percentileAllocations)) {\n throw new TypeError(\"Variant 'percentile' allocation must be an array.\");\n }\n\n for (const allocation of percentileAllocations) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(\"Elements in variant 'percentile' allocation must be an object.\");\n }\n if (typeof allocation.variant !== \"string\") {\n throw new TypeError(\"Percentile allocation 'variant' must be a string.\");\n }\n if (typeof allocation.from !== \"number\" || allocation.from < 0 || allocation.from > 100) {\n throw new TypeError(\"Percentile allocation 'from' must be a number between 0 and 100.\");\n }\n if (typeof allocation.to !== \"number\" || allocation.to < 0 || allocation.to > 100) {\n throw new TypeError(\"Percentile allocation 'to' must be a number between 0 and 100.\");\n }\n }\n}\n// #endregion\n\n// #region Telemetry\nfunction validateTelemetryOptions(telemetry: any) {\n if (typeof telemetry !== \"object\") {\n throw new TypeError(\"Feature flag 'telemetry' must be an object.\");\n }\n if (telemetry.enabled !== undefined && typeof telemetry.enabled !== \"boolean\") {\n throw new TypeError(\"Telemetry 'enabled' must be a boolean.\");\n }\n if (telemetry.metadata !== undefined && typeof telemetry.metadata !== \"object\") {\n throw new TypeError(\"Telemetry 'metadata' must be an object.\");\n }\n}\n// #endregion\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validator.js","sources":["../../../src/schema/validator.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Validates a feature flag object, checking if it conforms to the schema.\n * @param featureFlag The feature flag object to validate.\n */\nexport function validateFeatureFlag(featureFlag: any): void {\n if (featureFlag === undefined) {\n return; // no-op if feature flag is undefined, indicating that the feature flag is not found\n }\n if (featureFlag === null || typeof featureFlag !== \"object\") { // Note: typeof null = \"object\"\n throw new TypeError(\"Feature flag must be an object.\");\n }\n if (typeof featureFlag.id !== \"string\") {\n throw new TypeError(\"Feature flag 'id' must be a string.\");\n }\n\n if (featureFlag.enabled !== undefined && typeof featureFlag.enabled !== \"boolean\") {\n throw new TypeError(`Invalid feature flag: ${featureFlag.id}. Feature flag 'enabled' must be a boolean.`);\n }\n if (featureFlag.conditions !== undefined) {\n validateFeatureEnablementConditions(featureFlag.id, featureFlag.conditions);\n }\n if (featureFlag.variants !== undefined) {\n validateVariants(featureFlag.id, featureFlag.variants);\n }\n if (featureFlag.allocation !== undefined) {\n validateVariantAllocation(featureFlag.id, featureFlag.allocation);\n }\n if (featureFlag.telemetry !== undefined) {\n validateTelemetryOptions(featureFlag.id, featureFlag.telemetry);\n }\n}\n\nfunction validateFeatureEnablementConditions(id: string, conditions: any) {\n if (typeof conditions !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Feature flag 'conditions' must be an object.`);\n }\n if (conditions.requirement_type !== undefined && conditions.requirement_type !== \"Any\" && conditions.requirement_type !== \"All\") {\n throw new TypeError(`Invalid feature flag: ${id}. 'requirement_type' must be 'Any' or 'All'.`);\n }\n if (conditions.client_filters !== undefined) {\n validateClientFilters(id, conditions.client_filters);\n }\n}\n\nfunction validateClientFilters(id: string, client_filters: any) {\n if (!Array.isArray(client_filters)) {\n throw new TypeError(`Invalid feature flag: ${id}. Feature flag conditions 'client_filters' must be an array.`);\n }\n\n for (const filter of client_filters) {\n if (typeof filter.name !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Client filter 'name' must be a string.`);\n }\n if (filter.parameters !== undefined && typeof filter.parameters !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Client filter 'parameters' must be an object.`);\n }\n }\n}\n\nfunction validateVariants(id: string, variants: any) {\n if (!Array.isArray(variants)) {\n throw new TypeError(`Invalid feature flag: ${id}. Feature flag 'variants' must be an array.`);\n }\n\n for (const variant of variants) {\n if (typeof variant.name !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'name' must be a string.`);\n }\n // skip configuration_value validation as it accepts any type\n if (variant.status_override !== undefined && typeof variant.status_override !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'status_override' must be a string.`);\n }\n if (variant.status_override !== undefined && variant.status_override !== \"None\" && variant.status_override !== \"Enabled\" && variant.status_override !== \"Disabled\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'status_override' must be 'None', 'Enabled', or 'Disabled'.`);\n }\n }\n}\n\nfunction validateVariantAllocation(id: string, allocation: any) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'allocation' must be an object.`);\n }\n\n if (allocation.default_when_disabled !== undefined && typeof allocation.default_when_disabled !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant allocation 'default_when_disabled' must be a string.`);\n }\n if (allocation.default_when_enabled !== undefined && typeof allocation.default_when_enabled !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant allocation 'default_when_enabled' must be a string.`);\n }\n if (allocation.user !== undefined) {\n validateUserVariantAllocation(id, allocation.user);\n }\n if (allocation.group !== undefined) {\n validateGroupVariantAllocation(id, allocation.group);\n }\n if (allocation.percentile !== undefined) {\n validatePercentileVariantAllocation(id, allocation.percentile);\n }\n if (allocation.seed !== undefined && typeof allocation.seed !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Variant allocation 'seed' must be a string.`);\n }\n}\n\nfunction validateUserVariantAllocation(id: string, UserAllocations: any) {\n if (!Array.isArray(UserAllocations)) {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'user' allocation must be an array.`);\n }\n\n for (const allocation of UserAllocations) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Elements in variant 'user' allocation must be an object.`);\n }\n if (typeof allocation.variant !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. User allocation 'variant' must be a string.`);\n }\n if (!Array.isArray(allocation.users)) {\n throw new TypeError(`Invalid feature flag: ${id}. User allocation 'users' must be an array.`);\n }\n for (const user of allocation.users) {\n if (typeof user !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Elements in user allocation 'users' must be strings.`);\n }\n }\n }\n}\n\nfunction validateGroupVariantAllocation(id: string, groupAllocations: any) {\n if (!Array.isArray(groupAllocations)) {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'group' allocation must be an array.`);\n }\n\n for (const allocation of groupAllocations) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Elements in variant 'group' allocation must be an object.`);\n }\n if (typeof allocation.variant !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Group allocation 'variant' must be a string.`);\n }\n if (!Array.isArray(allocation.groups)) {\n throw new TypeError(`Invalid feature flag: ${id}. Group allocation 'groups' must be an array.`);\n }\n for (const group of allocation.groups) {\n if (typeof group !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Elements in group allocation 'groups' must be strings.`);\n }\n }\n }\n}\n\nfunction validatePercentileVariantAllocation(id: string, percentileAllocations: any) {\n if (!Array.isArray(percentileAllocations)) {\n throw new TypeError(`Invalid feature flag: ${id}. Variant 'percentile' allocation must be an array.`);\n }\n\n for (const allocation of percentileAllocations) {\n if (typeof allocation !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Elements in variant 'percentile' allocation must be an object.`);\n }\n if (typeof allocation.variant !== \"string\") {\n throw new TypeError(`Invalid feature flag: ${id}. Percentile allocation 'variant' must be a string.`);\n }\n if (typeof allocation.from !== \"number\" || allocation.from < 0 || allocation.from > 100) {\n throw new TypeError(`Invalid feature flag: ${id}. Percentile allocation 'from' must be a number between 0 and 100.`);\n }\n if (typeof allocation.to !== \"number\" || allocation.to < 0 || allocation.to > 100) {\n throw new TypeError(`Invalid feature flag: ${id}. Percentile allocation 'to' must be a number between 0 and 100.`);\n }\n }\n}\n// #endregion\n\n// #region Telemetry\nfunction validateTelemetryOptions(id: string, telemetry: any) {\n if (typeof telemetry !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Feature flag 'telemetry' must be an object.`);\n }\n if (telemetry.enabled !== undefined && typeof telemetry.enabled !== \"boolean\") {\n throw new TypeError(`Invalid feature flag: ${id}. Telemetry 'enabled' must be a boolean.`);\n }\n if (telemetry.metadata !== undefined && typeof telemetry.metadata !== \"object\") {\n throw new TypeError(`Invalid feature flag: ${id}. Telemetry 'metadata' must be an object.`);\n }\n}\n// #endregion\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { VariantAssignmentReason } from '../featureManager.js';
2
1
  import { EVALUATION_EVENT_VERSION } from '../version.js';
3
2
 
4
3
  // Copyright (c) Microsoft Corporation.
@@ -9,8 +8,6 @@ const ENABLED = "Enabled";
9
8
  const TARGETING_ID = "TargetingId";
10
9
  const VARIANT = "Variant";
11
10
  const VARIANT_ASSIGNMENT_REASON = "VariantAssignmentReason";
12
- const DEFAULT_WHEN_ENABLED = "DefaultWhenEnabled";
13
- const VARIANT_ASSIGNMENT_PERCENTAGE = "VariantAssignmentPercentage";
14
11
  function createFeatureEvaluationEventProperties(result) {
15
12
  if (result.feature === undefined) {
16
13
  return undefined;
@@ -24,29 +21,6 @@ function createFeatureEvaluationEventProperties(result) {
24
21
  [VARIANT]: result.variant ? result.variant.name : "",
25
22
  [VARIANT_ASSIGNMENT_REASON]: result.variantAssignmentReason,
26
23
  };
27
- if (result.feature.allocation?.default_when_enabled) {
28
- eventProperties[DEFAULT_WHEN_ENABLED] = result.feature.allocation.default_when_enabled;
29
- }
30
- if (result.variantAssignmentReason === VariantAssignmentReason.DefaultWhenEnabled) {
31
- let percentileAllocationPercentage = 0;
32
- if (result.variant !== undefined && result.feature.allocation !== undefined && result.feature.allocation.percentile !== undefined) {
33
- for (const percentile of result.feature.allocation.percentile) {
34
- percentileAllocationPercentage += percentile.to - percentile.from;
35
- }
36
- }
37
- eventProperties[VARIANT_ASSIGNMENT_PERCENTAGE] = (100 - percentileAllocationPercentage).toString();
38
- }
39
- else if (result.variantAssignmentReason === VariantAssignmentReason.Percentile) {
40
- let percentileAllocationPercentage = 0;
41
- if (result.variant !== undefined && result.feature.allocation !== undefined && result.feature.allocation.percentile !== undefined) {
42
- for (const percentile of result.feature.allocation.percentile) {
43
- if (percentile.variant === result.variant.name) {
44
- percentileAllocationPercentage += percentile.to - percentile.from;
45
- }
46
- }
47
- }
48
- eventProperties[VARIANT_ASSIGNMENT_PERCENTAGE] = percentileAllocationPercentage.toString();
49
- }
50
24
  const metadata = result.feature.telemetry?.metadata;
51
25
  if (metadata) {
52
26
  for (const key in metadata) {
@@ -1 +1 @@
1
- {"version":3,"file":"featureEvaluationEvent.js","sources":["../../../src/telemetry/featureEvaluationEvent.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { EvaluationResult, VariantAssignmentReason } from \"../featureManager\";\nimport { EVALUATION_EVENT_VERSION } from \"../version.js\";\n\nconst VERSION = \"Version\";\nconst FEATURE_NAME = \"FeatureName\";\nconst ENABLED = \"Enabled\";\nconst TARGETING_ID = \"TargetingId\";\nconst VARIANT = \"Variant\";\nconst VARIANT_ASSIGNMENT_REASON = \"VariantAssignmentReason\";\nconst DEFAULT_WHEN_ENABLED = \"DefaultWhenEnabled\";\nconst VARIANT_ASSIGNMENT_PERCENTAGE = \"VariantAssignmentPercentage\";\n\nexport function createFeatureEvaluationEventProperties(result: EvaluationResult): any {\n if (result.feature === undefined) {\n return undefined;\n }\n\n const eventProperties = {\n [VERSION]: EVALUATION_EVENT_VERSION,\n [FEATURE_NAME]: result.feature ? result.feature.id : \"\",\n [ENABLED]: result.enabled ? \"True\" : \"False\",\n // Ensure targetingId is string so that it will be placed in customDimensions\n [TARGETING_ID]: result.targetingId ? result.targetingId.toString() : \"\",\n [VARIANT]: result.variant ? result.variant.name : \"\",\n [VARIANT_ASSIGNMENT_REASON]: result.variantAssignmentReason,\n };\n\n if (result.feature.allocation?.default_when_enabled) {\n eventProperties[DEFAULT_WHEN_ENABLED] = result.feature.allocation.default_when_enabled;\n }\n\n if (result.variantAssignmentReason === VariantAssignmentReason.DefaultWhenEnabled) {\n let percentileAllocationPercentage = 0;\n if (result.variant !== undefined && result.feature.allocation !== undefined && result.feature.allocation.percentile !== undefined) {\n for (const percentile of result.feature.allocation.percentile) {\n percentileAllocationPercentage += percentile.to - percentile.from;\n }\n }\n eventProperties[VARIANT_ASSIGNMENT_PERCENTAGE] = (100 - percentileAllocationPercentage).toString();\n }\n else if (result.variantAssignmentReason === VariantAssignmentReason.Percentile) {\n let percentileAllocationPercentage = 0;\n if (result.variant !== undefined && result.feature.allocation !== undefined && result.feature.allocation.percentile !== undefined) {\n for (const percentile of result.feature.allocation.percentile) {\n if (percentile.variant === result.variant.name) {\n percentileAllocationPercentage += percentile.to - percentile.from;\n }\n }\n }\n eventProperties[VARIANT_ASSIGNMENT_PERCENTAGE] = percentileAllocationPercentage.toString();\n }\n\n const metadata = result.feature.telemetry?.metadata;\n if (metadata) {\n for (const key in metadata) {\n if (!(key in eventProperties)) {\n eventProperties[key] = metadata[key];\n }\n }\n }\n\n return eventProperties;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"featureEvaluationEvent.js","sources":["../../../src/telemetry/featureEvaluationEvent.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { EvaluationResult } from \"../featureManager\";\nimport { EVALUATION_EVENT_VERSION } from \"../version.js\";\n\nconst VERSION = \"Version\";\nconst FEATURE_NAME = \"FeatureName\";\nconst ENABLED = \"Enabled\";\nconst TARGETING_ID = \"TargetingId\";\nconst VARIANT = \"Variant\";\nconst VARIANT_ASSIGNMENT_REASON = \"VariantAssignmentReason\";\n\nexport function createFeatureEvaluationEventProperties(result: EvaluationResult): any {\n if (result.feature === undefined) {\n return undefined;\n }\n\n const eventProperties = {\n [VERSION]: EVALUATION_EVENT_VERSION,\n [FEATURE_NAME]: result.feature ? result.feature.id : \"\",\n [ENABLED]: result.enabled ? \"True\" : \"False\",\n // Ensure targetingId is string so that it will be placed in customDimensions\n [TARGETING_ID]: result.targetingId ? result.targetingId.toString() : \"\",\n [VARIANT]: result.variant ? result.variant.name : \"\",\n [VARIANT_ASSIGNMENT_REASON]: result.variantAssignmentReason,\n };\n\n const metadata = result.feature.telemetry?.metadata;\n if (metadata) {\n for (const key in metadata) {\n if (!(key in eventProperties)) {\n eventProperties[key] = metadata[key];\n }\n }\n }\n\n return eventProperties;\n}\n"],"names":[],"mappings":";;AAAA;AACA;AAKA,MAAM,OAAO,GAAG,SAAS,CAAC;AAC1B,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,OAAO,GAAG,SAAS,CAAC;AAC1B,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,OAAO,GAAG,SAAS,CAAC;AAC1B,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAEtD,SAAU,sCAAsC,CAAC,MAAwB,EAAA;AAC3E,IAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE;AAC9B,QAAA,OAAO,SAAS,CAAC;KACpB;AAED,IAAA,MAAM,eAAe,GAAG;QACpB,CAAC,OAAO,GAAG,wBAAwB;AACnC,QAAA,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE;AACvD,QAAA,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,OAAO;;AAE5C,QAAA,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE;AACvE,QAAA,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE;AACpD,QAAA,CAAC,yBAAyB,GAAG,MAAM,CAAC,uBAAuB;KAC9D,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;IACpD,IAAI,QAAQ,EAAE;AACV,QAAA,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE;AACxB,YAAA,IAAI,EAAE,GAAG,IAAI,eAAe,CAAC,EAAE;gBAC3B,eAAe,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;aACxC;SACJ;KACJ;AAED,IAAA,OAAO,eAAe,CAAC;AAC3B;;;;"}
@@ -1,6 +1,6 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- const VERSION = "2.0.0-preview.3";
3
+ const VERSION = "2.0.1";
4
4
  const EVALUATION_EVENT_VERSION = "1.0.0";
5
5
 
6
6
  export { EVALUATION_EVENT_VERSION, VERSION };
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../../src/version.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nexport const VERSION = \"2.0.0-preview.3\";\nexport const EVALUATION_EVENT_VERSION = \"1.0.0\";\n"],"names":[],"mappings":"AAAA;AACA;AAEO,MAAM,OAAO,GAAG,kBAAkB;AAClC,MAAM,wBAAwB,GAAG;;;;"}
1
+ {"version":3,"file":"version.js","sources":["../../src/version.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nexport const VERSION = \"2.0.1\";\nexport const EVALUATION_EVENT_VERSION = \"1.0.0\";\n"],"names":[],"mappings":"AAAA;AACA;AAEO,MAAM,OAAO,GAAG,QAAQ;AACxB,MAAM,wBAAwB,GAAG;;;;"}