feature-toggle-api 3.4.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -103
- package/dist/feature-toggle.d.ts +134 -0
- package/{src/index.js → dist/feature-toggle.js} +193 -114
- package/dist/feature-toggle.min.cjs +2 -0
- package/dist/feature-toggle.min.cjs.map +1 -0
- package/dist/feature-toggle.min.js +2 -0
- package/dist/feature-toggle.min.js.map +1 -0
- package/dist/feature-toggle.umd.min.js +2 -0
- package/dist/feature-toggle.umd.min.js.map +1 -0
- package/dist/html-plugin.umd.min.js +2 -0
- package/dist/html-plugin.umd.min.js.map +1 -0
- package/dist/url-plugin.umd.min.js +2 -0
- package/dist/url-plugin.umd.min.js.map +1 -0
- package/examples/01_basic_esmodule.js +10 -0
- package/examples/02_basic_cjsmodule.cjs +6 -0
- package/examples/{basic.html → 03_basic_scripttag.html} +3 -2
- package/examples/{example-htmlplugin.html → 04_example-htmlplugin.html} +2 -2
- package/examples/{example-urlplugin.html → 05_example-urlplugin.html} +2 -2
- package/examples/{withListener.html → 06_withListener.html} +1 -1
- package/package.json +32 -43
- package/rollup.config.js +107 -0
- package/src/featureToggle.ts +466 -0
- package/src/index.ts +10 -0
- package/src/plugins/htmlplugin/{plugin-html.js → plugin-html.ts} +22 -10
- package/src/plugins/urlplugin/{plugin-url.js → plugin-url.ts} +36 -10
- package/tests/featuretoggle.test.ts +450 -0
- package/tests/polyfills.ts +20 -0
- package/tsconfig.cjs.json +12 -0
- package/tsconfig.json +12 -0
- package/feature-toggle-api.js +0 -243
- package/feature-toggle-api.min.js +0 -1
- package/feature-toggle-api.module.js +0 -243
- package/spec/support/index.spec.js +0 -378
- package/spec/support/jasmine.json +0 -11
- package/spec/support/polyfills.js +0 -6
- package/src/index.cjs.js +0 -8
|
@@ -1,72 +1,176 @@
|
|
|
1
|
+
function useWindowMock() {
|
|
2
|
+
return {
|
|
3
|
+
isMocked: true,
|
|
4
|
+
decodeURIComponent: function (param1) {
|
|
5
|
+
return param1;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function parseValue(value) {
|
|
10
|
+
if (value === 'true')
|
|
11
|
+
return true;
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
function getParams(url, window) {
|
|
15
|
+
var params = {};
|
|
16
|
+
if (!url)
|
|
17
|
+
return [];
|
|
18
|
+
var urlparts = url.split("?");
|
|
19
|
+
//no params available for url
|
|
20
|
+
if (urlparts.length < 2)
|
|
21
|
+
return [];
|
|
22
|
+
const parts = urlparts[1].split('&');
|
|
23
|
+
parts.forEach(function (part) {
|
|
24
|
+
var pair = part.split('=');
|
|
25
|
+
pair[0] = window.decodeURIComponent(pair[0]);
|
|
26
|
+
pair[1] = parseValue(window.decodeURIComponent(pair[1]));
|
|
27
|
+
params[pair[0]] = (pair[1] !== 'undefined') ?
|
|
28
|
+
pair[1] : true;
|
|
29
|
+
});
|
|
30
|
+
return params;
|
|
31
|
+
}
|
|
32
|
+
function urlPlugin(config = {}) {
|
|
33
|
+
let _window;
|
|
34
|
+
if (config.useMockedWindow)
|
|
35
|
+
_window = useWindowMock();
|
|
36
|
+
else
|
|
37
|
+
_window = window;
|
|
38
|
+
config = Object.assign({}, {
|
|
39
|
+
url: _window.isMocked ? "" : _window.location.href,
|
|
40
|
+
prefix: ""
|
|
41
|
+
}, config);
|
|
42
|
+
return function (api) {
|
|
43
|
+
api.url = config.url;
|
|
44
|
+
const urlparams = getParams(config.url, _window);
|
|
45
|
+
const prefix = config.prefix;
|
|
46
|
+
Object.keys(urlparams).forEach(key => {
|
|
47
|
+
if (!key.startsWith(prefix))
|
|
48
|
+
return;
|
|
49
|
+
const keyWithoutPrefix = key.replace(prefix, "");
|
|
50
|
+
api.visibility(keyWithoutPrefix, urlparams[key]);
|
|
51
|
+
});
|
|
52
|
+
return { name: 'urlplugin' };
|
|
53
|
+
};
|
|
54
|
+
}
|
|
1
55
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
56
|
+
/*
|
|
57
|
+
creates a tag that is shown / hidden, depending on the visibility rules.
|
|
58
|
+
if not configured dynamically, it looks like this:
|
|
59
|
+
<feature name="featurename" variant="variantname" data="data">content </feature>
|
|
60
|
+
|
|
61
|
+
Parameter: (config)
|
|
62
|
+
- config.featureTagName: name of the tag. Default: "feature"
|
|
63
|
+
- nameAttributeName: Name of the Name-Attribute: default: "name"
|
|
64
|
+
- variantAttributeName: Name of the Variant-Attribute: default: "variant"
|
|
65
|
+
*/
|
|
66
|
+
const defaultparams = {
|
|
67
|
+
renderedTag: 'div',
|
|
68
|
+
featureTagName: 'feature',
|
|
69
|
+
tagAttributeName: 'tag',
|
|
70
|
+
nameAttributeName: 'name',
|
|
71
|
+
variantAttributeName: 'variant',
|
|
72
|
+
dataAttributeName: 'data',
|
|
73
|
+
displayAttributeName: 'display',
|
|
74
|
+
defaultDisplay: 'block',
|
|
75
|
+
};
|
|
76
|
+
function parseDataAttribute(attrAsString) {
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(attrAsString);
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
if (!isNaN(parseFloat(attrAsString)))
|
|
82
|
+
return parseFloat(attrAsString);
|
|
83
|
+
return attrAsString;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function htmlPlugin(config = {}) {
|
|
87
|
+
config = Object.assign({}, defaultparams, config);
|
|
88
|
+
function renderFeatureTag(elem, isVisible) {
|
|
89
|
+
const tagname = elem.getAttribute(config.tagAttributeName) || config.renderedTag;
|
|
90
|
+
const attributes = Array.from(elem.attributes);
|
|
91
|
+
let attributesAsString = "";
|
|
92
|
+
attributes.forEach(attr => {
|
|
93
|
+
attributesAsString += ` ${attr.nodeName}="${attr.nodeValue.replace(/"/g, """)}"`;
|
|
94
|
+
});
|
|
95
|
+
const display = isVisible ? (elem.getAttribute(config.displayAttributeName) || config.defaultDisplay) : 'none';
|
|
96
|
+
elem.outerHTML = `<${tagname} style="display:${display}" _feature="true" ${attributesAsString}>${elem.innerHTML}</${tagname}>`;
|
|
97
|
+
}
|
|
98
|
+
return function (api) {
|
|
99
|
+
var renderedTags = window.document.querySelectorAll(config.featureTagName);
|
|
100
|
+
renderedTags.forEach(tag => { renderFeatureTag(tag, false); });
|
|
101
|
+
api.on('visibilityrule', function (event) {
|
|
102
|
+
var selector = `[_feature][${config.nameAttributeName}="${event.name}"]`;
|
|
103
|
+
if (event.variant)
|
|
104
|
+
selector += `[${config.variantAttributeName}="${event.variant}"]`;
|
|
105
|
+
var elements = document.querySelectorAll(selector);
|
|
106
|
+
elements.forEach(elem => {
|
|
107
|
+
const dataAsString = elem.getAttribute(config.dataAttributeName);
|
|
108
|
+
const data = parseDataAttribute(dataAsString);
|
|
109
|
+
const isVisible = api.isVisible(event.name, event.variant, data);
|
|
110
|
+
renderFeatureTag(elem, isVisible);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
return { name: 'htmlplugin' };
|
|
114
|
+
};
|
|
115
|
+
}
|
|
5
116
|
|
|
117
|
+
function parseToFn(fnOrBool) {
|
|
118
|
+
if (typeof fnOrBool == 'boolean')
|
|
119
|
+
return function () { return fnOrBool; };
|
|
6
120
|
return fnOrBool;
|
|
7
121
|
}
|
|
8
|
-
|
|
9
|
-
const getKey = function (name, variant) {
|
|
122
|
+
function getKey(name, variant) {
|
|
10
123
|
var _name = name.toLowerCase();
|
|
11
|
-
if (typeof variant == 'string') {
|
|
124
|
+
if (variant && typeof variant == 'string') {
|
|
12
125
|
_name += "#" + variant.toLowerCase();
|
|
13
126
|
}
|
|
14
|
-
|
|
15
127
|
return _name;
|
|
16
128
|
}
|
|
17
|
-
|
|
18
129
|
function initVisibilities(visibilities = {}) {
|
|
19
130
|
const returnVisibilities = {};
|
|
20
131
|
Object.keys(visibilities).forEach(key => {
|
|
21
|
-
if(key.startsWith('_'))
|
|
132
|
+
if (key.startsWith('_') || key.startsWith('$'))
|
|
22
133
|
return;
|
|
23
134
|
returnVisibilities[getKey(key)] = parseToFn(visibilities[key]);
|
|
24
135
|
});
|
|
25
136
|
return returnVisibilities;
|
|
26
137
|
}
|
|
27
|
-
|
|
28
|
-
export default function featuretoggleapi(config={}) {
|
|
29
|
-
|
|
138
|
+
function useFeatureToggle(config = {}) {
|
|
30
139
|
const globals = {
|
|
31
140
|
datas: {},
|
|
32
141
|
listeners: {},
|
|
33
142
|
visibilities: initVisibilities(config),
|
|
34
143
|
showLogs: false,
|
|
35
144
|
usedPlugins: [],
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
145
|
+
};
|
|
146
|
+
function init(api) {
|
|
147
|
+
if (config.$default) {
|
|
148
|
+
api.setDefaultFlag(config.$default);
|
|
149
|
+
}
|
|
150
|
+
if (config.$required) {
|
|
151
|
+
api.setRequiredFlag(config.$required);
|
|
152
|
+
}
|
|
153
|
+
const allPlugins = [...(config.$plugins || []), ...(config._plugins || [])];
|
|
154
|
+
if (config._plugins) {
|
|
155
|
+
console.log('useFeatureToggle({_plugins:[]}): Key _plugins is deprecated. Use $plugins instead. This attribute will be removed in one of the next major versions.');
|
|
156
|
+
}
|
|
157
|
+
if (allPlugins.length) {
|
|
158
|
+
allPlugins.forEach(plugin => {
|
|
159
|
+
if (typeof plugin !== 'function')
|
|
46
160
|
throw new Error('featuretoggleapi()-constructor: config.plugins needs functions as entries, not ' + typeof plugin + '.');
|
|
47
|
-
|
|
48
|
-
addPlugin(plugin,api);
|
|
161
|
+
api.addPlugin(plugin);
|
|
49
162
|
});
|
|
50
163
|
}
|
|
51
|
-
|
|
52
164
|
triggerEvent('init');
|
|
53
165
|
}
|
|
54
|
-
|
|
55
|
-
function addPlugin(plugin,api)
|
|
56
|
-
{
|
|
57
|
-
plugin(api);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function triggerEvent(eventtype,param) {
|
|
166
|
+
function triggerEvent(eventtype, param) {
|
|
61
167
|
(globals.listeners[eventtype] || []).forEach(listener => {
|
|
62
168
|
listener(param);
|
|
63
169
|
});
|
|
64
170
|
}
|
|
65
|
-
|
|
66
171
|
const log = function (message) {
|
|
67
172
|
if (!globals.showLogs)
|
|
68
173
|
return;
|
|
69
|
-
|
|
70
174
|
//Nur Browser können Syntaxhighlighting die anderen geben die Nachricht einfach aus und schneiden
|
|
71
175
|
//die styletags raus
|
|
72
176
|
if (typeof window === 'undefined') {
|
|
@@ -74,55 +178,45 @@ export default function featuretoggleapi(config={}) {
|
|
|
74
178
|
console.log(loggedMessage);
|
|
75
179
|
return;
|
|
76
180
|
}
|
|
77
|
-
|
|
78
181
|
var hasBoldTag = message.indexOf('<b>') != -1;
|
|
79
182
|
var hasVisibleKeyword = message.indexOf('visible') != -1;
|
|
80
183
|
var hasHiddenKeyword = message.indexOf('hidden') != -1;
|
|
81
|
-
|
|
82
184
|
var _message = message.replace('visible', '%cvisible');
|
|
83
185
|
_message = _message.replace('hidden', '%chidden');
|
|
84
|
-
|
|
85
186
|
if (hasVisibleKeyword)
|
|
86
187
|
console.log(_message, "color:green;font-weight:bold;");
|
|
87
188
|
else if (hasHiddenKeyword)
|
|
88
189
|
console.log(_message, "color:red;font-weight:bold;");
|
|
89
190
|
else if (hasBoldTag) {
|
|
90
191
|
_message = _message.replace('<b>', '%c');
|
|
91
|
-
var parts = [_message, 'font-weight:bold;']
|
|
192
|
+
var parts = [_message, 'font-weight:bold;'];
|
|
92
193
|
console.log.apply(null, parts);
|
|
93
194
|
}
|
|
94
195
|
else
|
|
95
196
|
console.log(message);
|
|
96
|
-
}
|
|
97
|
-
|
|
197
|
+
};
|
|
98
198
|
const logAndReturn = function (returnValue, message) {
|
|
99
199
|
log(message);
|
|
100
200
|
log('');
|
|
101
201
|
return returnValue;
|
|
102
|
-
}
|
|
103
|
-
|
|
202
|
+
};
|
|
104
203
|
const getVisibility = function (visibilityFn, functionname, name, variant, data) {
|
|
105
204
|
if (visibilityFn == null)
|
|
106
205
|
return undefined;
|
|
107
|
-
|
|
108
206
|
var calculatedVisibility = visibilityFn({ name: name, variant: variant, data: data });
|
|
109
|
-
|
|
110
207
|
if (typeof calculatedVisibility == 'boolean') {
|
|
111
208
|
return calculatedVisibility;
|
|
112
209
|
}
|
|
113
|
-
|
|
114
210
|
return logAndReturn(false, `The ${functionname} returns ${calculatedVisibility}. => Please return true or false. This result (and all non-boolean results) will return false.`);
|
|
115
|
-
}
|
|
116
|
-
|
|
211
|
+
};
|
|
117
212
|
function parseKey(key) {
|
|
118
213
|
const parts = key.split('#');
|
|
119
214
|
return {
|
|
120
215
|
name: parts[0],
|
|
121
216
|
variant: parts.length > 1 ? parts[1] : undefined,
|
|
122
217
|
data: globals.datas[key],
|
|
123
|
-
}
|
|
218
|
+
};
|
|
124
219
|
}
|
|
125
|
-
|
|
126
220
|
/*
|
|
127
221
|
the following calls are possible:
|
|
128
222
|
visibility(name,result);
|
|
@@ -139,10 +233,8 @@ export default function featuretoggleapi(config={}) {
|
|
|
139
233
|
//name must always be set
|
|
140
234
|
if (param1 == undefined)
|
|
141
235
|
throw new Error('feature.visibility(): 1st parameter name must be defined');
|
|
142
|
-
|
|
143
236
|
if (arguments.length == 1)
|
|
144
237
|
throw new Error('feature.visibility(): 2nd parameter name must be a boolean or function, but is empty');
|
|
145
|
-
|
|
146
238
|
let name = param1, variant = null, data = null, result = null;
|
|
147
239
|
if (param3 == undefined && param4 == undefined) {
|
|
148
240
|
result = param2;
|
|
@@ -156,119 +248,89 @@ export default function featuretoggleapi(config={}) {
|
|
|
156
248
|
data = param3;
|
|
157
249
|
result = param4;
|
|
158
250
|
}
|
|
159
|
-
|
|
160
251
|
return {
|
|
161
252
|
name,
|
|
162
253
|
variant,
|
|
163
254
|
data,
|
|
164
255
|
result
|
|
165
|
-
}
|
|
256
|
+
};
|
|
166
257
|
}
|
|
167
|
-
|
|
168
258
|
function getEvent(name, variant, data, result) {
|
|
169
|
-
|
|
170
259
|
let event;
|
|
171
|
-
|
|
172
|
-
event = { name: name, variant: variant, data: data };
|
|
173
|
-
|
|
260
|
+
event = { name, variant, data };
|
|
174
261
|
event.key = getKey(event.name, event.variant);
|
|
175
|
-
|
|
176
262
|
if (result == null)
|
|
177
263
|
return event;
|
|
178
|
-
|
|
179
264
|
event.visibilityFunction = parseToFn(result);
|
|
180
|
-
event.result = event.visibilityFunction({
|
|
181
|
-
name: event.name,
|
|
182
|
-
variant: event.variant,
|
|
183
|
-
data: event.data || {},
|
|
265
|
+
event.result = event.visibilityFunction({
|
|
266
|
+
name: event.name,
|
|
267
|
+
variant: event.variant,
|
|
268
|
+
data: event.data || {},
|
|
184
269
|
_internalCall: true,
|
|
185
|
-
description:
|
|
186
|
-
})
|
|
270
|
+
description: 'When attaching a function, the result must be calculated internally. You can filter this out with the _internalCall:true -Flag.'
|
|
271
|
+
});
|
|
187
272
|
return event;
|
|
188
273
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
function isVisible(name, variant, data) {
|
|
274
|
+
function isActive(name, variant, data) {
|
|
193
275
|
const visibilities = globals.visibilities;
|
|
194
|
-
|
|
195
276
|
log(`\nCheck Visibility of <b>Feature "${name}", variant "${variant == undefined ? '' : variant}"${data ? " with data " + JSON.stringify(data) : ""}.`);
|
|
196
277
|
if (name == undefined)
|
|
197
278
|
throw new Error('The attribute "name" is required for tag <feature></feature>. Example: <feature name="aname"></feature>');
|
|
198
|
-
|
|
199
279
|
var requiredFn = visibilities['_required'];
|
|
200
280
|
var requiredFnExists = visibilities['_required'] != null;
|
|
201
281
|
var requiredFnResult = getVisibility(requiredFn, 'requiredVisibility', name, variant, data);
|
|
202
|
-
|
|
203
282
|
var visibilityFnKey = getKey(name, variant);
|
|
204
283
|
var visibilityFn = visibilities[visibilityFnKey];
|
|
205
284
|
var visibilityFnExists = visibilities[visibilityFnKey] != null;
|
|
206
285
|
var visibilityFnResult = getVisibility(visibilityFn, 'visibility function', name, variant, data);
|
|
207
|
-
|
|
208
286
|
var variantExists = variant != null;
|
|
209
287
|
var visibilityOnlyNameFnKey = getKey(name, null);
|
|
210
288
|
var visibilityOnlyNameFn = visibilities[visibilityOnlyNameFnKey];
|
|
211
|
-
var visibilityOnlyNameFnExists = visibilities[visibilityOnlyNameFnKey] != null;
|
|
212
289
|
var visibilityOnlyNameFnResult = getVisibility(visibilityOnlyNameFn, 'visibility function (only name)', name, variant, data);
|
|
213
|
-
|
|
214
290
|
var defaultFn = visibilities['_default'];
|
|
215
291
|
var defaultFnExists = visibilities['_default'] != null;
|
|
216
292
|
var defaultFnResult = getVisibility(defaultFn, 'defaultVisibility', name, variant, data);
|
|
217
|
-
|
|
218
293
|
if (!requiredFnExists)
|
|
219
294
|
log("No requiredVisibility rule specified for this feature.");
|
|
220
295
|
else if (requiredFnExists && requiredFnResult === true)
|
|
221
|
-
log("The requiredVisibility rule returns true. This feature will be shown when no other rule rejects it.")
|
|
296
|
+
log("The requiredVisibility rule returns true. This feature will be shown when no other rule rejects it.");
|
|
222
297
|
else if (requiredFnExists && requiredFnResult === false)
|
|
223
298
|
return logAndReturn(false, "The requiredVisibility rule returns false. This feature will be hidden.");
|
|
224
|
-
|
|
225
299
|
if (visibilityFnExists)
|
|
226
300
|
return logAndReturn(visibilityFnResult, `The visibility rule returns ${visibilityFnResult}. This feature will be ${visibilityFnResult ? 'visible' : 'hidden'}.`);
|
|
227
301
|
log('No visibility rule found matching name and variant.');
|
|
228
|
-
|
|
229
302
|
if (variantExists && typeof visibilityOnlyNameFnResult == 'boolean')
|
|
230
303
|
return logAndReturn(visibilityOnlyNameFnResult, `Found a visibility rule for name ${name} without variants. The rule returns ${visibilityOnlyNameFnResult}. => This feature will be ${visibilityOnlyNameFnResult ? 'visible' : 'hidden'}.`);
|
|
231
304
|
else if (variantExists)
|
|
232
|
-
log(`No rules found for name ${name} without variants.`)
|
|
233
|
-
|
|
234
|
-
|
|
305
|
+
log(`No rules found for name ${name} without variants.`);
|
|
235
306
|
if (defaultFnExists)
|
|
236
307
|
return logAndReturn(defaultFnResult, `Found a defaultVisibility rule. The rule returns ${defaultFnResult}. => This feature will be ${defaultFnResult ? 'visible' : 'hidden'}.`);
|
|
237
|
-
log(`No default rule found.`)
|
|
238
|
-
|
|
308
|
+
log(`No default rule found.`);
|
|
239
309
|
if (requiredFnExists)
|
|
240
310
|
return logAndReturn(true, `Only the requiredVisibility rule was found. This returned true. => This feature will be visible.`);
|
|
241
|
-
|
|
242
311
|
return logAndReturn(false, 'No rules were found. This feature will be hidden.');
|
|
243
312
|
}
|
|
244
|
-
|
|
245
313
|
const api = {
|
|
246
314
|
name: 'feature-toggle-api',
|
|
247
315
|
setData: function (nameParam, variantOrDataParam, dataParam) {
|
|
248
316
|
if (nameParam == undefined)
|
|
249
317
|
throw new Error('setData(): The name must of the feature must be defined, but ist undefined');
|
|
250
|
-
|
|
251
|
-
const variant = dataParam != undefined ? variantOrDataParam : undefined;
|
|
318
|
+
const variant = (dataParam != undefined ? variantOrDataParam : undefined);
|
|
252
319
|
const data = dataParam || variantOrDataParam;
|
|
253
|
-
|
|
254
320
|
const event = getEvent(nameParam, variant, data);
|
|
255
|
-
|
|
256
321
|
globals.datas[event.key] = event.data;
|
|
257
|
-
|
|
258
|
-
triggerEvent('visibilityrule',event);
|
|
322
|
+
triggerEvent('visibilityrule', event);
|
|
259
323
|
},
|
|
260
|
-
on
|
|
324
|
+
on(eventtype, fn, config) {
|
|
261
325
|
globals.listeners[eventtype] = globals.listeners[eventtype] || [];
|
|
262
326
|
globals.listeners[eventtype].push(fn);
|
|
263
|
-
|
|
264
|
-
triggerEvent('registerEvent',{
|
|
327
|
+
triggerEvent('registerEvent', {
|
|
265
328
|
type: eventtype
|
|
266
|
-
})
|
|
329
|
+
});
|
|
267
330
|
if (config != undefined && config.ignorePreviousRules)
|
|
268
331
|
return;
|
|
269
|
-
|
|
270
332
|
Object.keys(globals.visibilities).forEach(key => {
|
|
271
|
-
const event = parseKey(key
|
|
333
|
+
const event = parseKey(key);
|
|
272
334
|
const rule = globals.visibilities[key];
|
|
273
335
|
event.result = rule(event);
|
|
274
336
|
fn(event);
|
|
@@ -278,41 +340,58 @@ export default function featuretoggleapi(config={}) {
|
|
|
278
340
|
showLogs: function (showLogs) {
|
|
279
341
|
globals.showLogs = showLogs == undefined ? true : showLogs;
|
|
280
342
|
},
|
|
281
|
-
isVisible,
|
|
282
|
-
|
|
343
|
+
isVisible(name, variant, data) {
|
|
344
|
+
console.log('featureToggle.isVisible is deprecated. use featureToggle.isActive instead. This function will be removed in one of the next major versions.');
|
|
345
|
+
return isActive(name, variant, data);
|
|
346
|
+
},
|
|
347
|
+
isActive,
|
|
348
|
+
/**
|
|
283
349
|
the following function calls are possible:
|
|
284
350
|
visibility(name,result);
|
|
285
351
|
visibility(name,variant,result);
|
|
286
352
|
visibility(name,variant,data,result);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const params = visibilityFnParams(
|
|
353
|
+
*/
|
|
354
|
+
setFlag(name, resultOrVariant, resultOrData, result) {
|
|
355
|
+
const params = visibilityFnParams(name, resultOrVariant, resultOrData, result);
|
|
290
356
|
const event = getEvent(params.name, params.variant, params.data, params.result);
|
|
291
|
-
|
|
292
357
|
globals.visibilities[event.key] = event.visibilityFunction;
|
|
293
358
|
globals.datas[event.key] = event.data;
|
|
294
|
-
triggerEvent('visibilityrule',event);
|
|
359
|
+
triggerEvent('visibilityrule', event);
|
|
360
|
+
},
|
|
361
|
+
visibility: function (name, resultOrVariant, resultOrData, result) {
|
|
362
|
+
console.log('featureToggle.visibility is deprecated. use featureToggle.setVisibility instead. This function will be removed in one of the next major versions.');
|
|
363
|
+
api.setFlag(name, resultOrVariant, resultOrData, result);
|
|
295
364
|
},
|
|
296
365
|
requiredVisibility: function (fn) {
|
|
366
|
+
console.log('featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions.');
|
|
367
|
+
api.setRequiredFlag(fn);
|
|
368
|
+
},
|
|
369
|
+
defaultVisibility: function (fn) {
|
|
370
|
+
console.log('featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions.');
|
|
371
|
+
api.setDefaultFlag(fn);
|
|
372
|
+
},
|
|
373
|
+
setRequiredFlag(fn) {
|
|
297
374
|
if (typeof fn != "function")
|
|
298
|
-
throw new Error('feature.
|
|
299
|
-
|
|
375
|
+
throw new Error('feature.setRequiredFlag(): 1st parameter must be a function, but is ' + typeof fn);
|
|
300
376
|
globals.visibilities['_required'] = parseToFn(fn);
|
|
301
377
|
},
|
|
302
|
-
|
|
378
|
+
setDefaultFlag(fn) {
|
|
303
379
|
if (typeof fn != "function")
|
|
304
380
|
throw new Error('feature.defaultVisibility(): 1st parameter must be a function, but is ' + typeof fn);
|
|
305
|
-
|
|
306
381
|
globals.visibilities['_default'] = parseToFn(fn);
|
|
307
382
|
},
|
|
308
|
-
addPlugin: function(plugin){
|
|
309
|
-
if(globals.usedPlugins.includes(plugin))
|
|
383
|
+
addPlugin: function (plugin) {
|
|
384
|
+
if (globals.usedPlugins.includes(plugin))
|
|
310
385
|
return;
|
|
311
|
-
|
|
312
|
-
|
|
386
|
+
const newPlugin = plugin(api);
|
|
387
|
+
for (let _key of Object.keys(newPlugin)) {
|
|
388
|
+
api[_key] = newPlugin[_key];
|
|
389
|
+
}
|
|
313
390
|
globals.usedPlugins.push(plugin);
|
|
314
391
|
},
|
|
315
392
|
};
|
|
316
393
|
init(api);
|
|
317
394
|
return api;
|
|
318
395
|
}
|
|
396
|
+
|
|
397
|
+
export { htmlPlugin, urlPlugin, useFeatureToggle };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const e={renderedTag:"div",featureTagName:"feature",tagAttributeName:"tag",nameAttributeName:"name",variantAttributeName:"variant",dataAttributeName:"data",displayAttributeName:"display",defaultDisplay:"block"};function t(e){return"boolean"==typeof e?function(){return e}:e}function i(e,t){var i=e.toLowerCase();return t&&"string"==typeof t&&(i+="#"+t.toLowerCase()),i}function n(e={}){const n={};return Object.keys(e).forEach((r=>{r.startsWith("_")||r.startsWith("$")||(n[i(r)]=t(e[r]))})),n}exports.htmlPlugin=function(t={}){function i(e,i){const n=e.getAttribute(t.tagAttributeName)||t.renderedTag,r=Array.from(e.attributes);let l="";r.forEach((e=>{l+=` ${e.nodeName}="${e.nodeValue.replace(/"/g,""")}"`}));const a=i?e.getAttribute(t.displayAttributeName)||t.defaultDisplay:"none";e.outerHTML=`<${n} style="display:${a}" _feature="true" ${l}>${e.innerHTML}</${n}>`}return t=Object.assign({},e,t),function(e){return window.document.querySelectorAll(t.featureTagName).forEach((e=>{i(e,!1)})),e.on("visibilityrule",(function(n){var r=`[_feature][${t.nameAttributeName}="${n.name}"]`;n.variant&&(r+=`[${t.variantAttributeName}="${n.variant}"]`),document.querySelectorAll(r).forEach((r=>{const l=function(e){try{return JSON.parse(e)}catch(t){return isNaN(parseFloat(e))?e:parseFloat(e)}}(r.getAttribute(t.dataAttributeName));i(r,e.isVisible(n.name,n.variant,l))}))})),{name:"htmlplugin"}}},exports.urlPlugin=function(e={}){let t;return t=e.useMockedWindow?{isMocked:!0,decodeURIComponent:function(e){return e}}:window,e=Object.assign({},{url:t.isMocked?"":t.location.href,prefix:""},e),function(i){i.url=e.url;const n=function(e,t){var i={};if(!e)return[];var n=e.split("?");return n.length<2?[]:(n[1].split("&").forEach((function(e){var n=e.split("=");n[0]=t.decodeURIComponent(n[0]),n[1]="true"===t.decodeURIComponent(n[1]),i[n[0]]="undefined"===n[1]||n[1]})),i)}(e.url,t),r=e.prefix;return Object.keys(n).forEach((e=>{if(!e.startsWith(r))return;const t=e.replace(r,"");i.visibility(t,n[e])})),{name:"urlplugin"}}},exports.useFeatureToggle=function(e={}){const r={datas:{},listeners:{},visibilities:n(e),showLogs:!1,usedPlugins:[]};function l(e,t){(r.listeners[e]||[]).forEach((e=>{e(t)}))}const a=function(e){if(r.showLogs)if("undefined"!=typeof window){var t=-1!=e.indexOf("<b>"),i=-1!=e.indexOf("visible"),n=-1!=e.indexOf("hidden"),l=e.replace("visible","%cvisible");if(l=l.replace("hidden","%chidden"),i)console.log(l,"color:green;font-weight:bold;");else if(n)console.log(l,"color:red;font-weight:bold;");else if(t){var a=[l=l.replace("<b>","%c"),"font-weight:bold;"];console.log.apply(null,a)}else console.log(e)}else{const t=e.replace(/<b>/g,"");console.log(t)}},u=function(e,t){return a(t),a(""),e},s=function(e,t,i,n,r){if(null!=e){var l=e({name:i,variant:n,data:r});return"boolean"==typeof l?l:u(!1,`The ${t} returns ${l}. => Please return true or false. This result (and all non-boolean results) will return false.`)}};function o(e,n,r,l){let a;return a={name:e,variant:n,data:r},a.key=i(a.name,a.variant),null==l||(a.visibilityFunction=t(l),a.result=a.visibilityFunction({name:a.name,variant:a.variant,data:a.data||{},_internalCall:!0,description:"When attaching a function, the result must be calculated internally. You can filter this out with the _internalCall:true -Flag."})),a}function f(e,t,n){const l=r.visibilities;if(a(`\nCheck Visibility of <b>Feature "${e}", variant "${null==t?"":t}"${n?" with data "+JSON.stringify(n):""}.`),null==e)throw new Error('The attribute "name" is required for tag <feature></feature>. Example: <feature name="aname"></feature>');var o=l._required,f=null!=l._required,d=s(o,"requiredVisibility",e,t,n),c=i(e,t),b=l[c],g=null!=l[c],h=s(b,"visibility function",e,t,n),v=null!=t,m=l[i(e,null)],y=s(m,"visibility function (only name)",e,t,n),p=l._default,w=null!=l._default,T=s(p,"defaultVisibility",e,t,n);if(f){if(f&&!0===d)a("The requiredVisibility rule returns true. This feature will be shown when no other rule rejects it.");else if(f&&!1===d)return u(!1,"The requiredVisibility rule returns false. This feature will be hidden.")}else a("No requiredVisibility rule specified for this feature.");return g?u(h,`The visibility rule returns ${h}. This feature will be ${h?"visible":"hidden"}.`):(a("No visibility rule found matching name and variant."),v&&"boolean"==typeof y?u(y,`Found a visibility rule for name ${e} without variants. The rule returns ${y}. => This feature will be ${y?"visible":"hidden"}.`):(v&&a(`No rules found for name ${e} without variants.`),w?u(T,`Found a defaultVisibility rule. The rule returns ${T}. => This feature will be ${T?"visible":"hidden"}.`):(a("No default rule found."),f?u(!0,"Only the requiredVisibility rule was found. This returned true. => This feature will be visible."):u(!1,"No rules were found. This feature will be hidden."))))}const d={name:"feature-toggle-api",setData:function(e,t,i){if(null==e)throw new Error("setData(): The name must of the feature must be defined, but ist undefined");const n=o(e,null!=i?t:void 0,i||t);r.datas[n.key]=n.data,l("visibilityrule",n)},on(e,t,i){r.listeners[e]=r.listeners[e]||[],r.listeners[e].push(t),l("registerEvent",{type:e}),null!=i&&i.ignorePreviousRules||Object.keys(r.visibilities).forEach((e=>{const i=function(e){const t=e.split("#");return{name:t[0],variant:t.length>1?t[1]:void 0,data:r.datas[e]}}(e),n=r.visibilities[e];i.result=n(i),t(i)}))},trigger:l,showLogs:function(e){r.showLogs=null==e||e},isVisible:(e,t,i)=>(console.log("featureToggle.isVisible is deprecated. use featureToggle.isActive instead. This function will be removed in one of the next major versions."),f(e,t,i)),isActive:f,setFlag(e,t,i,n){const a=function(e,t,i,n){if(null==e)throw new Error("feature.visibility(): 1st parameter name must be defined");if(1==arguments.length)throw new Error("feature.visibility(): 2nd parameter name must be a boolean or function, but is empty");let r=null,l=null,a=null;return null==i&&null==n?a=t:null==n?(r=t,a=i):(r=t,l=i,a=n),{name:e,variant:r,data:l,result:a}}(e,t,i,n),u=o(a.name,a.variant,a.data,a.result);r.visibilities[u.key]=u.visibilityFunction,r.datas[u.key]=u.data,l("visibilityrule",u)},visibility:function(e,t,i,n){console.log("featureToggle.visibility is deprecated. use featureToggle.setVisibility instead. This function will be removed in one of the next major versions."),d.setFlag(e,t,i,n)},requiredVisibility:function(e){console.log("featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions."),d.setRequiredFlag(e)},defaultVisibility:function(e){console.log("featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions."),d.setDefaultFlag(e)},setRequiredFlag(e){if("function"!=typeof e)throw new Error("feature.setRequiredFlag(): 1st parameter must be a function, but is "+typeof e);r.visibilities._required=t(e)},setDefaultFlag(e){if("function"!=typeof e)throw new Error("feature.defaultVisibility(): 1st parameter must be a function, but is "+typeof e);r.visibilities._default=t(e)},addPlugin:function(e){if(r.usedPlugins.includes(e))return;const t=e(d);for(let e of Object.keys(t))d[e]=t[e];r.usedPlugins.push(e)}};return function(t){e.$default&&t.setDefaultFlag(e.$default),e.$required&&t.setRequiredFlag(e.$required);const i=[...e.$plugins||[],...e._plugins||[]];e._plugins&&console.log("useFeatureToggle({_plugins:[]}): Key _plugins is deprecated. Use $plugins instead. This attribute will be removed in one of the next major versions."),i.length&&i.forEach((e=>{if("function"!=typeof e)throw new Error("featuretoggleapi()-constructor: config.plugins needs functions as entries, not "+typeof e+".");t.addPlugin(e)})),l("init")}(d),d};
|
|
2
|
+
//# sourceMappingURL=feature-toggle.min.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-toggle.min.cjs","sources":["../src/plugins/htmlplugin/plugin-html.ts","../src/featureToggle.ts","../src/plugins/urlplugin/plugin-url.ts"],"sourcesContent":["type Display = 'block' | 'inline-block' | 'inline' | 'flex' | 'inline-flex' | 'grid' | 'inline-grid';\n\ninterface HtmlPluginConfig {\n renderedTag?: string,\n featureTagName?: string,\n tagAttributeName?: string,\n nameAttributeName?:string,\n variantAttributeName?: string,\n dataAttributeName?: string,\n displayAttributeName?: string,\n defaultDisplay?: Display,\n}\n\n/*\n creates a tag that is shown / hidden, depending on the visibility rules.\n if not configured dynamically, it looks like this:\n <feature name=\"featurename\" variant=\"variantname\" data=\"data\">content </feature>\n\n Parameter: (config)\n - config.featureTagName: name of the tag. Default: \"feature\"\n - nameAttributeName: Name of the Name-Attribute: default: \"name\"\n - variantAttributeName: Name of the Variant-Attribute: default: \"variant\"\n*/\nconst defaultparams :HtmlPluginConfig = {\n renderedTag: 'div',\n featureTagName: 'feature',\n tagAttributeName: 'tag',\n nameAttributeName:'name',\n variantAttributeName: 'variant',\n dataAttributeName: 'data',\n displayAttributeName: 'display',\n defaultDisplay: 'block',\n}\nfunction parseDataAttribute(attrAsString){\n try{\n return JSON.parse(attrAsString);\n }\n catch(e)\n {\n if(!isNaN(parseFloat(attrAsString)))\n return parseFloat(attrAsString);\n \n return attrAsString;\n }\n}\n\nfunction htmlPlugin(config :HtmlPluginConfig = {}) {\n config = Object.assign({},defaultparams,config);\n\n function renderFeatureTag(elem:HTMLElement,isVisible){\n const tagname = elem.getAttribute(config.tagAttributeName) || config.renderedTag;\n const attributes = Array.from(elem.attributes);\n let attributesAsString = \"\";\n attributes.forEach(attr => {\n attributesAsString += ` ${attr.nodeName}=\"${attr.nodeValue.replace(/\"/g,\""\")}\"`;\n });\n const display = isVisible ? (elem.getAttribute(config.displayAttributeName) || config.defaultDisplay) : 'none';\n elem.outerHTML = `<${tagname} style=\"display:${display}\" _feature=\"true\" ${attributesAsString}>${elem.innerHTML}</${tagname}>`;\n } \n return function (api) {\n var renderedTags :NodeListOf<HTMLElement> = window.document.querySelectorAll(config.featureTagName);\n renderedTags.forEach(tag => { renderFeatureTag(tag,false) });\n\n api.on('visibilityrule', function (event) {\n var selector = `[_feature][${config.nameAttributeName}=\"${event.name}\"]`;\n if (event.variant) selector += `[${config.variantAttributeName}=\"${event.variant}\"]`;\n var elements :NodeListOf<HTMLElement> = document.querySelectorAll(selector);\n elements.forEach(elem => { \n const dataAsString = elem.getAttribute(config.dataAttributeName);\n const data = parseDataAttribute(dataAsString);\n \n const isVisible = api.isVisible(event.name,event.variant,data);\n renderFeatureTag(elem, isVisible);\n });\n })\n\n return { name: 'htmlplugin' };\n }\n}\n\nexport {\n htmlPlugin\n}","interface OnConfiguration {\n ignorePreviousRules: boolean\n}\ntype Plugin = (api) => Partial<FeatureToggleApi>;\n\ntype EventType = 'visibilityrule' | 'init' | 'registerEvent' | string;\ninterface OnEvent {\n name: string,\n variant: string,\n data: any,\n result?: boolean\n}\n\ntype FirstCharOfFeatureFlagKey = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' |\n 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';\n \ntype FeatureFlagKey = `${FirstCharOfFeatureFlagKey}${string}`;\ntype FeatureFlag = boolean | ((rule:Rule) => boolean);\ninterface FeatureToggleConfig {\n [key: FeatureFlagKey]: FeatureFlag,\n $plugins?: Plugin[]\n /**\n * @deprecated Use key`$plugins` instead.\n */\n _plugins?: Plugin[]\n\n /**\n * This rule will always run before the main rule. \n * If it returns false, the main rules will be skipped and false is returned\n */\n $required?: FeatureFlag\n\n /**\n * This rule will always run after the main rule. \n * If the main rule returns false, the result of the default rule will be taken.s\n */\n $default?: FeatureFlag\n}\n\ninterface Rule {\n name: string,\n variant: string,\n data: any,\n _internalCall?: true,\n description?: string\n}\n\ninterface FeatureToggleApiBase {\n name: string,\n setData(name: string, dataParam?: any): void;\n setData(name: string, variant: string, dataParam?: any): void,\n setData(nameParam: string, variantOrDataParam: string | { [key: string]: any },\n dataParam?: any): void;\n\n on(eventType: EventType, fn: (event: OnEvent) => void, config?: OnConfiguration): void;\n trigger(eventtype: EventType, param?: any);\n showLogs(showLogs?: boolean): void\n\n /**\n * @deprecated Use `featureToggle.isActive` instead.\n */\n isVisible(name: string, variant?: string, data?: any): boolean\n\n isActive(name: string, variant?: string, data?: any): boolean\n\n /**\n * @deprecated Use `featureToggle.setFlag` instead.\n */\n visibility(name: string, result: boolean | ((rule: Rule) => boolean)): void,\n /**\n * @deprecated Use `featureToggle.setFlag` instead.\n */\n visibility(name: string, variant: string | null, result: boolean | ((rule: Rule) => boolean)): void\n /**\n * @deprecated Use `featureToggle.setFlag` instead.\n */\n visibility(name: string, variant: string | null, data: any, result: boolean | ((rule: Rule) => boolean)): void,\n /**\n * @deprecated Use `featureToggle.setFlag` instead.\n */\n visibility(name: string, resultOrVariant: string | null | boolean | ((rule: Rule) => boolean), resultOrData?: any, result?: boolean | (() => boolean)): void\n\n setFlag(name: string, result: boolean | ((rule: Rule) => boolean)): void,\n setFlag(name: string, variant: string | null, result: boolean | ((rule: Rule) => boolean)): void,\n setFlag(name: string, variant: string | null, data: any, result: boolean | ((rule: Rule) => boolean)): void,\n setFlag(name: string, resultOrVariant: string | null | boolean | ((rule: Rule) => boolean), resultOrData?: any, result?: boolean | (() => boolean)): void\n\n /**\n * @deprecated Use `featureToggle.setRequiredFlag` instead.\n */\n requiredVisibility(fn: boolean | ((result: Rule) => boolean)): void\n\n /**\n * @deprecated Use `featureToggle.setDefaultFlag` instead.\n */\n defaultVisibility(fn: boolean | ((result: Rule) => boolean)): void\n\n /**\n * This rule will run first and only if it is true, the feature.setFlag() - rules apply.\n * In other words: if the required-rule returns false, all feature.setFlag-rules return false - regardless of its normal result.\n * @param fn \n */\n setRequiredFlag(fn: boolean | ((result: Rule) => boolean)): void\n\n /**\n * This is the default-rule and will be overwritten by feature.setFlag() - rules.\n * In other words: If feature.setFlag == false, the result of the defaultRule applies.\n * @param fn DefaultRule\n */\n setDefaultFlag(fn: boolean | ((result: Rule) => boolean)): void\n\n addPlugin(plugin: Plugin)\n}\n\ntype FeatureToggleApi = FeatureToggleApiBase & Record<string, any>;\n\nfunction parseToFn(fnOrBool: boolean | ((param?: any) => boolean)) {\n if (typeof fnOrBool == 'boolean')\n return function () { return fnOrBool };\n\n return fnOrBool;\n}\n\nfunction getKey(name: string, variant?: string): string {\n var _name = name.toLowerCase();\n if (variant && typeof variant == 'string') {\n _name += \"#\" + variant.toLowerCase();\n }\n\n return _name;\n}\n\nfunction initVisibilities(visibilities: FeatureToggleConfig = {}) {\n const returnVisibilities = {};\n Object.keys(visibilities).forEach(key => {\n if (key.startsWith('_') || key.startsWith('$'))\n return;\n returnVisibilities[getKey(key)] = parseToFn(visibilities[key]);\n });\n return returnVisibilities;\n}\n\nfunction useFeatureToggle(config: FeatureToggleConfig = {}): FeatureToggleApi {\n\n const globals = {\n datas: {},\n listeners: {},\n visibilities: initVisibilities(config),\n showLogs: false,\n usedPlugins: [],\n }\n\n function init(api: FeatureToggleApi) {\n if(config.$default){\n api.setDefaultFlag(config.$default);\n }\n\n if(config.$required){\n api.setRequiredFlag(config.$required);\n }\n\n const allPlugins = [...(config.$plugins||[]),...(config._plugins||[])];\n if(config._plugins){\n console.log('useFeatureToggle({_plugins:[]}): Key _plugins is deprecated. Use $plugins instead. This attribute will be removed in one of the next major versions.');\n }\n\n\n if (allPlugins.length) {\n allPlugins.forEach(plugin => {\n if (typeof plugin !== 'function')\n throw new Error('featuretoggleapi()-constructor: config.plugins needs functions as entries, not ' + typeof plugin + '.');\n\n api.addPlugin(plugin);\n });\n }\n\n triggerEvent('init');\n }\n\n function triggerEvent(eventtype: EventType, param?: any) {\n (globals.listeners[eventtype] || []).forEach(listener => {\n listener(param);\n });\n }\n\n const log = function (message) {\n if (!globals.showLogs)\n return;\n\n //Nur Browser können Syntaxhighlighting die anderen geben die Nachricht einfach aus und schneiden\n //die styletags raus\n if (typeof window === 'undefined') {\n const loggedMessage = message.replace(/<b>/g, \"\");\n console.log(loggedMessage);\n return;\n }\n\n var hasBoldTag = message.indexOf('<b>') != -1;\n var hasVisibleKeyword = message.indexOf('visible') != -1;\n var hasHiddenKeyword = message.indexOf('hidden') != -1;\n\n var _message = message.replace('visible', '%cvisible');\n _message = _message.replace('hidden', '%chidden');\n\n if (hasVisibleKeyword)\n console.log(_message, \"color:green;font-weight:bold;\");\n else if (hasHiddenKeyword)\n console.log(_message, \"color:red;font-weight:bold;\");\n else if (hasBoldTag) {\n _message = _message.replace('<b>', '%c');\n var parts = [_message, 'font-weight:bold;']\n console.log.apply(null, parts);\n }\n else\n console.log(message);\n }\n\n const logAndReturn = function (returnValue, message) {\n log(message);\n log('');\n return returnValue;\n }\n\n const getVisibility = function (visibilityFn, functionname, name, variant, data) {\n if (visibilityFn == null)\n return undefined;\n\n var calculatedVisibility = visibilityFn({ name: name, variant: variant, data: data });\n\n if (typeof calculatedVisibility == 'boolean') {\n return calculatedVisibility;\n }\n\n return logAndReturn(false, `The ${functionname} returns ${calculatedVisibility}. => Please return true or false. This result (and all non-boolean results) will return false.`);\n }\n\n function parseKey(key: string): OnEvent {\n const parts = key.split('#');\n return {\n name: parts[0],\n variant: parts.length > 1 ? parts[1] : undefined,\n data: globals.datas[key],\n }\n }\n\n /*\n the following calls are possible:\n visibility(name,result);\n visibility(name,variant,result);\n visibility(name,variant,data,result);\n \n =>\n param1: name\n param2: result || variant\n param3: result || data\n param4: result\n */\n function visibilityFnParams(param1, param2, param3, param4) {\n //name must always be set\n if (param1 == undefined)\n throw new Error('feature.visibility(): 1st parameter name must be defined');\n\n if (arguments.length == 1)\n throw new Error('feature.visibility(): 2nd parameter name must be a boolean or function, but is empty');\n\n let name = param1, variant = null, data = null, result = null;\n if (param3 == undefined && param4 == undefined) {\n result = param2;\n }\n else if (param4 == undefined) {\n variant = param2;\n result = param3;\n }\n else {\n variant = param2;\n data = param3;\n result = param4;\n }\n\n return {\n name,\n variant,\n data,\n result\n }\n }\n\n function getEvent(name: string, variant: string, data?, result?: any) {\n\n let event;\n\n event = { name, variant, data };\n\n event.key = getKey(event.name, event.variant);\n\n if (result == null)\n return event;\n\n event.visibilityFunction = parseToFn(result);\n event.result = event.visibilityFunction({\n name: event.name,\n variant: event.variant,\n data: event.data || {},\n _internalCall: true,\n description: 'When attaching a function, the result must be calculated internally. You can filter this out with the _internalCall:true -Flag.'\n })\n return event;\n }\n\n\n\n function isActive(name: string, variant?: string, data?: any): boolean {\n const visibilities = globals.visibilities;\n\n log(`\\nCheck Visibility of <b>Feature \"${name}\", variant \"${variant == undefined ? '' : variant}\"${data ? \" with data \" + JSON.stringify(data) : \"\"}.`);\n if (name == undefined)\n throw new Error('The attribute \"name\" is required for tag <feature></feature>. Example: <feature name=\"aname\"></feature>');\n\n var requiredFn = visibilities['_required'];\n var requiredFnExists = visibilities['_required'] != null;\n var requiredFnResult = getVisibility(requiredFn, 'requiredVisibility', name, variant, data);\n\n var visibilityFnKey = getKey(name, variant);\n var visibilityFn = visibilities[visibilityFnKey];\n var visibilityFnExists = visibilities[visibilityFnKey] != null;\n var visibilityFnResult = getVisibility(visibilityFn, 'visibility function', name, variant, data);\n\n var variantExists = variant != null;\n var visibilityOnlyNameFnKey = getKey(name, null);\n var visibilityOnlyNameFn = visibilities[visibilityOnlyNameFnKey];\n var visibilityOnlyNameFnExists = visibilities[visibilityOnlyNameFnKey] != null;\n var visibilityOnlyNameFnResult = getVisibility(visibilityOnlyNameFn, 'visibility function (only name)', name, variant, data);\n\n var defaultFn = visibilities['_default'];\n var defaultFnExists = visibilities['_default'] != null;\n var defaultFnResult = getVisibility(defaultFn, 'defaultVisibility', name, variant, data);\n\n if (!requiredFnExists)\n log(\"No requiredVisibility rule specified for this feature.\");\n else if (requiredFnExists && requiredFnResult === true)\n log(\"The requiredVisibility rule returns true. This feature will be shown when no other rule rejects it.\")\n else if (requiredFnExists && requiredFnResult === false)\n return logAndReturn(false, \"The requiredVisibility rule returns false. This feature will be hidden.\");\n\n if (visibilityFnExists)\n return logAndReturn(visibilityFnResult, `The visibility rule returns ${visibilityFnResult}. This feature will be ${visibilityFnResult ? 'visible' : 'hidden'}.`);\n log('No visibility rule found matching name and variant.');\n\n if (variantExists && typeof visibilityOnlyNameFnResult == 'boolean')\n return logAndReturn(visibilityOnlyNameFnResult, `Found a visibility rule for name ${name} without variants. The rule returns ${visibilityOnlyNameFnResult}. => This feature will be ${visibilityOnlyNameFnResult ? 'visible' : 'hidden'}.`);\n else if (variantExists)\n log(`No rules found for name ${name} without variants.`)\n\n\n if (defaultFnExists)\n return logAndReturn(defaultFnResult, `Found a defaultVisibility rule. The rule returns ${defaultFnResult}. => This feature will be ${defaultFnResult ? 'visible' : 'hidden'}.`);\n log(`No default rule found.`)\n\n if (requiredFnExists)\n return logAndReturn(true, `Only the requiredVisibility rule was found. This returned true. => This feature will be visible.`);\n\n return logAndReturn(false, 'No rules were found. This feature will be hidden.');\n }\n\n const api: FeatureToggleApi = {\n name: 'feature-toggle-api',\n setData: function (nameParam, variantOrDataParam, dataParam?): void {\n if (nameParam == undefined)\n throw new Error('setData(): The name must of the feature must be defined, but ist undefined');\n\n const variant = (dataParam != undefined ? variantOrDataParam : undefined) as string;\n const data = dataParam || variantOrDataParam;\n\n const event = getEvent(nameParam, variant, data);\n\n globals.datas[event.key] = event.data;\n\n triggerEvent('visibilityrule', event);\n },\n on(eventtype: EventType, fn, config?) {\n globals.listeners[eventtype] = globals.listeners[eventtype] || [];\n globals.listeners[eventtype].push(fn);\n\n triggerEvent('registerEvent', {\n type: eventtype\n })\n if (config != undefined && config.ignorePreviousRules)\n return;\n\n \n Object.keys(globals.visibilities).forEach(key => {\n const event = parseKey(key);\n const rule = globals.visibilities[key];\n event.result = rule(event);\n fn(event);\n });\n },\n trigger: triggerEvent,\n showLogs: function (showLogs?: boolean): void {\n globals.showLogs = showLogs == undefined ? true : showLogs;\n },\n isVisible(name,variant,data){\n console.log('featureToggle.isVisible is deprecated. use featureToggle.isActive instead. This function will be removed in one of the next major versions.');\n return isActive(name,variant,data);\n },\n isActive,\n /**\n the following function calls are possible:\n visibility(name,result);\n visibility(name,variant,result);\n visibility(name,variant,data,result);\n */\n setFlag(name, resultOrVariant, resultOrData?, result?) {\n const params = visibilityFnParams(name, resultOrVariant, resultOrData, result);\n const event = getEvent(params.name, params.variant, params.data, params.result);\n\n globals.visibilities[event.key] = event.visibilityFunction;\n globals.datas[event.key] = event.data;\n triggerEvent('visibilityrule', event);\n },\n visibility: function (name, resultOrVariant, resultOrData?, result?) {\n console.log('featureToggle.visibility is deprecated. use featureToggle.setVisibility instead. This function will be removed in one of the next major versions.');\n\n api.setFlag(name, resultOrVariant, resultOrData, result);\n },\n requiredVisibility: function (fn) {\n console.log('featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions.');\n\n api.setRequiredFlag(fn);\n },\n defaultVisibility: function (fn) {\n console.log('featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions.');\n\n api.setDefaultFlag(fn);\n },\n setRequiredFlag(fn) {\n if (typeof fn != \"function\")\n throw new Error('feature.setRequiredFlag(): 1st parameter must be a function, but is ' + typeof fn);\n\n globals.visibilities['_required'] = parseToFn(fn);\n },\n setDefaultFlag(fn) {\n if (typeof fn != \"function\")\n throw new Error('feature.defaultVisibility(): 1st parameter must be a function, but is ' + typeof fn);\n\n globals.visibilities['_default'] = parseToFn(fn);\n },\n addPlugin: function (plugin) {\n if (globals.usedPlugins.includes(plugin))\n return;\n\n const newPlugin = plugin(api);\n\n for(let _key of Object.keys(newPlugin)){\n api[_key] = newPlugin[_key];\n }\n\n globals.usedPlugins.push(plugin);\n },\n };\n init(api);\n\n return api;\n}\n\nexport default useFeatureToggle;","interface URLPluginConfig{\n useMockedWindow?: boolean,\n url?: string,\n prefix?: string\n\n}\n\nfunction useWindowMock(){\n return {\n isMocked: true,\n decodeURIComponent:function(param1){\n return param1;\n }\n }\n}\n\ndeclare global {\n interface Window {\n isMocked: boolean\n }\n }\n\n declare var window: Window;\n\nfunction parseValue(value){\n if(value === 'true')\n return true;\n return false;\n}\n\nfunction getParams(url,window) {\n var params = {};\n if (!url) \n return [];\n \n var urlparts = url.split(\"?\");\n\n //no params available for url\n if(urlparts.length < 2)\n return [];\n\n const parts = urlparts[1].split('&');\n\n parts.forEach(function (part) {\n var pair = part.split('=');\n pair[0] = window.decodeURIComponent(pair[0]);\n pair[1] = parseValue(window.decodeURIComponent(pair[1]));\n params[pair[0]] = (pair[1] !== 'undefined') ?\n pair[1] : true;\n });\n\n return params;\n }\n\n function urlPlugin(config: URLPluginConfig={}) {\n let _window;\n\n if(config.useMockedWindow)\n _window = useWindowMock();\n else\n _window = window;\n \n config = Object.assign({},{\n url: _window.isMocked ? \"\" : _window.location.href,\n prefix: \"\"\n },config);\n\n \n\n return function(api){\n api.url = config.url;\n const urlparams = getParams(config.url,_window);\n const prefix = config.prefix;\n\n Object.keys(urlparams).forEach(key => {\n if(!key.startsWith(prefix))\n return;\n \n const keyWithoutPrefix = key.replace(prefix,\"\");\n api.visibility(keyWithoutPrefix,urlparams[key]);\n });\n\n return {name: 'urlplugin'};\n }\n\n}\n\nexport {\n urlPlugin\n}"],"names":["defaultparams","renderedTag","featureTagName","tagAttributeName","nameAttributeName","variantAttributeName","dataAttributeName","displayAttributeName","defaultDisplay","parseToFn","fnOrBool","getKey","name","variant","_name","toLowerCase","initVisibilities","visibilities","returnVisibilities","Object","keys","forEach","key","startsWith","config","renderFeatureTag","elem","isVisible","tagname","getAttribute","attributes","Array","from","attributesAsString","attr","nodeName","nodeValue","replace","display","outerHTML","innerHTML","assign","api","window","document","querySelectorAll","tag","on","event","selector","data","attrAsString","JSON","parse","e","isNaN","parseFloat","parseDataAttribute","_window","useMockedWindow","isMocked","decodeURIComponent","param1","url","location","href","prefix","urlparams","params","urlparts","split","length","part","pair","getParams","keyWithoutPrefix","visibility","globals","datas","listeners","showLogs","usedPlugins","triggerEvent","eventtype","param","listener","log","message","hasBoldTag","indexOf","hasVisibleKeyword","hasHiddenKeyword","_message","console","parts","apply","loggedMessage","logAndReturn","returnValue","getVisibility","visibilityFn","functionname","calculatedVisibility","getEvent","result","visibilityFunction","_internalCall","description","isActive","undefined","stringify","Error","requiredFn","requiredFnExists","requiredFnResult","visibilityFnKey","visibilityFnExists","visibilityFnResult","variantExists","visibilityOnlyNameFn","visibilityOnlyNameFnResult","defaultFn","defaultFnExists","defaultFnResult","setData","nameParam","variantOrDataParam","dataParam","fn","push","type","ignorePreviousRules","parseKey","rule","trigger","setFlag","resultOrVariant","resultOrData","param2","param3","param4","arguments","visibilityFnParams","requiredVisibility","setRequiredFlag","defaultVisibility","setDefaultFlag","addPlugin","plugin","includes","newPlugin","_key","$default","$required","allPlugins","$plugins","_plugins","init"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e={}){let t;return t=e.useMockedWindow?{isMocked:!0,decodeURIComponent:function(e){return e}}:window,e=Object.assign({},{url:t.isMocked?"":t.location.href,prefix:""},e),function(i){i.url=e.url;const n=function(e,t){var i={};if(!e)return[];var n=e.split("?");return n.length<2?[]:(n[1].split("&").forEach((function(e){var n=e.split("=");n[0]=t.decodeURIComponent(n[0]),n[1]="true"===t.decodeURIComponent(n[1]),i[n[0]]="undefined"===n[1]||n[1]})),i)}(e.url,t),r=e.prefix;return Object.keys(n).forEach((e=>{if(!e.startsWith(r))return;const t=e.replace(r,"");i.visibility(t,n[e])})),{name:"urlplugin"}}}const t={renderedTag:"div",featureTagName:"feature",tagAttributeName:"tag",nameAttributeName:"name",variantAttributeName:"variant",dataAttributeName:"data",displayAttributeName:"display",defaultDisplay:"block"};function i(e={}){function i(t,i){const n=t.getAttribute(e.tagAttributeName)||e.renderedTag,r=Array.from(t.attributes);let l="";r.forEach((e=>{l+=` ${e.nodeName}="${e.nodeValue.replace(/"/g,""")}"`}));const a=i?t.getAttribute(e.displayAttributeName)||e.defaultDisplay:"none";t.outerHTML=`<${n} style="display:${a}" _feature="true" ${l}>${t.innerHTML}</${n}>`}return e=Object.assign({},t,e),function(t){return window.document.querySelectorAll(e.featureTagName).forEach((e=>{i(e,!1)})),t.on("visibilityrule",(function(n){var r=`[_feature][${e.nameAttributeName}="${n.name}"]`;n.variant&&(r+=`[${e.variantAttributeName}="${n.variant}"]`),document.querySelectorAll(r).forEach((r=>{const l=function(e){try{return JSON.parse(e)}catch(t){return isNaN(parseFloat(e))?e:parseFloat(e)}}(r.getAttribute(e.dataAttributeName));i(r,t.isVisible(n.name,n.variant,l))}))})),{name:"htmlplugin"}}}function n(e){return"boolean"==typeof e?function(){return e}:e}function r(e,t){var i=e.toLowerCase();return t&&"string"==typeof t&&(i+="#"+t.toLowerCase()),i}function l(e={}){const t={};return Object.keys(e).forEach((i=>{i.startsWith("_")||i.startsWith("$")||(t[r(i)]=n(e[i]))})),t}function a(e={}){const t={datas:{},listeners:{},visibilities:l(e),showLogs:!1,usedPlugins:[]};function i(e,i){(t.listeners[e]||[]).forEach((e=>{e(i)}))}const a=function(e){if(t.showLogs)if("undefined"!=typeof window){var i=-1!=e.indexOf("<b>"),n=-1!=e.indexOf("visible"),r=-1!=e.indexOf("hidden"),l=e.replace("visible","%cvisible");if(l=l.replace("hidden","%chidden"),n)console.log(l,"color:green;font-weight:bold;");else if(r)console.log(l,"color:red;font-weight:bold;");else if(i){var a=[l=l.replace("<b>","%c"),"font-weight:bold;"];console.log.apply(null,a)}else console.log(e)}else{const t=e.replace(/<b>/g,"");console.log(t)}},u=function(e,t){return a(t),a(""),e},s=function(e,t,i,n,r){if(null!=e){var l=e({name:i,variant:n,data:r});return"boolean"==typeof l?l:u(!1,`The ${t} returns ${l}. => Please return true or false. This result (and all non-boolean results) will return false.`)}};function o(e,t,i,l){let a;return a={name:e,variant:t,data:i},a.key=r(a.name,a.variant),null==l||(a.visibilityFunction=n(l),a.result=a.visibilityFunction({name:a.name,variant:a.variant,data:a.data||{},_internalCall:!0,description:"When attaching a function, the result must be calculated internally. You can filter this out with the _internalCall:true -Flag."})),a}function f(e,i,n){const l=t.visibilities;if(a(`\nCheck Visibility of <b>Feature "${e}", variant "${null==i?"":i}"${n?" with data "+JSON.stringify(n):""}.`),null==e)throw new Error('The attribute "name" is required for tag <feature></feature>. Example: <feature name="aname"></feature>');var o=l._required,f=null!=l._required,d=s(o,"requiredVisibility",e,i,n),c=r(e,i),b=l[c],g=null!=l[c],h=s(b,"visibility function",e,i,n),v=null!=i,m=l[r(e,null)],y=s(m,"visibility function (only name)",e,i,n),p=l._default,w=null!=l._default,T=s(p,"defaultVisibility",e,i,n);if(f){if(f&&!0===d)a("The requiredVisibility rule returns true. This feature will be shown when no other rule rejects it.");else if(f&&!1===d)return u(!1,"The requiredVisibility rule returns false. This feature will be hidden.")}else a("No requiredVisibility rule specified for this feature.");return g?u(h,`The visibility rule returns ${h}. This feature will be ${h?"visible":"hidden"}.`):(a("No visibility rule found matching name and variant."),v&&"boolean"==typeof y?u(y,`Found a visibility rule for name ${e} without variants. The rule returns ${y}. => This feature will be ${y?"visible":"hidden"}.`):(v&&a(`No rules found for name ${e} without variants.`),w?u(T,`Found a defaultVisibility rule. The rule returns ${T}. => This feature will be ${T?"visible":"hidden"}.`):(a("No default rule found."),f?u(!0,"Only the requiredVisibility rule was found. This returned true. => This feature will be visible."):u(!1,"No rules were found. This feature will be hidden."))))}const d={name:"feature-toggle-api",setData:function(e,n,r){if(null==e)throw new Error("setData(): The name must of the feature must be defined, but ist undefined");const l=o(e,null!=r?n:void 0,r||n);t.datas[l.key]=l.data,i("visibilityrule",l)},on(e,n,r){t.listeners[e]=t.listeners[e]||[],t.listeners[e].push(n),i("registerEvent",{type:e}),null!=r&&r.ignorePreviousRules||Object.keys(t.visibilities).forEach((e=>{const i=function(e){const i=e.split("#");return{name:i[0],variant:i.length>1?i[1]:void 0,data:t.datas[e]}}(e),r=t.visibilities[e];i.result=r(i),n(i)}))},trigger:i,showLogs:function(e){t.showLogs=null==e||e},isVisible:(e,t,i)=>(console.log("featureToggle.isVisible is deprecated. use featureToggle.isActive instead. This function will be removed in one of the next major versions."),f(e,t,i)),isActive:f,setFlag(e,n,r,l){const a=function(e,t,i,n){if(null==e)throw new Error("feature.visibility(): 1st parameter name must be defined");if(1==arguments.length)throw new Error("feature.visibility(): 2nd parameter name must be a boolean or function, but is empty");let r=null,l=null,a=null;return null==i&&null==n?a=t:null==n?(r=t,a=i):(r=t,l=i,a=n),{name:e,variant:r,data:l,result:a}}(e,n,r,l),u=o(a.name,a.variant,a.data,a.result);t.visibilities[u.key]=u.visibilityFunction,t.datas[u.key]=u.data,i("visibilityrule",u)},visibility:function(e,t,i,n){console.log("featureToggle.visibility is deprecated. use featureToggle.setVisibility instead. This function will be removed in one of the next major versions."),d.setFlag(e,t,i,n)},requiredVisibility:function(e){console.log("featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions."),d.setRequiredFlag(e)},defaultVisibility:function(e){console.log("featureToggle.requiredVisibility is deprecated. use featureToggle.setRequiredFlag instead. This function will be removed in one of the next major versions."),d.setDefaultFlag(e)},setRequiredFlag(e){if("function"!=typeof e)throw new Error("feature.setRequiredFlag(): 1st parameter must be a function, but is "+typeof e);t.visibilities._required=n(e)},setDefaultFlag(e){if("function"!=typeof e)throw new Error("feature.defaultVisibility(): 1st parameter must be a function, but is "+typeof e);t.visibilities._default=n(e)},addPlugin:function(e){if(t.usedPlugins.includes(e))return;const i=e(d);for(let e of Object.keys(i))d[e]=i[e];t.usedPlugins.push(e)}};return function(t){e.$default&&t.setDefaultFlag(e.$default),e.$required&&t.setRequiredFlag(e.$required);const n=[...e.$plugins||[],...e._plugins||[]];e._plugins&&console.log("useFeatureToggle({_plugins:[]}): Key _plugins is deprecated. Use $plugins instead. This attribute will be removed in one of the next major versions."),n.length&&n.forEach((e=>{if("function"!=typeof e)throw new Error("featuretoggleapi()-constructor: config.plugins needs functions as entries, not "+typeof e+".");t.addPlugin(e)})),i("init")}(d),d}export{i as htmlPlugin,e as urlPlugin,a as useFeatureToggle};
|
|
2
|
+
//# sourceMappingURL=feature-toggle.min.js.map
|