Skip to content

Commit 3f03b9b

Browse files
committed
preparing for 1.0.0
1 parent 8ed5e6a commit 3f03b9b

File tree

2 files changed

+68
-49
lines changed

2 files changed

+68
-49
lines changed

README.md

Lines changed: 67 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ A minimalist Feature Flag engine for CFML apps
1515
- Rules engine
1616
- DSL (Domain Specific Language) for defining flags as data
1717
- Methods for flag CRUD, and evaluation
18-
- [![Tests](https://github.com/atuttle/semaphore/actions/workflows/main_tests.yml/badge.svg)](https://github.com/atuttle/semaphore/actions/workflows/main_tests.yml) Comprehensive test suite so that you know all of the above is trustworthy
18+
- [![Tests](https://github.com/atuttle/semaphore/actions/workflows/main_tests.yml/badge.svg)](https://github.com/atuttle/semaphore/actions/workflows/main_tests.yml) 👈🏻 Comprehensive test suite so that you know all of the above is trustworthy
1919

2020
### What's NOT included?
2121

@@ -57,74 +57,101 @@ I recommend storing this in the user session to eliminate repetitive data lookup
5757

5858
## Flag Definitions
5959

60-
This is likely to change, but for now here's what they look like:
61-
6260
```js
6361
{
6462
'example_percentage_flag': {
6563
name: 'Example Percentage Flag',
66-
description: 'This flag is only true for ~50% of the user population',
64+
description: 'This flag is only active for ~50% of the user population',
6765
active: true,
6866
rules: [
69-
{
70-
type: '%',
71-
percentage: 50
72-
}
67+
[
68+
{
69+
type: '%',
70+
percentage: 50
71+
}
72+
]
7373
]
7474
}
7575
,'example_userId_flag': {
7676
name: 'Example UserId Flag',
77-
description: 'This flag is only true for userId 42',
77+
description: 'This flag is only active for userId 42',
7878
active: true,
7979
rules: [
80-
{
81-
type: 'filter',
82-
attribute: 'userId',
83-
operator: '=',
84-
comparator: 42
85-
}
80+
[
81+
{
82+
type: 'filter',
83+
attribute: 'userId',
84+
operator: '=',
85+
comparator: 42
86+
}
87+
]
8688
]
8789
}
8890
,'example_email_flag': {
8991
name: 'Example Email Flag',
90-
description: 'This flag is only true for [email protected]',
92+
description: 'This flag is only active for [email protected]',
9193
active: true,
92-
baseState: false,
9394
rules: [
94-
{
95-
type: 'filter',
96-
attribute: 'userEmail',
97-
operator: 'in',
98-
comparator: ['[email protected]']
99-
}
95+
[
96+
{
97+
type: 'filter',
98+
attribute: 'userEmail',
99+
operator: 'in',
100+
comparator: ['[email protected]']
101+
}
102+
]
100103
]
101104
}
102105
,'example_AND_flag': {
103106
name: 'Example AND Flag',
104-
description: 'This flag requires both rules to evaluate to TRUE',
107+
description: 'This flag is active only if both rules to evaluate to TRUE (user has role writer, and user has betaOptIn=true)',
108+
active: true,
109+
rules: [
110+
[
111+
112+
{
113+
type: 'filter',
114+
attribute: 'role',
115+
operator: 'has',
116+
comparator: ['writer']
117+
},
118+
{
119+
type: 'filter',
120+
attribute: 'betaOptIn',
121+
operator: '==',
122+
comparator: true
123+
}
124+
]
125+
]
126+
}
127+
,'example_OR_flag': {
128+
name: 'Example AND Flag',
129+
description: 'This flag is active if either rule evaluates to TRUE (user has role writer, OR user has betaOptIn=true)',
105130
active: true,
106-
baseState: false,
107-
matchRules: 'all',
108131
rules: [
109-
{
110-
type: 'filter',
111-
attribute: 'role',
112-
operator: 'has',
113-
comparator: ['writer']
114-
},
115-
{
116-
type: 'filter',
117-
attribute: 'betaOptIn',
118-
operator: '==',
119-
comparator: true
120-
}
132+
[
133+
134+
{
135+
type: 'filter',
136+
attribute: 'role',
137+
operator: 'has',
138+
comparator: ['writer']
139+
}
140+
],
141+
[
142+
{
143+
type: 'filter',
144+
attribute: 'betaOptIn',
145+
operator: '==',
146+
comparator: true
147+
}
148+
]
121149
]
122150
}
123151
,'example_inactive_flag': {
124152
name: 'Example Inactive Flag',
125-
description: 'This flag is false for everyone because it is inactive',
153+
description: 'This flag is inactive',
126154
active: false,
127-
baseState: false,
128155
rules: []
129156
}
130157
}
@@ -138,14 +165,6 @@ This is likely to change, but for now here's what they look like:
138165
- `everybody`: Flag is ON for all users
139166
- More TBD? If you have ideas, [hit me up!](https://github.com/atuttle/semaphore/issues)
140167

141-
#### AND vs. OR
142-
143-
Flags can have multiple rules. At present, Semaphore only supports flag-wide AND/OR: You can require that `ALL` of the rules evaluate to TRUE, or that `ANY` of the rules evaluate to TRUE.
144-
145-
The default is `ANY`. If you want to require all rules match, set `matchRules: 'ALL'` on your flag.
146-
147-
> **Deprecation warning:** In version 1.x the `matchRules` property will be removed in support of [better and/or support](https://adamtuttle.codes/blog/2022/semaphore-0.3-and-1.0/).
148-
149168
# Why not just use config settings?
150169

151170
You could do that, sure. But the value proposition of feature flags is that they can be toggled independendtly of deploying code changes to your application, and often much more rapidly. They can take effect as quickly as you can update the flag state on your application. How you do that is left as an exercise for you.

box.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "semaphore",
3-
"version": "0.3.0",
3+
"version": "1.0.0",
44
"author": "Adam Tuttle <https://adamtuttle.codes>",
55
"location": "ForgeboxStorage",
66
"homepage": "https://github.com/atuttle/semaphore",

0 commit comments

Comments
 (0)