02-rbor 0.2.0 β 0.2.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.
- package/README.md +676 -606
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,606 +1,676 @@
|
|
|
1
|
-
# 02-rBOR CLI
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/02-rbor)
|
|
4
|
-
[](https://github.com/02-davinci-01/02-rbor/actions)
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
6
|
-
|
|
7
|
-
> **Scaffold Clean Architecture-inspired React features with dependency graph analysis**
|
|
8
|
-
|
|
9
|
-
A CLI tool for building frontend applications following the **02-rBOR** architecture pattern. Generate domain-driven feature modules with proper layering, enforce architectural rules, and analyze dependency graphs β with SVG visualization out of the box.
|
|
10
|
-
|
|
11
|
-
## π€ What is rBOR?
|
|
12
|
-
|
|
13
|
-
rBOR is an opinionated folder architecture for React apps. Instead of organizing by file type (`components/`, `hooks/`, `services/` at the root), rBOR organizes by **domain** β each feature gets its own self-contained folder with every layer it needs.
|
|
14
|
-
|
|
15
|
-
The idea: a `user` feature shouldn't scatter its files across 6 different top-level folders. Everything related to `user` lives under `domains/user/`, with a single barrel export (`index.tsx`) as the public API.
|
|
16
|
-
|
|
17
|
-
Each domain follows a strict **downward dependency rule** inspired by the [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle):
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
(route)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
##
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
rbor
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
domains/user
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
β
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
rbor
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
rbor
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
1
|
+
# 02-rBOR CLI
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/02-rbor)
|
|
4
|
+
[](https://github.com/02-davinci-01/02-rbor/actions)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
> **Scaffold Clean Architecture-inspired React features with dependency graph analysis**
|
|
8
|
+
|
|
9
|
+
A CLI tool for building frontend applications following the **02-rBOR** architecture pattern. Generate domain-driven feature modules with proper layering, enforce architectural rules, and analyze dependency graphs β with SVG visualization out of the box.
|
|
10
|
+
|
|
11
|
+
## π€ What is rBOR?
|
|
12
|
+
|
|
13
|
+
rBOR is an opinionated folder architecture for React apps. Instead of organizing by file type (`components/`, `hooks/`, `services/` at the root), rBOR organizes by **domain** β each feature gets its own self-contained folder with every layer it needs.
|
|
14
|
+
|
|
15
|
+
The idea: a `user` feature shouldn't scatter its files across 6 different top-level folders. Everything related to `user` lives under `domains/user/`, with a single barrel export (`index.tsx`) as the public API.
|
|
16
|
+
|
|
17
|
+
Each domain follows a strict **downward dependency rule** inspired by the [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle):
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
βββββββββββββββββββββββββββββββ
|
|
21
|
+
β Page (route) β composes components
|
|
22
|
+
ββββββββββββββββ¬βββββββββββββββ
|
|
23
|
+
βΌ
|
|
24
|
+
βββββββββββββββββββββββββββββββ
|
|
25
|
+
β Component (UI) β renders data from hooks
|
|
26
|
+
ββββββββββββββββ¬βββββββββββββββ
|
|
27
|
+
βΌ
|
|
28
|
+
βββββββββββββββββββββββββββββββ
|
|
29
|
+
β Hook β data / action β React Query fetching & mutations
|
|
30
|
+
ββββββββββββββββ¬βββββββββββββββ
|
|
31
|
+
βΌ
|
|
32
|
+
βββββββββββββββββββββββββββββββ
|
|
33
|
+
β Hook β controller β creates service, wires methods
|
|
34
|
+
ββββββββββββββββ¬βββββββββββββββ
|
|
35
|
+
βΌ
|
|
36
|
+
βββββββββββββββββββββββββββββββ
|
|
37
|
+
β Method (pure logic) β receives service as 1st param
|
|
38
|
+
ββββββββββββββββ¬βββββββββββββββ
|
|
39
|
+
βΌ
|
|
40
|
+
βββββββββββββββββββββββββββββββ
|
|
41
|
+
β Service (HTTP layer) β extends BaseService
|
|
42
|
+
ββββββββββββββββ¬βββββββββββββββ
|
|
43
|
+
βΌ
|
|
44
|
+
βββββββββββββββββββββββββββββββ
|
|
45
|
+
β Infrastructure (shared) β BaseService, ServiceFactory
|
|
46
|
+
βββββββββββββββββββββββββββββββ
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Control flows upward** β each layer orchestrates the layer below it.
|
|
50
|
+
**Dependencies flow downward** β lower layers are completely independent of what consumes them.
|
|
51
|
+
|
|
52
|
+
This means:
|
|
53
|
+
|
|
54
|
+
- `Infrastructure` (BaseService, ServiceFactory) knows nothing about any domain.
|
|
55
|
+
- `Service` extends BaseService β depends only on infrastructure.
|
|
56
|
+
- `Method` receives a service object as its first argument β depends only on services.
|
|
57
|
+
- `Hook (controller)` creates the service via ServiceFactory, passes it to methods β depends on methods & infrastructure.
|
|
58
|
+
- `Hook (data/action)` consumes the controller hook for fetching or mutations β depends on the controller.
|
|
59
|
+
- `Component` renders data from hooks β depends only on hooks.
|
|
60
|
+
- `Page` composes components β depends only on components.
|
|
61
|
+
|
|
62
|
+
Lower layers never import from higher layers. This keeps your business logic testable, your services reusable, and your UI replaceable.
|
|
63
|
+
|
|
64
|
+
## π¦ Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm install -g 02-rbor
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
rbor init
|
|
72
|
+
rbor domain <domain-name>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> **Tip:** If you prefer not to install globally, use `npx` β it works without any install:
|
|
76
|
+
>
|
|
77
|
+
> ```bash
|
|
78
|
+
> npx 02-rbor init
|
|
79
|
+
> npx 02-rbor domain <domain-name>
|
|
80
|
+
> ```
|
|
81
|
+
>
|
|
82
|
+
> All commands work with `npx 02-rbor <command>`, for example:
|
|
83
|
+
>
|
|
84
|
+
> ```bash
|
|
85
|
+
> npx 02-rbor domain user
|
|
86
|
+
> npx 02-rbor validate
|
|
87
|
+
> npx 02-rbor deps domains/user -f svg
|
|
88
|
+
> ```
|
|
89
|
+
|
|
90
|
+
## π Quick Start
|
|
91
|
+
|
|
92
|
+
### 1. Initialize your project
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
rbor init
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This creates a `.rborrc.json` configuration file with your project defaults.
|
|
99
|
+
|
|
100
|
+
### 2. Generate your first domain
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Interactive mode β prompts for name and HTTP client
|
|
104
|
+
rbor domain
|
|
105
|
+
|
|
106
|
+
# Or pass the name directly
|
|
107
|
+
rbor domain user --http axios
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This generates a complete domain structure:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
domains/user/
|
|
114
|
+
βββ index.tsx # Barrel export (public API)
|
|
115
|
+
βββ __test__/ # Test directory
|
|
116
|
+
βββ components/
|
|
117
|
+
β βββ User.tsx # Main component
|
|
118
|
+
βββ hooks/
|
|
119
|
+
β βββ useUser.ts # Controller hook (creates service, wires methods)
|
|
120
|
+
β βββ useUserData.ts # Data hook (React Query)
|
|
121
|
+
β βββ useUserAction.ts # Action hook (mutations)
|
|
122
|
+
βββ methods/
|
|
123
|
+
β βββ user-logic.ts # Pure async functions (React-independent)
|
|
124
|
+
βββ schema/
|
|
125
|
+
β βββ user-schema.ts # Validation schema (zod)
|
|
126
|
+
βββ services/
|
|
127
|
+
β βββ user-service.ts # Domain service (HTTP layer)
|
|
128
|
+
βββ types/
|
|
129
|
+
β βββ user-types.ts # TypeScript types
|
|
130
|
+
βββ utils/
|
|
131
|
+
βββ constant/
|
|
132
|
+
β βββ user-constants.ts
|
|
133
|
+
β βββ user-endpoints.ts
|
|
134
|
+
βββ helper/
|
|
135
|
+
βββ user-helpers.ts
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### What each folder does
|
|
139
|
+
|
|
140
|
+
| Folder | Purpose | Rules |
|
|
141
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
142
|
+
| **`components/`** | React UI. Renders data, handles user interaction. | Can import from `hooks/`. Nothing else in the domain. |
|
|
143
|
+
| **`hooks/`** | Wiring layer. Connects React to your domain logic. | `useUser` creates the service object and passes it to methods. `useUserData` and `useUserAction` provide React Query scaffolds for fetching and mutations. |
|
|
144
|
+
| **`methods/`** | Pure business logic. Every function receives the service as its first argument β no React, no hooks, no global state. | Can import from `services/` and `utils/`. Must stay framework-free so it's easy to test and reuse. |
|
|
145
|
+
| **`services/`** | HTTP layer. Extends `BaseService` to get an axios (or fetch/ky) instance. Exposes typed `get`, `post`, `put`, `delete` methods with URL param substitution. | Can import from `infrastructure/` and `utils/`. |
|
|
146
|
+
| **`schema/`** | Validation schemas (zod by default). Define the shape of your domain data for form validation, API response parsing, etc. | Pure data definitions β no side effects. |
|
|
147
|
+
| **`types/`** | TypeScript interfaces and types for this domain. | Pure type definitions. |
|
|
148
|
+
| **`utils/constant/`** | Endpoint paths and domain-specific constants (timeouts, config values, feature flags). | Pure values β no logic. |
|
|
149
|
+
| **`utils/helper/`** | Domain-specific utility functions (formatters, transformers, parsers). | Pure functions β no React, no service calls. |
|
|
150
|
+
| **`__test__/`** | Tests for this domain. | Mirrors the folder structure above. |
|
|
151
|
+
| **`index.tsx`** | Barrel export β the **only** file other parts of your app should import from. | Re-exports the component and anything else that's part of the public API. |
|
|
152
|
+
|
|
153
|
+
#### How data flows
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
ββββββββββββββββββββββββββββββββ
|
|
157
|
+
β Component (User.tsx) β UI β renders data
|
|
158
|
+
ββββββββββββββββ¬ββββββββββββββββ
|
|
159
|
+
β uses hooks
|
|
160
|
+
βΌ
|
|
161
|
+
ββββββββββββββββββββββββββββββββ
|
|
162
|
+
β useUserData / useUserAction β React Query β fetching & mutations
|
|
163
|
+
ββββββββββββββββ¬ββββββββββββββββ
|
|
164
|
+
β consumes controller
|
|
165
|
+
βΌ
|
|
166
|
+
ββββββββββββββββββββββββββββββββ
|
|
167
|
+
β useUser (controller hook) β creates service, wires methods
|
|
168
|
+
β β ServiceFactory.create('USER')
|
|
169
|
+
βββββββββ¬βββββββββββββββ¬ββββββββ
|
|
170
|
+
β β
|
|
171
|
+
βΌ βΌ
|
|
172
|
+
ββββββββββββββββ ββββββββββββββββββββββ
|
|
173
|
+
β user-logic β β ServiceFactory β
|
|
174
|
+
β (methods) β β (infrastructure) β
|
|
175
|
+
ββββββββ¬ββββββββ ββββββββββββββββββββββ
|
|
176
|
+
β calls service
|
|
177
|
+
βΌ
|
|
178
|
+
ββββββββββββββββββββββββββββββββ
|
|
179
|
+
β UserService β extends BaseService
|
|
180
|
+
β self-registers with Factory β
|
|
181
|
+
ββββββββββββββββ¬ββββββββββββββββ
|
|
182
|
+
β
|
|
183
|
+
βΌ
|
|
184
|
+
ββββββββββββββββββββββββββββββββ
|
|
185
|
+
β BaseService β axios instance, interceptors,
|
|
186
|
+
β (infrastructure) β base URL, timeout
|
|
187
|
+
ββββββββββββββββββββββββββββββββ
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Dependency Inversion in practice:**
|
|
191
|
+
|
|
192
|
+
- Lower layers are **stable abstractions** β they define contracts (BaseService, ServiceFactory registry) that don't change when features change.
|
|
193
|
+
- Higher layers are **volatile details** β UI, state management, and wiring change frequently.
|
|
194
|
+
- Each layer only depends on the layer directly below it, never sideways or upward.
|
|
195
|
+
- ServiceFactory never imports domain services β each service self-registers via `ServiceFactory.register()` at the bottom of its file. The controller hook triggers registration by importing the service file.
|
|
196
|
+
- `hook-data` and `hook-action` are **independent siblings** β both depend on the controller hook, but never on each other.
|
|
197
|
+
|
|
198
|
+
### 3. Add endpoints and constants
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
cd domains/user
|
|
202
|
+
rbor endpoint users/:id/profile # β USERS_ID_PROFILE
|
|
203
|
+
rbor constant timeout=3000 # β TIMEOUT = 3000
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 4. Analyze dependencies
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Who imports this file?
|
|
210
|
+
rbor deps domains/user/components/User.tsx -d reverse -f svg -o deps.svg
|
|
211
|
+
|
|
212
|
+
# What does this file import?
|
|
213
|
+
rbor deps src/app/App.tsx -d forward -f tree
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 5. Validate architecture
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
rbor validate
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## π Commands
|
|
225
|
+
|
|
226
|
+
| Command | Description |
|
|
227
|
+
| --------------------------- | ------------------------------------------------ |
|
|
228
|
+
| `rbor init` | Initialize `.rborrc.json` configuration |
|
|
229
|
+
| `rbor domain [name]` | Generate a domain (interactive if no name given) |
|
|
230
|
+
| `rbor endpoint <path>` | Add an endpoint to the current domain |
|
|
231
|
+
| `rbor constant <key=value>` | Add a constant to the current domain |
|
|
232
|
+
| `rbor list` | List all domains with metadata |
|
|
233
|
+
| `rbor validate` | Validate architecture rules |
|
|
234
|
+
| `rbor deps <path>` | Analyze dependency graph |
|
|
235
|
+
| `rbor davinci` | Credits |
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### `rbor init`
|
|
240
|
+
|
|
241
|
+
Initialize rBOR configuration in your project.
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
rbor init [options]
|
|
245
|
+
|
|
246
|
+
Options:
|
|
247
|
+
--http <client> HTTP client (axios, fetch, ky)
|
|
248
|
+
--domains-path <path> Path to domains folder
|
|
249
|
+
--infrastructure-path <path> Path to infrastructure folder
|
|
250
|
+
--force Overwrite existing config
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Creates `.rborrc.json`:
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"http": "axios",
|
|
258
|
+
"domainsPath": "domains",
|
|
259
|
+
"infrastructurePath": "infrastructure",
|
|
260
|
+
"schema": { "library": "zod" }
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
### `rbor domain [name]`
|
|
267
|
+
|
|
268
|
+
Generate a new domain with the full 02-rBOR structure.
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Interactive mode (prompts for name, HTTP client, confirmation)
|
|
272
|
+
rbor domain
|
|
273
|
+
|
|
274
|
+
# Direct mode
|
|
275
|
+
rbor domain auth
|
|
276
|
+
rbor domain products --http ky
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**What it generates:**
|
|
280
|
+
|
|
281
|
+
- β
Component with TypeScript + JSX
|
|
282
|
+
- β
Three-hook pattern (controller, data, action)
|
|
283
|
+
- β
Pure domain logic (methods receive service, stay React-free)
|
|
284
|
+
- β
Service layer with HTTP client integration
|
|
285
|
+
- β
Validation schemas (zod)
|
|
286
|
+
- β
Type definitions
|
|
287
|
+
- β
Constants and endpoint files
|
|
288
|
+
- β
Barrel export (index.tsx)
|
|
289
|
+
|
|
290
|
+
**Hook pattern:**
|
|
291
|
+
|
|
292
|
+
Three hooks are generated per domain:
|
|
293
|
+
|
|
294
|
+
- **`use<Domain>`** β Controller hook. Creates a service object and wires up all methods:
|
|
295
|
+
- **`use<Domain>Data`** β Data hook. Fetches server state using React Query (commented scaffold).
|
|
296
|
+
- **`use<Domain>Action`** β Action hook. Mutation actions via React Query (commented scaffold).
|
|
297
|
+
|
|
298
|
+
The controller hook wires up services and methods:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
export const useUser = () => {
|
|
302
|
+
const service = ServiceFactory.create('USER') as UserService;
|
|
303
|
+
|
|
304
|
+
return {
|
|
305
|
+
getList: () => getUserList(service),
|
|
306
|
+
getById: (id: string) => getUserById(service, id),
|
|
307
|
+
create: (data: unknown) => createUser(service, data),
|
|
308
|
+
update: (id: string, data: unknown) => updateUser(service, id, data),
|
|
309
|
+
remove: (id: string) => deleteUser(service, id),
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
> **Note:** If you need access to the Redux store or other global state, access it in the hook and pass values down to your methods. Methods should remain pure async functions.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### `rbor endpoint <path>`
|
|
319
|
+
|
|
320
|
+
Add an API endpoint constant to an existing domain. Run from inside `domains/<domain>/`.
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
rbor endpoint users/:id/profile
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Generates ALL_CAPS keys and appends to `utils/constant/<domain>-endpoints.ts`:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
export const AUTH_ENDPOINTS = {
|
|
330
|
+
LOGIN: '/login',
|
|
331
|
+
USERS_ID_PROFILE: '/users/:id/profile',
|
|
332
|
+
} as const;
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
### `rbor constant <key=value>`
|
|
338
|
+
|
|
339
|
+
Add a constant to the current domain's constants file. Run from inside `domains/<domain>/`.
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
rbor constant timeout=3000 # β export const TIMEOUT = 3000;
|
|
343
|
+
rbor constant maxRetries=5 # β export const MAX_RETRIES = 5;
|
|
344
|
+
rbor constant api-url=https://x # β export const API_URL = 'https://x';
|
|
345
|
+
rbor constant debug=true # β export const DEBUG = true;
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Auto-detects value types β numbers and booleans stay unquoted, strings get wrapped in quotes.
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
### `rbor list`
|
|
353
|
+
|
|
354
|
+
List all domains with metadata.
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
rbor list # or: rbor ls
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### `rbor validate`
|
|
363
|
+
|
|
364
|
+
Enforce 02-rBOR architectural rules.
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
rbor validate # or: rbor lint
|
|
368
|
+
rbor validate --strict # treat warnings as errors
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**What it checks:**
|
|
372
|
+
|
|
373
|
+
- β **No cross-domain imports** β Domains must not import from each other
|
|
374
|
+
- β **Downward-only dependencies** β Page β Component β Hook (data/action) β Hook (controller) β Method β Service β Infrastructure
|
|
375
|
+
- β **Sibling isolation** β `hook-data` and `hook-action` must be independent (no importing each other)
|
|
376
|
+
- β **No React in methods layer** β Pure logic must be framework-free
|
|
377
|
+
- β οΈ **Barrel exports** β Every domain should have an index.tsx
|
|
378
|
+
- β οΈ **Circular dependencies** β Warns about import cycles
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
### `rbor deps <path>`
|
|
383
|
+
|
|
384
|
+
Analyze dependency graphs for any file or directory. Traces imports forward (what does this file use?) or reverse (who imports this file?) and renders the result in five different formats β from quick terminal summaries to full SVG diagrams you can open in a browser.
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
rbor deps <path> [options]
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### Flags
|
|
391
|
+
|
|
392
|
+
| Flag | Short | Description | Default |
|
|
393
|
+
| --------------------- | ----- | ------------------------------------------------------ | ------------------------------- |
|
|
394
|
+
| `--direction <dir>` | `-d` | `forward` (imports) or `reverse` (importers) | `forward` |
|
|
395
|
+
| `--format <fmt>` | `-f` | Output format: `summary`, `tree`, `json`, `dot`, `svg` | `summary` |
|
|
396
|
+
| `--output <file>` | `-o` | Write output to a file instead of stdout | _(stdout)_ |
|
|
397
|
+
| `--depth <n>` | | Maximum traversal depth | `10` |
|
|
398
|
+
| `--include-external` | | Include external npm packages in the graph | `false` |
|
|
399
|
+
| `--include-tests` | | Include test files (`*.test.*`, `*.spec.*`) | `false` |
|
|
400
|
+
| `--include-types` | | Include type-only imports (`import type { ... }`) | `true` |
|
|
401
|
+
| `--aliases <mapping>` | | Path aliases, e.g. `"@/=src/,@utils/=src/utils/"` | _(auto-detected from tsconfig)_ |
|
|
402
|
+
|
|
403
|
+
> **Alias auto-detection:** If your project has a `tsconfig.json` with `compilerOptions.paths`, aliases are read automatically. Use `--aliases` to add extras or override.
|
|
404
|
+
|
|
405
|
+
#### Direction
|
|
406
|
+
|
|
407
|
+
**`--direction forward`** (default) β "What does this file import?"
|
|
408
|
+
|
|
409
|
+
```
|
|
410
|
+
ββββββββββββ
|
|
411
|
+
β App.tsx β
|
|
412
|
+
β (entry) β
|
|
413
|
+
ββββββ¬ββββββ
|
|
414
|
+
β
|
|
415
|
+
βββββββββββΌβββββββββββ
|
|
416
|
+
βΌ βΌ βΌ
|
|
417
|
+
router.ts store.ts utils.ts
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**`--direction reverse`** β "Who imports this file?"
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
Layout.tsx Main.tsx test.tsx
|
|
424
|
+
β β β
|
|
425
|
+
βββββββββββΌβββββββββββ
|
|
426
|
+
βΌ
|
|
427
|
+
ββββββββββββ
|
|
428
|
+
β App.tsx β
|
|
429
|
+
β (target) β
|
|
430
|
+
ββββββββββββ
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Use `forward` to understand what a file depends on. Use `reverse` to see a file's consumers β useful for gauging blast radius before a refactor.
|
|
434
|
+
|
|
435
|
+
#### Output Formats
|
|
436
|
+
|
|
437
|
+
**`summary`** (default) β Grouped table view in the terminal. Shows imports and importers categorized by file type, plus stats.
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
441
|
+
FILE SUMMARY: useUser.ts
|
|
442
|
+
Path: domains/user/hooks/useUser.ts
|
|
443
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
444
|
+
|
|
445
|
+
π₯ IMPORTS (what this file depends on)
|
|
446
|
+
π¨ method user-logic.ts
|
|
447
|
+
ποΈ infrastructure ServiceFactory.ts
|
|
448
|
+
π type user-types.ts
|
|
449
|
+
|
|
450
|
+
π€ IMPORTED BY (what depends on this file)
|
|
451
|
+
π hook-data useUserData.ts
|
|
452
|
+
β‘ hook-action useUserAction.ts
|
|
453
|
+
|
|
454
|
+
π STATS
|
|
455
|
+
Nodes: 5 β Edges: 4 β Circular: 0
|
|
456
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**`tree`** β ASCII tree in the terminal. Respects `--depth` to control how deep the traversal goes.
|
|
460
|
+
|
|
461
|
+
```
|
|
462
|
+
π¦ domains/user/hooks/useUser.ts
|
|
463
|
+
βββ π¨ domains/user/methods/user-logic.ts
|
|
464
|
+
β βββ βοΈ domains/user/services/user-service.ts
|
|
465
|
+
β βββ ποΈ infrastructure/BaseService.ts
|
|
466
|
+
βββ ποΈ infrastructure/ServiceFactory.ts
|
|
467
|
+
βββ π domains/user/types/user-types.ts
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**`json`** β Full structured output. Contains `nodes`, `edges`, `metadata`, and `stats`. Pipe to `jq` or consume in scripts.
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
rbor deps domains/user -f json | jq '.stats'
|
|
474
|
+
rbor deps domains/user -f json -o deps.json
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
```json
|
|
478
|
+
{
|
|
479
|
+
"nodes": [
|
|
480
|
+
{ "id": "domains/user/hooks/useUser.ts", "type": "internal", "category": "hook-controller" }
|
|
481
|
+
],
|
|
482
|
+
"edges": [
|
|
483
|
+
{
|
|
484
|
+
"source": "domains/user/hooks/useUser.ts",
|
|
485
|
+
"target": "domains/user/methods/user-logic.ts",
|
|
486
|
+
"importType": "static"
|
|
487
|
+
}
|
|
488
|
+
],
|
|
489
|
+
"metadata": { "direction": "forward", "circularDependencies": [] },
|
|
490
|
+
"stats": { "nodeCount": 5, "edgeCount": 4 }
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**`dot`** β [Graphviz DOT](https://graphviz.org/) format. Use if you have Graphviz installed locally or want to paste into an online viewer.
|
|
495
|
+
|
|
496
|
+
```bash
|
|
497
|
+
rbor deps domains/user -f dot -o deps.dot
|
|
498
|
+
dot -Tpng deps.dot -o deps.png # render with Graphviz
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**`svg`** β Renders the DOT graph to an SVG image using `@viz-js/viz` (bundled, no external install needed). This is the richest format β color-coded nodes, labeled edges, and circular dependency highlighting.
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
rbor deps domains/user -f svg -o deps.svg
|
|
505
|
+
# Open deps.svg in your browser or VS Code
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
SVG/DOT node colors:
|
|
509
|
+
|
|
510
|
+
```
|
|
511
|
+
ββββββββββββββββββββββββββββββ
|
|
512
|
+
β π£ Entry point (purple) β
|
|
513
|
+
β π΅ Internal file (blue) β
|
|
514
|
+
β π’ External package (green)β
|
|
515
|
+
β π‘ Dynamic import (amber) β
|
|
516
|
+
β βͺ Built-in module (grey) β
|
|
517
|
+
ββββββββββββββββββββββββββββββ
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
#### Circular Dependency Detection
|
|
521
|
+
|
|
522
|
+
All formats detect and report circular imports. In SVG/DOT output they're visually highlighted:
|
|
523
|
+
|
|
524
|
+
```
|
|
525
|
+
Normal edge: Circular edge:
|
|
526
|
+
|
|
527
|
+
ββββββββββ ββββββββββ
|
|
528
|
+
β A.ts β β A.ts β (red border)
|
|
529
|
+
βββββ¬βββββ βββββ¬βββββ
|
|
530
|
+
β β
|
|
531
|
+
βΌ βΌ β circular (red edge)
|
|
532
|
+
ββββββββββ ββββββββββ
|
|
533
|
+
β B.ts β β B.ts β (red border)
|
|
534
|
+
ββββββββββ ββββββββββ
|
|
535
|
+
|
|
536
|
+
π΄ Red borders β nodes involved in a cycle
|
|
537
|
+
π΄ Red edges β the circular import itself, labeled "β circular"
|
|
538
|
+
π Legend box β appears in the bottom-left with the cycle count
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
The `summary` and `tree` formats print `(circular)` inline when a cycle is encountered.
|
|
542
|
+
|
|
543
|
+
#### Recipes
|
|
544
|
+
|
|
545
|
+
```bash
|
|
546
|
+
# Quick overview of a domain's internal structure
|
|
547
|
+
rbor deps domains/auth -f tree --depth 3
|
|
548
|
+
|
|
549
|
+
# Full SVG graph saved to file
|
|
550
|
+
rbor deps domains/auth -f svg -o auth-deps.svg
|
|
551
|
+
|
|
552
|
+
# Reverse lookup: who depends on this service?
|
|
553
|
+
rbor deps domains/auth/services/auth-service.ts -d reverse -f tree
|
|
554
|
+
|
|
555
|
+
# Include npm packages in the graph
|
|
556
|
+
rbor deps src/App.tsx -f svg --include-external -o full-deps.svg
|
|
557
|
+
|
|
558
|
+
# Shallow analysis (immediate imports only)
|
|
559
|
+
rbor deps domains/auth/hooks/useAuth.ts -f summary --depth 1
|
|
560
|
+
|
|
561
|
+
# JSON for scripting / CI pipelines
|
|
562
|
+
rbor deps domains/auth -f json -o deps.json
|
|
563
|
+
|
|
564
|
+
# Custom aliases (on top of tsconfig auto-detection)
|
|
565
|
+
rbor deps src/App.tsx --aliases "@shared/=src/shared/,@lib/=lib/"
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
---
|
|
569
|
+
|
|
570
|
+
## βοΈ Configuration
|
|
571
|
+
|
|
572
|
+
### `.rborrc.json`
|
|
573
|
+
|
|
574
|
+
```json
|
|
575
|
+
{
|
|
576
|
+
"http": "axios",
|
|
577
|
+
"domainsPath": "domains",
|
|
578
|
+
"infrastructurePath": "infrastructure",
|
|
579
|
+
"schema": { "library": "zod" }
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
| Option | Description | Values |
|
|
584
|
+
| -------------------- | ------------------------- | ---------------------- |
|
|
585
|
+
| `http` | Default HTTP client | `axios`, `fetch`, `ky` |
|
|
586
|
+
| `domainsPath` | Where to generate domains | Any path |
|
|
587
|
+
| `infrastructurePath` | Shared infrastructure dir | Any path |
|
|
588
|
+
| `schema.library` | Validation library | `zod`, `yup`, `none` |
|
|
589
|
+
|
|
590
|
+
CLI flags always override config values.
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## ποΈ Architecture Philosophy
|
|
595
|
+
|
|
596
|
+
**02-rBOR** is built on the **Dependency Inversion Principle** β higher layers control the flow, lower layers remain independent abstractions.
|
|
597
|
+
|
|
598
|
+
### The Layer Model
|
|
599
|
+
|
|
600
|
+
```
|
|
601
|
+
Layer 0 β type, schema, constant, config, util β importable by anyone (pure data)
|
|
602
|
+
Layer 1 β infrastructure (BaseService, Factory) β independent, no domain knowledge
|
|
603
|
+
Layer 2 β service (extends BaseService) β depends only on infrastructure
|
|
604
|
+
Layer 3 β method (pure async functions) β depends on service, no React
|
|
605
|
+
Layer 4 β hook-controller (useUser) β wires service + methods
|
|
606
|
+
Layer 5 β hook-data / hook-action β consumes controller, independent siblings
|
|
607
|
+
Layer 6 β component (User.tsx) β renders from hooks
|
|
608
|
+
Layer 7 β page (route) β composes components
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
Each layer can import from the **same layer or below**, never above. `hook-data` and `hook-action` are at the same level but must stay independent β both consume the controller, neither consumes the other.
|
|
612
|
+
|
|
613
|
+
### Why this works
|
|
614
|
+
|
|
615
|
+
1. **Feature Containerization** β Each domain is self-contained with a single barrel export. The rest of the app imports `from 'domains/user'`, never `from 'domains/user/services/user-service'`.
|
|
616
|
+
2. **Downward Dependencies** β Complexity flows down: Page β Component β Hook β Method β Service β Infrastructure. Upper layers orchestrate lower layers, never the reverse.
|
|
617
|
+
3. **Layer Separation** β React stays in the component and hook layers. Methods are pure async functions that receive a service object and return data. You can unit test them without rendering anything.
|
|
618
|
+
4. **No Cross-Domain Imports** β `domains/auth` must never import from `domains/user`. Shared logic goes in `infrastructure/`.
|
|
619
|
+
5. **Service as a Parameter** β Methods don't create their own HTTP clients. They receive the service object from the hook, making them easy to mock and test.
|
|
620
|
+
6. **Sibling Isolation** β `useUserData` (fetching) and `useUserAction` (mutations) are independent. They both depend on `useUser` (the controller), but never on each other. This prevents tangled state flows between reads and writes.
|
|
621
|
+
|
|
622
|
+
### Infrastructure (shared across all domains)
|
|
623
|
+
|
|
624
|
+
```
|
|
625
|
+
infrastructure/
|
|
626
|
+
βββ BaseService.ts # Abstract class β creates axios instance, interceptors, base CRUD methods
|
|
627
|
+
βββ ServiceFactory.ts # Registry-based factory β services self-register, factory never imports domain code
|
|
628
|
+
βββ generateURL.ts # URL builder β replaces :params and appends ?query strings
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
- **BaseService** β Every domain service extends this. It creates an axios instance with configured `baseURL`, `timeout`, and request/response interceptors. Exposes `protected` `get`, `post`, `put`, `delete` methods that all domain services inherit.
|
|
632
|
+
- **ServiceFactory** β A registry-based factory. Each domain service calls `ServiceFactory.register('KEY', () => new DomainService())` at the bottom of its own file. The factory never imports domain code β it just stores creators and instantiates on demand via `ServiceFactory.create('KEY')`. This keeps infrastructure fully independent (Dependency Inversion).
|
|
633
|
+
- **generateURL** β Utility for URL parameter substitution (`/users/:id` β `/users/42`) and query string building.
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
## π§ͺ Testing
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
npm test # Run all tests
|
|
641
|
+
npm run test:watch # Watch mode
|
|
642
|
+
npm run test:coverage # Coverage report
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
---
|
|
646
|
+
|
|
647
|
+
## π‘ Examples
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
# Full domain setup
|
|
651
|
+
rbor domain auth --http axios
|
|
652
|
+
cd domains/auth
|
|
653
|
+
rbor endpoint auth/login
|
|
654
|
+
rbor endpoint auth/logout
|
|
655
|
+
rbor endpoint auth/refresh
|
|
656
|
+
rbor constant session-timeout=1800000
|
|
657
|
+
|
|
658
|
+
# Generate more domains
|
|
659
|
+
rbor domain user
|
|
660
|
+
rbor domain products --http ky
|
|
661
|
+
|
|
662
|
+
# Analyze and validate
|
|
663
|
+
rbor validate --strict
|
|
664
|
+
rbor deps domains/auth -d forward -f svg -o auth-deps.svg
|
|
665
|
+
rbor list
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
## π License
|
|
671
|
+
|
|
672
|
+
MIT Β© [02-davinci-01](https://github.com/02-davinci-01)
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
**rendered to reality by [02-davinci-01](https://02-davinci-01.vercel.app)**
|