@ultimat3/flags 19.2.0 → 19.3.2
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/package.json +2 -2
- package/src/targeting-assert.ts +18 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/flags",
|
|
3
|
-
"version": "19.2
|
|
3
|
+
"version": "19.3.2",
|
|
4
4
|
"description": "Feature flags: permanent switches, and temporary ones that cannot be forgotten",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"test": "bun test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ultimat3/core": "19.2
|
|
34
|
+
"@ultimat3/core": "19.3.2"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/targeting-assert.ts
CHANGED
|
@@ -31,6 +31,7 @@ const LIST_EXAMPLE: Readonly<Record<IdListField, string>> = {
|
|
|
31
31
|
* | `default: true` with a `rollout` | the two answer the same actors and disagree; there is no reading of "on for everyone, and also on for 10%" |
|
|
32
32
|
* | `bucketBy` with no `rollout` | it names what a rollout divides, and there is no rollout to divide |
|
|
33
33
|
* | a blank `bucketBy` | names no kind at all |
|
|
34
|
+
* | `subjects` that is not a map | reachable from a store snapshot; `null` reached `Object.entries` as a bare `TypeError` |
|
|
34
35
|
* | `subjects.actor` / `subjects.org` | `actors` and `orgs` are the one spelling; two would disagree |
|
|
35
36
|
* | a `subjects` entry that is not a list of non-empty ids | reachable from a store snapshot, and it matches nothing while reading as an allow list |
|
|
36
37
|
*
|
|
@@ -133,8 +134,25 @@ function assertIdList(key: string, field: IdListField, list: unknown): void {
|
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
/**
|
|
138
|
+
* `subjects` is a MAP at all, established before it is walked — the check `assertObject` makes one
|
|
139
|
+
* level up, on the one rank it did not reach. The declared parameter type is a promise the caller
|
|
140
|
+
* makes and `applyFlagSnapshot` lands a store payload nobody made it for: `subjects: null` reached
|
|
141
|
+
* `Object.entries` as a bare `TypeError` out of the function whose whole job is a coded refusal,
|
|
142
|
+
* while `bucketBy: null`, `rollout: null` and `actors: null` all answered
|
|
143
|
+
* `X_FLAG_TARGETING_INVALID`. A bare string is the quieter half — `Object.entries('ab')` walks it
|
|
144
|
+
* by index, so it was reported as a kind called `0`, which describes nothing an author wrote.
|
|
145
|
+
*/
|
|
136
146
|
function assertSubjects(key: string, subjects: Readonly<Record<string, readonly string[]>>): void {
|
|
137
147
|
const fix = `give each subjects entry a kind and a list of ids — { bank: ['bank_integration:bbva'] } — in defineFlag({ key: '${key}' })`;
|
|
148
|
+
const given: unknown = subjects;
|
|
149
|
+
if (typeof given !== 'object' || given === null || Array.isArray(given)) {
|
|
150
|
+
throw flagTargetingInvalid(
|
|
151
|
+
key,
|
|
152
|
+
`subjects is ${renderGiven(given)}, which is not a map of subject kind to ids`,
|
|
153
|
+
fix,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
138
156
|
for (const [kind, ids] of Object.entries<unknown>(subjects)) {
|
|
139
157
|
if (kind.trim() === '') throw flagTargetingInvalid(key, 'a subjects kind is blank', fix);
|
|
140
158
|
if (isBuiltInSubjectKind(kind)) {
|