react-ability-kit 0.1.3 → 0.1.5

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.
Files changed (2) hide show
  1. package/README.md +117 -111
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,22 +1,29 @@
1
1
  # React Ability
2
2
 
3
- A small, typed permission layer for React that keeps authorization logic **out of your components** and **in one place**.
3
+ **A small, strongly-typed permission layer for React**
4
+ Keep authorization logic **out of your components** and **in one place**.
4
5
 
5
6
  ---
6
7
 
7
- ## Core idea (in one sentence)
8
+ ## Why this exists
8
9
 
9
- > The package centralizes and standardizes permission logic so your UI doesn’t turn into a mess of `if (user.role === …)` checks scattered everywhere.
10
+ Most React apps don’t plan to become permission nightmares they just grow into one.
10
11
 
11
- That’s it. Everything else is implementation details.
12
+ This package introduces a **policy-first** approach to permissions, so your UI stays clean and your rules stay auditable.
12
13
 
13
14
  ---
14
15
 
15
- ## The real problem (what goes wrong in real apps)
16
+ ## Core idea (one sentence)
17
+
18
+ > Define permission rules once, then query them everywhere — instead of scattering fragile `if` checks across your UI.
19
+
20
+ Everything else is just implementation details.
21
+
22
+ ---
16
23
 
17
- Let’s start with how apps usually look **without** a permission layer.
24
+ ## The real problem (what goes wrong in real apps)
18
25
 
19
- ### ❌ Without a package (today’s reality)
26
+ ### ❌ Without a permission layer
20
27
 
21
28
  ```tsx
22
29
  // Button.tsx
@@ -41,55 +48,48 @@ if (user && user.role !== "guest") {
41
48
  }
42
49
  ```
43
50
 
51
+ ### Problems this creates
44
52
 
45
- Problems this creates
46
- Logic duplication
47
- The same rules are written differently in many files.
48
-
49
- Rules drift
50
- Someone updates one condition but forgets others.
53
+ - **Logic duplication** – same rules rewritten in different places
54
+ - **Rules drift** – one condition changes, others don’t
55
+ - **Impossible to audit** “Who can edit invoices?” → grep the whole repo
56
+ - ❌ **UI inconsistencies**
57
+ - Button visible but API rejects
58
+ - Button hidden but API allows
59
+ - ❌ **No type safety**
51
60
 
52
- ❌ Impossible to audit
53
- “Who can edit invoices?” you must search the entire codebase.
61
+ ```ts
62
+ "inovice:update" // typo = silent bug
63
+ ```
54
64
 
55
- UI bugs
56
- Button visible but API rejects
65
+ - **Hard to evolve roles** – adding a new role breaks logic everywhere
57
66
 
58
- Button hidden but API allows
67
+ ---
59
68
 
60
- No type safety
61
- ts
62
- Copier le code
63
- "inovice:update" // typo = silent bug
64
- ❌ Hard to change roles
65
- Adding a new role breaks logic everywhere.
69
+ ## The missing abstraction: policy-first permissions
66
70
 
67
- What this package introduces (the missing abstraction)
68
- Key idea: policy-first permissions
69
71
  Instead of asking:
70
72
 
71
- “Can the user do this?”
72
-
73
- everywhere in the UI…
73
+ > “Can the user do this?”
74
+ > everywhere in the UI…
74
75
 
75
76
  You define rules once, then query them everywhere.
76
77
 
77
- Mental model (important)
78
- Think of your app like this:
78
+ ### Mental model
79
79
 
80
- ```bash
80
+ ```text
81
81
  User + Context → Ability → UI decisions
82
82
  ```
83
83
 
84
- Your package only handles the Ability part.
85
-
86
- ```bash
84
+ ```text
87
85
  User ──► Policy ──► Ability ──► UI / Components
88
86
  ```
89
87
 
90
- What the package actually solves (concretely)
91
- 1️⃣ Single source of truth for permissions
92
- Instead of scattered checks, you get one policy file:
88
+ ---
89
+
90
+ ## What this package actually solves
91
+
92
+ ### 1️⃣ Single source of truth for permissions
93
93
 
94
94
  ```ts
95
95
  // policy.ts
@@ -97,13 +97,16 @@ allow("update", "Invoice", invoice => invoice.ownerId === user.id);
97
97
  deny("delete", "Invoice");
98
98
  ```
99
99
 
100
- Result:
100
+ **Result**
101
101
 
102
- All permission logic lives in one place
102
+ - All rules live in one place
103
+ - Easy to review, change, and reason about
104
+ - No more scattered conditions
105
+
106
+ ---
103
107
 
104
- Easy to review, change, and reason about
108
+ ### 2️⃣ Business rules become readable policies
105
109
 
106
- 2️⃣ Turns business rules into readable policies
107
110
  ❌ Before
108
111
 
109
112
  ```ts
@@ -115,7 +118,7 @@ if (
115
118
  )
116
119
  ```
117
120
 
118
- With the package
121
+ After
119
122
 
120
123
  ```ts
121
124
  allow(
@@ -125,12 +128,15 @@ allow(
125
128
  );
126
129
  ```
127
130
 
128
- This is domain language, not UI logic.
131
+ This is **domain language**, not UI logic.
132
+
133
+ ---
134
+
135
+ ### 3️⃣ Removes permission logic from components
129
136
 
130
- 3️⃣ Removes permission logic from components
131
137
  ❌ Before
132
138
 
133
- ```ts
139
+ ```tsx
134
140
  {user?.role === "admin" && <DeleteButton />}
135
141
  ```
136
142
 
@@ -142,10 +148,11 @@ This is domain language, not UI logic.
142
148
  </Can>
143
149
  ```
144
150
 
145
- Components now care only about UI, not authorization details.
151
+ Your components focus on **rendering**, not authorization.
152
+
153
+ ---
146
154
 
147
- 4️⃣ Prevents permission bugs at compile time (TypeScript win)
148
- This is huge.
155
+ ### 4️⃣ Type-safe permissions (TypeScript win)
149
156
 
150
157
  ❌ Without typing
151
158
 
@@ -160,55 +167,62 @@ can("updtae", "Invioce");
160
167
  // ❌ TypeScript error immediately
161
168
  ```
162
169
 
163
- This eliminates an entire class of bugs.
170
+ This removes an entire class of bugs.
171
+
172
+ ---
173
+
174
+ ### 5️⃣ Ownership rules become first-class
164
175
 
165
- 5️⃣ Makes ownership rules first-class (not hacks)
166
- Ownership checks are usually scattered:
176
+ Scattered ownership checks
167
177
 
168
178
  ```ts
169
179
  if (invoice.ownerId === user.id)
170
180
  ```
171
181
 
172
- With this package:
182
+ Centralized ownership rule
173
183
 
174
184
  ```ts
175
185
  allow("update", "Invoice", invoice => invoice.ownerId === user.id);
176
186
  ```
177
187
 
178
- Ownership logic becomes:
188
+ Ownership logic is now:
179
189
 
180
- consistent
190
+ - consistent
191
+ - reusable
192
+ - testable
181
193
 
182
- reusable
194
+ ---
183
195
 
184
- testable
196
+ ### 6️⃣ Predictable SSR & hydration
185
197
 
186
- 6️⃣ Makes SSR and hydration predictable
187
198
  Without a system:
188
199
 
189
- UI flickers
190
-
191
- Buttons appear/disappear after hydration
200
+ - UI flickers
201
+ - Buttons appear/disappear after hydration
202
+ - Server/client logic diverges
192
203
 
193
- Different logic runs on server vs client
204
+ With **React Ability**:
194
205
 
195
- With this package:
206
+ - Ability is built once from user data
207
+ - Server and client agree on permissions
208
+ - Stable, predictable rendering
196
209
 
197
- Ability is created once from the same user data
210
+ ---
198
211
 
199
- Server and client render the same decisions
212
+ ## What `<Can />` actually does
200
213
 
201
- What the <Can /> component really is
202
214
  It’s not magic.
203
215
 
204
216
  It simply means:
205
217
 
206
- Render children only if a permission rule passes.”
218
+ > Render children **only if the permission passes**.
207
219
 
208
220
  Instead of:
221
+
209
222
  ```tsx
210
223
  if (!canEdit) return null;
211
224
  ```
225
+
212
226
  You write:
213
227
 
214
228
  ```tsx
@@ -219,68 +233,60 @@ You write:
219
233
 
220
234
  That’s it.
221
235
 
222
- What this package is NOT
223
- This is important.
224
-
225
- ❌ Not an auth system
226
- ❌ Not a backend security layer
227
- ❌ Not a role manager UI
228
- ❌ Not a permission database
229
-
230
- This package:
231
-
232
- does not replace backend checks
233
-
234
- does not handle authentication
236
+ ---
235
237
 
236
- does not store roles
238
+ ## What this package is NOT
237
239
 
238
- It only answers one question:
240
+ Not an authentication system
241
+ ❌ Not a backend security layer
242
+ ❌ Not a role management UI
243
+ ❌ Not a permission database
239
244
 
240
- “Given a user and a resource, is this action allowed?”
245
+ This package **does not**:
241
246
 
242
- When this package makes sense
243
- SaaS dashboards
244
- ✅ Multi-role apps
245
- ✅ B2B products
246
- ✅ Apps with ownership rules
247
- ✅ Teams larger than 1 developer
247
+ - replace backend checks
248
+ - handle authentication
249
+ - store users or roles
248
250
 
249
- When it’s overkill
250
- ❌ Landing pages
251
- ❌ Simple blogs
252
- ❌ Apps with only admin / non-admin logic
251
+ It answers one question only:
253
252
 
254
- Why this is worth publishing
255
- Most developers:
253
+ > **“Given a user and a resource, is this action allowed?”**
256
254
 
257
- feel this pain
255
+ ---
258
256
 
259
- write ad-hoc permission logic
257
+ ## When this package makes sense
260
258
 
261
- never extract it cleanly
259
+ - SaaS dashboards
260
+ - ✅ Multi-role applications
261
+ - ✅ B2B products
262
+ - ✅ Ownership-based rules
263
+ - ✅ Teams larger than one developer
262
264
 
263
- This package:
265
+ ---
264
266
 
265
- gives a clear, repeatable pattern
267
+ ## When it’s overkill
266
268
 
267
- provides excellent TypeScript DX
269
+ - Landing pages
270
+ - ❌ Simple blogs
271
+ - ❌ Apps with only admin / non-admin logic
268
272
 
269
- keeps the API small and focused
273
+ ---
270
274
 
271
- That’s exactly what successful small libraries do.
275
+ ## Final summary
272
276
 
273
- Final simplified summary
274
- This package solves one problem:
277
+ **React Ability solves one problem:**
275
278
 
276
- How do I express and use permissions in React without scattering fragile conditional logic everywhere?”
279
+ > How do I express and use permissions in React without scattering fragile conditional logic everywhere?
277
280
 
278
- It solves it by:
281
+ It does this by:
279
282
 
280
- centralizing permission rules
283
+ - centralizing permission rules
284
+ - typing actions and resources
285
+ - exposing a clean `can()` API
286
+ - providing `<Can />` for UI rendering
281
287
 
282
- typing actions and resources
288
+ ---
283
289
 
284
- exposing a clean can() API
290
+ ## Credits
285
291
 
286
- providing <Can /> for UI rendering
292
+ Created by **Mohamed Ali Sraieb**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-ability-kit",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",