@rse/specbook 1.3.1 → 1.4.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 +5 -2
- package/dst/specbook-api.js +7 -5
- package/dst/specbook-cli.js +0 -0
- package/dst/specbook-cmd-export.js +2 -2
- package/dst/specbook-coverage.js +1 -1
- package/dst/specbook-diagram.d.ts +1 -1
- package/dst/specbook-diagram.js +9 -3
- package/dst/specbook-export-ast.d.ts +1 -1
- package/dst/specbook-export-ast.js +21 -4
- package/dst/specbook-export-code.d.ts +14 -0
- package/dst/specbook-export-code.js +155 -0
- package/dst/specbook-export-common.d.ts +4 -2
- package/dst/specbook-export-common.js +110 -6
- package/dst/specbook-export-diagram.d.ts +15 -0
- package/dst/specbook-export-diagram.js +211 -0
- package/dst/specbook-export-html-fold.d.ts +20 -0
- package/dst/specbook-export-html-fold.js +458 -0
- package/dst/specbook-export-html-render.d.ts +51 -0
- package/dst/specbook-export-html-render.js +749 -0
- package/dst/specbook-export-html-search.js +6 -5
- package/dst/specbook-export-html-template.d.ts +21 -0
- package/dst/specbook-export-html-template.js +282 -0
- package/dst/specbook-export-html-widget.d.ts +12 -0
- package/dst/specbook-export-html-widget.js +605 -0
- package/dst/specbook-export-html.css +325 -50
- package/dst/specbook-export-html.js +62 -1931
- package/dst/specbook-export-image.d.ts +2 -0
- package/dst/specbook-export-image.js +161 -9
- package/dst/specbook-export-md.js +60 -12
- package/dst/specbook-format-schema.d.ts +1 -1
- package/dst/specbook-format-schema.js +1 -1
- package/dst/specbook-format-spec.d.ts +1 -0
- package/dst/specbook-format-spec.js +1 -0
- package/dst/specbook-format.md +169 -17
- package/dst/specbook-format.yaml +224 -23
- package/dst/specbook-ignore.js +2 -0
- package/dst/specbook-link.js +21 -5
- package/dst/specbook-parse-common.d.ts +24 -0
- package/dst/specbook-parse-common.js +137 -10
- package/dst/specbook-parse-semantic.js +2 -0
- package/dst/specbook-parse-syntax.js +81 -20
- package/dst/specbook-parse.js +1 -1
- package/dst/specbook-theme.d.ts +1 -0
- package/dst/specbook-theme.js +2 -0
- package/package.json +17 -11
package/dst/specbook-format.yaml
CHANGED
|
@@ -267,6 +267,7 @@
|
|
|
267
267
|
states a fact or event, not a decision (a deliberate exclusion is the `SCOPE` of
|
|
268
268
|
the Solution Vision or a `WONT` requirement instead).
|
|
269
269
|
format:
|
|
270
|
+
type: compact
|
|
270
271
|
maxTableColumns: 5
|
|
271
272
|
props:
|
|
272
273
|
- name: TYPE
|
|
@@ -341,6 +342,7 @@
|
|
|
341
342
|
term from its siblings (e.g. `A Message submitted by an Attendee as ...`), so that
|
|
342
343
|
the hierarchy and the definitions cross-check each other.
|
|
343
344
|
format:
|
|
345
|
+
type: compact
|
|
344
346
|
maxTableColumns: 5
|
|
345
347
|
referenced:
|
|
346
348
|
- "[[*]]"
|
|
@@ -352,8 +354,9 @@
|
|
|
352
354
|
labeled: true
|
|
353
355
|
qualified: true
|
|
354
356
|
config:
|
|
355
|
-
size-node-width-max:
|
|
357
|
+
size-node-width-max: 440
|
|
356
358
|
size-node-height-scale: 1.75
|
|
359
|
+
hub-node-count-max: 3
|
|
357
360
|
props:
|
|
358
361
|
- name: TYPE
|
|
359
362
|
desc: >
|
|
@@ -661,6 +664,17 @@
|
|
|
661
664
|
maxTableColumns: 6
|
|
662
665
|
referenced:
|
|
663
666
|
- "[[USE-CASE:*]]"
|
|
667
|
+
diagram:
|
|
668
|
+
type: hub
|
|
669
|
+
center: self
|
|
670
|
+
nodes: "[[FR.REQUIREMENT:*]], [[NR.REQUIREMENT:*]], [[PREMISE:*]], [[RULE:*]],
|
|
671
|
+
[[USE-CASE:*]], [[DM.ENTITY:*]], [[FV.COMPONENT:*]], [[TEST-CASE:*]]"
|
|
672
|
+
labeled: true
|
|
673
|
+
qualified: true
|
|
674
|
+
config:
|
|
675
|
+
size-node-width-max: 440
|
|
676
|
+
size-node-height-scale: 1.75
|
|
677
|
+
hub-node-count-max: 3
|
|
664
678
|
props:
|
|
665
679
|
- name: PRIORITY
|
|
666
680
|
desc: >
|
|
@@ -734,6 +748,7 @@
|
|
|
734
748
|
config:
|
|
735
749
|
size-node-width-max: 440
|
|
736
750
|
size-node-height-scale: 1.75
|
|
751
|
+
hub-node-count-max: 3
|
|
737
752
|
props:
|
|
738
753
|
- name: PRIORITY
|
|
739
754
|
desc: >
|
|
@@ -827,6 +842,18 @@
|
|
|
827
842
|
maxTableColumns: 5
|
|
828
843
|
referenced:
|
|
829
844
|
- "[[TEST-CASE:*]]"
|
|
845
|
+
diagram:
|
|
846
|
+
type: hub
|
|
847
|
+
center: self
|
|
848
|
+
nodes: "[[RULE:*]], [[TERM:*]], [[FR.REQUIREMENT:*]], [[NR.REQUIREMENT:*]],
|
|
849
|
+
[[PREMISE:*]], [[WORKFLOW:*]], [[HANDOFF:*]], [[USE-CASE:*]], [[TRANSITION:*]],
|
|
850
|
+
[[PERMISSION:*]], [[TEST-CASE:*]]"
|
|
851
|
+
labeled: true
|
|
852
|
+
qualified: true
|
|
853
|
+
config:
|
|
854
|
+
size-node-width-max: 440
|
|
855
|
+
size-node-height-scale: 1.75
|
|
856
|
+
hub-node-count-max: 3
|
|
830
857
|
props:
|
|
831
858
|
- name: CATEGORY
|
|
832
859
|
desc: >
|
|
@@ -1599,7 +1626,19 @@
|
|
|
1599
1626
|
roles against entities. Any operation, state, or condition not covered by a
|
|
1600
1627
|
permission of the role (or of a role it `INHERITS`) is forbidden.
|
|
1601
1628
|
format:
|
|
1629
|
+
type: compact
|
|
1602
1630
|
maxTableColumns: 8
|
|
1631
|
+
diagram:
|
|
1632
|
+
type: hub
|
|
1633
|
+
center: self
|
|
1634
|
+
nodes: "[[PERMISSION:*]], [[ROLE:*]], [[DM.ENTITY:*]], [[STATE:*]], [[TRANSITION:*]],
|
|
1635
|
+
[[RULE:*]], [[USE-CASE:*]], [[SCENARIO:*]], [[ENDPOINT:*]], [[TEST-CASE:*]]"
|
|
1636
|
+
labeled: true
|
|
1637
|
+
qualified: true
|
|
1638
|
+
config:
|
|
1639
|
+
size-node-width-max: 440
|
|
1640
|
+
size-node-height-scale: 1.75
|
|
1641
|
+
hub-node-count-max: 3
|
|
1603
1642
|
props:
|
|
1604
1643
|
- name: ROLE
|
|
1605
1644
|
desc: >
|
|
@@ -2188,12 +2227,14 @@
|
|
|
2188
2227
|
it rejects is its `TRADE-OFF`), and is not verifiable by a metric (a measurable
|
|
2189
2228
|
quality bound is a Non-Functional Requirement instead).
|
|
2190
2229
|
referenced:
|
|
2191
|
-
- "[[PATTERN:*]]"
|
|
2230
|
+
- "[[DIALOG-PATTERN:*]]"
|
|
2231
|
+
format:
|
|
2232
|
+
type: compact
|
|
2192
2233
|
diagram:
|
|
2193
2234
|
type: hub
|
|
2194
2235
|
center: self
|
|
2195
2236
|
nodes: "[[PRINCIPLE:*]], [[PERSONA:*]], [[STEP:*]], [[USE-CASE:*]], [[CONVENTION:*]],
|
|
2196
|
-
[[PATTERN:*]], [[ELEMENT:*]], [[DECISION:*]]"
|
|
2237
|
+
[[DIALOG-PATTERN:*]], [[ELEMENT:*]], [[DECISION:*]]"
|
|
2197
2238
|
labeled: true
|
|
2198
2239
|
qualified: true
|
|
2199
2240
|
config:
|
|
@@ -2284,6 +2325,18 @@
|
|
|
2284
2325
|
solution phrases what it says, not what it does (a behavior is an Interaction
|
|
2285
2326
|
Concept principle instead) and not what a term means (a definition is a Domain
|
|
2286
2327
|
Glossary term instead).
|
|
2328
|
+
format:
|
|
2329
|
+
type: compact
|
|
2330
|
+
diagram:
|
|
2331
|
+
type: hub
|
|
2332
|
+
center: self
|
|
2333
|
+
nodes: "[[CONVENTION:*]], [[PERSONA:*]], [[PRINCIPLE:*]], [[TERM:*]], [[DECISION:*]]"
|
|
2334
|
+
labeled: true
|
|
2335
|
+
qualified: true
|
|
2336
|
+
config:
|
|
2337
|
+
size-node-width-max: 440
|
|
2338
|
+
size-node-height-scale: 1.75
|
|
2339
|
+
hub-node-count-max: 3
|
|
2287
2340
|
props:
|
|
2288
2341
|
- name: CATEGORY
|
|
2289
2342
|
desc: >
|
|
@@ -2338,7 +2391,7 @@
|
|
|
2338
2391
|
optional: true
|
|
2339
2392
|
diagram:
|
|
2340
2393
|
type: grid
|
|
2341
|
-
nodes: "[[PATTERN:*]]"
|
|
2394
|
+
nodes: "[[DIALOG-PATTERN:*]]"
|
|
2342
2395
|
properties:
|
|
2343
2396
|
- CATEGORY
|
|
2344
2397
|
config:
|
|
@@ -2346,7 +2399,7 @@
|
|
|
2346
2399
|
size-node-height-scale: 2
|
|
2347
2400
|
grid-columns-max: 4
|
|
2348
2401
|
children:
|
|
2349
|
-
- kind: PATTERN
|
|
2402
|
+
- kind: DIALOG-PATTERN
|
|
2350
2403
|
desc: >
|
|
2351
2404
|
A single reusable dialog pattern, named with a short (2-5 word) summary (e.g.
|
|
2352
2405
|
`Master-Detail`, `Wizard`, `Inline Edit`) and described in a concise (1-3 sentence)
|
|
@@ -2360,7 +2413,7 @@
|
|
|
2360
2413
|
diagram:
|
|
2361
2414
|
type: hub
|
|
2362
2415
|
center: self
|
|
2363
|
-
nodes: "[[PATTERN:*]], [[PRINCIPLE:*]], [[STORYBOARD:*]], [[DECISION:*]]"
|
|
2416
|
+
nodes: "[[DIALOG-PATTERN:*]], [[PRINCIPLE:*]], [[STORYBOARD:*]], [[DECISION:*]]"
|
|
2364
2417
|
deep: true
|
|
2365
2418
|
labeled: true
|
|
2366
2419
|
qualified: true
|
|
@@ -2405,7 +2458,7 @@
|
|
|
2405
2458
|
pattern is composed of (e.g. a `Master-Detail` using an `Inline Edit` in
|
|
2406
2459
|
its detail), so that the patterns form a language of related structures
|
|
2407
2460
|
rather than a flat catalogue.
|
|
2408
|
-
value: list([[PATTERN:*]])
|
|
2461
|
+
value: list([[DIALOG-PATTERN:*]])
|
|
2409
2462
|
optional: true
|
|
2410
2463
|
- name: TRADE-OFF
|
|
2411
2464
|
desc: >
|
|
@@ -2450,7 +2503,7 @@
|
|
|
2450
2503
|
diagram:
|
|
2451
2504
|
type: hub
|
|
2452
2505
|
center: self
|
|
2453
|
-
nodes: "[[STORYBOARD:*]], [[PERSONA:*]], [[SCENARIO:*]], [[PATTERN:*]], [[MOCKUP:*]]"
|
|
2506
|
+
nodes: "[[STORYBOARD:*]], [[PERSONA:*]], [[SCENARIO:*]], [[DIALOG-PATTERN:*]], [[MOCKUP:*]]"
|
|
2454
2507
|
deep: true
|
|
2455
2508
|
labeled: true
|
|
2456
2509
|
qualified: true
|
|
@@ -2502,7 +2555,7 @@
|
|
|
2502
2555
|
Comma-separated references to the DIALOG-PATTERNS objects the frame
|
|
2503
2556
|
instantiates, so that a pattern is shown to recur across the
|
|
2504
2557
|
concrete flows rather than merely being catalogued.
|
|
2505
|
-
value: list([[PATTERN:*]])
|
|
2558
|
+
value: list([[DIALOG-PATTERN:*]])
|
|
2506
2559
|
optional: true
|
|
2507
2560
|
- name: SKETCH
|
|
2508
2561
|
desc: >
|
|
@@ -2559,6 +2612,7 @@
|
|
|
2559
2612
|
list of token values (the values are in the design system) or a measurable bound
|
|
2560
2613
|
(a bound is a Non-Functional Requirement instead).
|
|
2561
2614
|
format:
|
|
2615
|
+
type: compact
|
|
2562
2616
|
maxTableColumns: 5
|
|
2563
2617
|
diagram:
|
|
2564
2618
|
type: hub
|
|
@@ -2568,6 +2622,7 @@
|
|
|
2568
2622
|
qualified: true
|
|
2569
2623
|
config:
|
|
2570
2624
|
size-node-width-max: 440
|
|
2625
|
+
hub-node-count-max: 3
|
|
2571
2626
|
props:
|
|
2572
2627
|
- name: CATEGORY
|
|
2573
2628
|
desc: >
|
|
@@ -2617,6 +2672,15 @@
|
|
|
2617
2672
|
applied rather than stating them (a rule is an `ELEMENT` instead).
|
|
2618
2673
|
format:
|
|
2619
2674
|
type: complex
|
|
2675
|
+
diagram:
|
|
2676
|
+
type: hub
|
|
2677
|
+
center: self
|
|
2678
|
+
nodes: "[[MOCKUP:*]], [[PERSONA:*]], [[STORYBOARD:*]], [[ELEMENT:*]]"
|
|
2679
|
+
labeled: true
|
|
2680
|
+
qualified: true
|
|
2681
|
+
config:
|
|
2682
|
+
size-node-width-max: 440
|
|
2683
|
+
hub-node-count-max: 3
|
|
2620
2684
|
props:
|
|
2621
2685
|
- name: ACTORS
|
|
2622
2686
|
desc: >
|
|
@@ -2691,6 +2755,7 @@
|
|
|
2691
2755
|
Deployment View node instead -- only a party or system the solution merely consumes
|
|
2692
2756
|
or serves belongs to the system context.
|
|
2693
2757
|
format:
|
|
2758
|
+
type: compact
|
|
2694
2759
|
maxTableColumns: 5
|
|
2695
2760
|
props:
|
|
2696
2761
|
- name: KIND
|
|
@@ -2808,12 +2873,14 @@
|
|
|
2808
2873
|
with the components it depends on, plus a 1-sentence rationale ("why") for the
|
|
2809
2874
|
component's existence and boundary.
|
|
2810
2875
|
format:
|
|
2876
|
+
type: compact
|
|
2811
2877
|
maxTableColumns: 5
|
|
2812
2878
|
diagram:
|
|
2813
2879
|
type: hub
|
|
2814
2880
|
center: self
|
|
2815
2881
|
nodes: "[[FV.COMPONENT:*]], [[FR.REQUIREMENT:*]], [[INTERFACE:*]], [[DM.ENTITY:*]],
|
|
2816
|
-
[[UNIT:*]], [[NODE:*]], [[CONCERN:*]], [[TACTIC:*]], [[DECISION:*]]
|
|
2882
|
+
[[UNIT:*]], [[NODE:*]], [[CONCERN:*]], [[TACTIC:*]], [[DECISION:*]],
|
|
2883
|
+
[[CODE-PATTERN:*]]"
|
|
2817
2884
|
labeled: true
|
|
2818
2885
|
qualified: true
|
|
2819
2886
|
properties:
|
|
@@ -2821,6 +2888,7 @@
|
|
|
2821
2888
|
config:
|
|
2822
2889
|
size-node-width-max: 440
|
|
2823
2890
|
size-node-height-scale: 1.75
|
|
2891
|
+
hub-node-count-max: 3
|
|
2824
2892
|
props:
|
|
2825
2893
|
- name: KIND
|
|
2826
2894
|
desc: |
|
|
@@ -2950,11 +3018,13 @@
|
|
|
2950
3018
|
carrying trade-off behind the choice is a Design Decisions decision
|
|
2951
3019
|
referencing the component through `DECIDES`, and the functional components
|
|
2952
3020
|
depending on the product reference it through `USED-BY`.
|
|
3021
|
+
format:
|
|
3022
|
+
type: compact
|
|
2953
3023
|
diagram:
|
|
2954
3024
|
type: hub
|
|
2955
3025
|
center: self
|
|
2956
3026
|
nodes: "[[TS.TIER:*.COMPONENT:*]], [[FV.COMPONENT:*]], [[CONCERN:*]],
|
|
2957
|
-
[[TACTIC:*]], [[DECISION:*]]"
|
|
3027
|
+
[[TACTIC:*]], [[DECISION:*]], [[CODE-PATTERN:*]]"
|
|
2958
3028
|
labeled: true
|
|
2959
3029
|
qualified: true
|
|
2960
3030
|
properties:
|
|
@@ -2963,6 +3033,7 @@
|
|
|
2963
3033
|
config:
|
|
2964
3034
|
size-node-width-max: 440
|
|
2965
3035
|
size-node-height-scale: 1.75
|
|
3036
|
+
hub-node-count-max: 3
|
|
2966
3037
|
props:
|
|
2967
3038
|
- name: PRODUCT
|
|
2968
3039
|
desc: >
|
|
@@ -3276,9 +3347,11 @@
|
|
|
3276
3347
|
process: it names no concrete products (a Technology Stack `Build-Time` component
|
|
3277
3348
|
states the product choice), does not restate the runtime structure (a Functionality
|
|
3278
3349
|
View `Module` or `Subsystem` groups the logic), does not cover production
|
|
3279
|
-
procedures (an Operations View concern does),
|
|
3280
|
-
|
|
3281
|
-
|
|
3350
|
+
procedures (an Operations View concern does), does not prescribe how a concern is
|
|
3351
|
+
coded (a Code Patterns pattern shows that as a listing), and the trade-off that
|
|
3352
|
+
produced a rule is a Design Decisions decision referencing the aspect through
|
|
3353
|
+
`AFFECTS`, while the quality the rule protects (usually a `Maintainability`
|
|
3354
|
+
requirement) is
|
|
3282
3355
|
addressed by a Quality Perspectives tactic referencing the aspect through
|
|
3283
3356
|
`AFFECTS`, too, so the hub diagram of an aspect shows the decision and the tactic
|
|
3284
3357
|
behind it.
|
|
@@ -3353,6 +3426,7 @@
|
|
|
3353
3426
|
config:
|
|
3354
3427
|
size-node-width-max: 440
|
|
3355
3428
|
size-node-height-scale: 1.75
|
|
3429
|
+
hub-node-count-max: 3
|
|
3356
3430
|
props:
|
|
3357
3431
|
- name: KIND
|
|
3358
3432
|
desc: |
|
|
@@ -3455,6 +3529,7 @@
|
|
|
3455
3529
|
config:
|
|
3456
3530
|
size-node-width-max: 440
|
|
3457
3531
|
size-node-height-scale: 1.75
|
|
3532
|
+
hub-node-count-max: 3
|
|
3458
3533
|
props:
|
|
3459
3534
|
- name: PART-OF
|
|
3460
3535
|
desc: >
|
|
@@ -3534,6 +3609,7 @@
|
|
|
3534
3609
|
config:
|
|
3535
3610
|
size-node-width-max: 440
|
|
3536
3611
|
size-node-height-scale: 1.75
|
|
3612
|
+
hub-node-count-max: 3
|
|
3537
3613
|
props:
|
|
3538
3614
|
- name: KIND
|
|
3539
3615
|
desc: |
|
|
@@ -3629,6 +3705,7 @@
|
|
|
3629
3705
|
config:
|
|
3630
3706
|
size-node-width-max: 440
|
|
3631
3707
|
size-node-height-scale: 1.75
|
|
3708
|
+
hub-node-count-max: 3
|
|
3632
3709
|
props:
|
|
3633
3710
|
- name: SCOPE
|
|
3634
3711
|
desc: |
|
|
@@ -3700,6 +3777,7 @@
|
|
|
3700
3777
|
config:
|
|
3701
3778
|
size-node-width-max: 440
|
|
3702
3779
|
size-node-height-scale: 1.75
|
|
3780
|
+
hub-node-count-max: 3
|
|
3703
3781
|
props:
|
|
3704
3782
|
- name: CATEGORY
|
|
3705
3783
|
desc: |
|
|
@@ -3801,16 +3879,20 @@
|
|
|
3801
3879
|
Design Decisions decision referencing the tactic through `DECIDES`, the product
|
|
3802
3880
|
realizing the mechanism is a Technology Stack component referenced through
|
|
3803
3881
|
`TOOLS`, the developer-facing rule about the source structure is an aspect of the
|
|
3804
|
-
Development Aspects,
|
|
3882
|
+
Development Aspects, the coded form of the mechanism is a Code Patterns pattern
|
|
3883
|
+
referencing the tactic through `REALIZES`, and a mechanism driven solely by a
|
|
3884
|
+
`Constraint` requirement
|
|
3805
3885
|
(e.g. a hosting or budget mandate) protects no quality and is a Design Decisions
|
|
3806
3886
|
decision alone -- only the mechanism, the quality it achieves, and the elements it
|
|
3807
3887
|
shapes belong here.
|
|
3888
|
+
format:
|
|
3889
|
+
type: compact
|
|
3808
3890
|
diagram:
|
|
3809
3891
|
type: hub
|
|
3810
3892
|
center: self
|
|
3811
3893
|
nodes: "[[TACTIC:*]], [[NR.REQUIREMENT:*]], [[FV.COMPONENT:*]], [[UNIT:*]],
|
|
3812
3894
|
[[ASPECT:*]], [[NODE:*]], [[DM.ENTITY:*]], [[CONCERN:*]], [[DECISION:*]],
|
|
3813
|
-
[[TS.TIER:*.COMPONENT:*]], [[TEST-CASE:*]]"
|
|
3895
|
+
[[TS.TIER:*.COMPONENT:*]], [[CODE-PATTERN:*]], [[TEST-CASE:*]]"
|
|
3814
3896
|
labeled: true
|
|
3815
3897
|
qualified: true
|
|
3816
3898
|
properties:
|
|
@@ -3885,9 +3967,10 @@
|
|
|
3885
3967
|
file: 30-ARCH-DD-Design-Decisions.md
|
|
3886
3968
|
desc: >
|
|
3887
3969
|
The major decisions related to the solution design, each recording the forces at play, the
|
|
3888
|
-
chosen response, and the reasoning that justifies it. The artifact is the last
|
|
3889
|
-
architecture, as a decision references the requirements forcing
|
|
3890
|
-
shapes, and the tactics and products it chose, all of which precede
|
|
3970
|
+
chosen response, and the reasoning that justifies it. The artifact is the last
|
|
3971
|
+
decision-level one of the architecture, as a decision references the requirements forcing
|
|
3972
|
+
it, the elements it shapes, and the tactics and products it chose, all of which precede
|
|
3973
|
+
it, while the Code Patterns following it reference the decisions they implement.
|
|
3891
3974
|
optional: true
|
|
3892
3975
|
refs: >
|
|
3893
3976
|
- Nygard: Documenting Architecture Decisions (2011),
|
|
@@ -3963,15 +4046,17 @@
|
|
|
3963
4046
|
decision is under-justified. The rationale should make the decision feel earned,
|
|
3964
4047
|
not asserted - if you delete the rationale and the decision suddenly looks
|
|
3965
4048
|
arbitrary, the rationale was doing its job.
|
|
4049
|
+
format:
|
|
4050
|
+
type: complex
|
|
3966
4051
|
diagram:
|
|
3967
4052
|
type: hub
|
|
3968
4053
|
center: self
|
|
3969
4054
|
nodes: "[[DECISION:*]], [[NR.REQUIREMENT:*]], [[PREMISE:*]], [[DM.ENTITY:*]],
|
|
3970
4055
|
[[LIFECYCLE:*]], [[ROLE:*]], [[INTERFACE:*]], [[TYPE:*]], [[ENDPOINT:*]],
|
|
3971
|
-
[[PRINCIPLE:*]], [[CONVENTION:*]], [[PATTERN:*]], [[STORYBOARD:*]],
|
|
4056
|
+
[[PRINCIPLE:*]], [[CONVENTION:*]], [[DIALOG-PATTERN:*]], [[STORYBOARD:*]],
|
|
3972
4057
|
[[ELEMENT:*]], [[CV.ENTITY:*]], [[FV.COMPONENT:*]], [[UNIT:*]], [[ASPECT:*]],
|
|
3973
4058
|
[[DV.TIER:*]], [[AREA:*]], [[NODE:*]], [[NETWORK:*]], [[TACTIC:*]],
|
|
3974
|
-
[[TS.TIER:*.COMPONENT:*]]"
|
|
4059
|
+
[[TS.TIER:*.COMPONENT:*]], [[CODE-PATTERN:*]]"
|
|
3975
4060
|
labeled: true
|
|
3976
4061
|
qualified: true
|
|
3977
4062
|
properties:
|
|
@@ -4019,7 +4104,7 @@
|
|
|
4019
4104
|
integrated); omitted for a decision shaping no modeled element.
|
|
4020
4105
|
value: list([[DM.ENTITY:*]], [[LIFECYCLE:*]], [[ROLE:*]], [[INTERFACE:*]],
|
|
4021
4106
|
[[TYPE:*]], [[ENDPOINT:*]], [[PRINCIPLE:*]], [[CONVENTION:*]],
|
|
4022
|
-
[[PATTERN:*]], [[STORYBOARD:*]], [[ELEMENT:*]], [[CV.ENTITY:*]],
|
|
4107
|
+
[[DIALOG-PATTERN:*]], [[STORYBOARD:*]], [[ELEMENT:*]], [[CV.ENTITY:*]],
|
|
4023
4108
|
[[FV.COMPONENT:*]], [[UNIT:*]], [[ASPECT:*]], [[DV.TIER:*]], [[AREA:*]],
|
|
4024
4109
|
[[NODE:*]], [[NETWORK:*]])
|
|
4025
4110
|
optional: true
|
|
@@ -4115,10 +4200,123 @@
|
|
|
4115
4200
|
matrix of considered alternatives); and
|
|
4116
4201
|
- links to strongly related decisions.
|
|
4117
4202
|
optional: true
|
|
4203
|
+
|
|
4204
|
+
- kind: ARCH
|
|
4205
|
+
name: Code Patterns
|
|
4206
|
+
id: CP
|
|
4207
|
+
file: 31-ARCH-CP-Code-Patterns.md
|
|
4208
|
+
desc: >
|
|
4209
|
+
The implementation patterns the source code of the solution follows, each prescribing how
|
|
4210
|
+
one recurring concern (e.g. authorization enforcement, entity persistence, error
|
|
4211
|
+
propagation) is coded and showing it as a code listing. The artifact follows the Design
|
|
4212
|
+
Decisions, as a pattern is the coded form of the tactics and decisions preceding it, and
|
|
4213
|
+
is absent when the coding conventions are governed outside the specification (e.g. by
|
|
4214
|
+
repository-level contributor instructions).
|
|
4215
|
+
optional: true
|
|
4216
|
+
refs: >
|
|
4217
|
+
- Starke/Hruschka: arc42 Template: Crosscutting Concepts (2005),
|
|
4218
|
+
https://arc42.org/overview
|
|
4219
|
+
- Fowler: Patterns of Enterprise Application Architecture (2002),
|
|
4220
|
+
https://martinfowler.com/books/eaa.html
|
|
4221
|
+
- Beck: Implementation Patterns (2007),
|
|
4222
|
+
https://www.informit.com/store/implementation-patterns-9780321413093
|
|
4223
|
+
diagram:
|
|
4224
|
+
type: grid
|
|
4225
|
+
nodes: "[[CODE-PATTERN:*]]"
|
|
4226
|
+
config:
|
|
4227
|
+
size-node-width-max: 440
|
|
4228
|
+
grid-columns-max: 4
|
|
4229
|
+
children:
|
|
4230
|
+
- kind: CODE-PATTERN
|
|
4231
|
+
desc: >
|
|
4232
|
+
A single code pattern, named with a short (2-5 word) summary of the concern it
|
|
4233
|
+
codes (e.g. `Endpoint Authorization`, `Entity Persistence`, `Error Propagation`)
|
|
4234
|
+
and described in a concise (1-3 sentence) paragraph by the rule the code follows
|
|
4235
|
+
whenever the concern arises, plus a 1-sentence rationale ("why") for the rule.
|
|
4236
|
+
|
|
4237
|
+
The listing showing the pattern follows the description and its rationale as the
|
|
4238
|
+
elaboration of the pattern: either a fenced code block in the language of the
|
|
4239
|
+
pattern (e.g. ` ```ts start=10 mark=3-5 `, the parameters numbering the lines
|
|
4240
|
+
from `start` and marking the essential ones) or an embedded excerpt of an existing
|
|
4241
|
+
source file (e.g. ``,
|
|
4242
|
+
the fragment selecting and marking the lines), the latter preferred once the code
|
|
4243
|
+
exists, as the specification then never drifts from it. The listing is the
|
|
4244
|
+
canonical, idealized form of the pattern, not an exhaustive example, so it is kept
|
|
4245
|
+
short (typically 10-30 lines) and the prose names what the listing cannot: the
|
|
4246
|
+
places the pattern applies and the deviation it rules out (`AVOID`).
|
|
4247
|
+
|
|
4248
|
+
A pattern states how a concern is coded, and nothing else: the quality mechanism
|
|
4249
|
+
it implements is a Quality Perspectives tactic referenced through `REALIZES`, the
|
|
4250
|
+
trade-off that chose its approach over alternatives is a Design Decisions decision
|
|
4251
|
+
referenced through `DECIDED-BY` (a pattern weighs no alternatives itself), the
|
|
4252
|
+
product it codes against is a Technology Stack component referenced through
|
|
4253
|
+
`TOOLS`, and the rule about the source layout, build, or process it lives in is a
|
|
4254
|
+
Development Aspects aspect -- only the recurring code shape, the elements written
|
|
4255
|
+
that way, and the deviation ruled out belong here.
|
|
4256
|
+
format:
|
|
4257
|
+
type: complex
|
|
4258
|
+
diagram:
|
|
4259
|
+
type: hub
|
|
4260
|
+
center: self
|
|
4261
|
+
nodes: "[[CODE-PATTERN:*]], [[FV.COMPONENT:*]], [[UNIT:*]], [[DM.ENTITY:*]],
|
|
4262
|
+
[[ROLE:*]], [[INTERFACE:*]], [[ENDPOINT:*]], [[TS.TIER:*.COMPONENT:*]],
|
|
4263
|
+
[[TACTIC:*]], [[DECISION:*]]"
|
|
4264
|
+
labeled: true
|
|
4265
|
+
qualified: true
|
|
4266
|
+
config:
|
|
4267
|
+
size-node-width-max: 440
|
|
4268
|
+
props:
|
|
4269
|
+
- name: APPLIES-TO
|
|
4270
|
+
desc: >
|
|
4271
|
+
Comma-separated references to the FUNCTIONALITY-VIEW, CONCURRENCY-VIEW,
|
|
4272
|
+
DATA-MODEL, AUTHORIZATION-MODEL, INTERFACE-MODEL, or INTERFACE-ENDPOINTS
|
|
4273
|
+
objects whose code follows the pattern (e.g. the components persisting
|
|
4274
|
+
their entities this way, the roles and endpoints guarded by the check);
|
|
4275
|
+
omitted for a pattern applied throughout the code base.
|
|
4276
|
+
value: list([[FV.COMPONENT:*]], [[UNIT:*]], [[DM.ENTITY:*]], [[ROLE:*]],
|
|
4277
|
+
[[INTERFACE:*]], [[ENDPOINT:*]])
|
|
4278
|
+
optional: true
|
|
4279
|
+
- name: REALIZES
|
|
4280
|
+
desc: >
|
|
4281
|
+
Comma-separated references to the QUALITY-PERSPECTIVES tactics the pattern
|
|
4282
|
+
is the coded form of (e.g. the token check implementing the access
|
|
4283
|
+
security tactic); omitted for a pattern serving no modeled tactic.
|
|
4284
|
+
value: list([[TACTIC:*]])
|
|
4285
|
+
optional: true
|
|
4286
|
+
- name: DECIDED-BY
|
|
4287
|
+
desc: >
|
|
4288
|
+
Comma-separated references to the DESIGN-DECISIONS objects the pattern
|
|
4289
|
+
implements (e.g. the query builder usage following the decision against an
|
|
4290
|
+
ORM); omitted for a pattern behind which no recorded decision stands.
|
|
4291
|
+
value: list([[DECISION:*]])
|
|
4292
|
+
optional: true
|
|
4293
|
+
- name: TOOLS
|
|
4294
|
+
desc: >
|
|
4295
|
+
Comma-separated references to the TECHNOLOGY-STACK components the pattern
|
|
4296
|
+
codes against (e.g. the query builder, the logging library); omitted for a
|
|
4297
|
+
pattern using the language alone.
|
|
4298
|
+
value: list([[TS.TIER:*.COMPONENT:*]])
|
|
4299
|
+
optional: true
|
|
4300
|
+
- name: USES
|
|
4301
|
+
desc: >
|
|
4302
|
+
Comma-separated references to the smaller CODE-PATTERNS objects the pattern
|
|
4303
|
+
is composed of (e.g. an `Endpoint Authorization` using the `Error
|
|
4304
|
+
Propagation` for its rejections), so that the patterns form a language of
|
|
4305
|
+
related shapes rather than a flat catalogue.
|
|
4306
|
+
value: list([[CODE-PATTERN:*]])
|
|
4307
|
+
optional: true
|
|
4308
|
+
acyclic: true
|
|
4309
|
+
- name: AVOID
|
|
4310
|
+
desc: >
|
|
4311
|
+
The deviation the pattern rules out, stated as the concrete shape a
|
|
4312
|
+
developer would otherwise reach for (e.g. `SQL strings assembled in the
|
|
4313
|
+
request handlers`, `role checks in the client alone`); omitted when the
|
|
4314
|
+
rule has no tempting alternative.
|
|
4315
|
+
optional: true
|
|
4118
4316
|
- kind: TEST
|
|
4119
4317
|
name: Test Cases
|
|
4120
4318
|
id: TC
|
|
4121
|
-
file:
|
|
4319
|
+
file: 32-TEST-TC-Test-Cases.md
|
|
4122
4320
|
desc: >
|
|
4123
4321
|
The verifiable conditions and steps used to confirm that requirements, domain rules, use
|
|
4124
4322
|
case scenarios, state transitions, and the mechanisms, procedures, and decisions of the
|
|
@@ -4182,6 +4380,8 @@
|
|
|
4182
4380
|
concurrency unit when its collaboration or contention is exercised, an aspect of
|
|
4183
4381
|
the Development Aspects or a Design Decisions decision when its rule is checked by
|
|
4184
4382
|
an architectural fitness function (e.g. no dependency edge against the layering).
|
|
4383
|
+
format:
|
|
4384
|
+
type: compact
|
|
4185
4385
|
diagram:
|
|
4186
4386
|
type: hub
|
|
4187
4387
|
center: self
|
|
@@ -4195,6 +4395,7 @@
|
|
|
4195
4395
|
config:
|
|
4196
4396
|
size-node-width-max: 440
|
|
4197
4397
|
size-node-height-scale: 1.75
|
|
4398
|
+
hub-node-count-max: 3
|
|
4198
4399
|
props:
|
|
4199
4400
|
- name: VERIFIES
|
|
4200
4401
|
desc: >
|
package/dst/specbook-ignore.js
CHANGED
|
@@ -41,6 +41,8 @@ const compileRule = (line, base, nocase) => {
|
|
|
41
41
|
const anchored = pattern.includes("/");
|
|
42
42
|
if (pattern.startsWith("/"))
|
|
43
43
|
pattern = pattern.slice(1);
|
|
44
|
+
if (pattern === "")
|
|
45
|
+
return null;
|
|
44
46
|
/* a negated character class is "[!...]" in the wildmatch of Git,
|
|
45
47
|
while picomatch knows the "[^...]" spelling only */
|
|
46
48
|
pattern = pattern.replace(/\[!/g, "[^");
|
package/dst/specbook-link.js
CHANGED
|
@@ -5,9 +5,24 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/* the Wiki-style reference syntax ("[[xxx]]") */
|
|
7
7
|
export const referenceRegex = /\[\[([^[\]]+)\]\]/g;
|
|
8
|
-
/*
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
/* the fenced code blocks of a Markdown text (from the opening fence line
|
|
9
|
+
up to the closing fence line, or to the end of an unclosed one) */
|
|
10
|
+
const fenceRegex = /^[ \t]*(`{3,}|~{3,})[^\n]*(?:\n[\s\S]*?(?:\n[ \t]*\1[`~]*[ \t]*(?=\n|$)|(?![\s\S]))|(?![\s\S]))/gm;
|
|
11
|
+
/* apply a transformation to the parts of a text outside of its fenced
|
|
12
|
+
code blocks, which stay verbatim, as code carries no references */
|
|
13
|
+
const outsideFences = (text, apply) => {
|
|
14
|
+
let result = "";
|
|
15
|
+
let last = 0;
|
|
16
|
+
for (const m of text.matchAll(fenceRegex)) {
|
|
17
|
+
result += apply(text.slice(last, m.index)) + m[0];
|
|
18
|
+
last = m.index + m[0].length;
|
|
19
|
+
}
|
|
20
|
+
return result + apply(text.slice(last));
|
|
21
|
+
};
|
|
22
|
+
/* strip the fenced code blocks of a description and the inline code
|
|
23
|
+
markup of a name, property value, or description (preserved in the
|
|
24
|
+
AST for rendering) for matching and labeling */
|
|
25
|
+
export const plainText = (text) => text.replace(fenceRegex, "").replace(/`/g, "");
|
|
11
26
|
/* provide the lookup structures of an index, built once on first use */
|
|
12
27
|
const lookups = new WeakMap();
|
|
13
28
|
const lookup = (index) => {
|
|
@@ -184,5 +199,6 @@ export const anchorPaths = (index) => {
|
|
|
184
199
|
}
|
|
185
200
|
return paths;
|
|
186
201
|
};
|
|
187
|
-
/* expand all references of a text via a per-reference replacer
|
|
188
|
-
|
|
202
|
+
/* expand all references of a text via a per-reference replacer
|
|
203
|
+
(except inside its fenced code blocks) */
|
|
204
|
+
export const expandReferences = (text, replace) => outsideFences(text, (part) => part.replace(referenceRegex, (_, reference) => replace(reference.trim())));
|
|
@@ -31,6 +31,30 @@ export declare const becauseRegex: RegExp;
|
|
|
31
31
|
export declare const embeddingRegex: RegExp;
|
|
32
32
|
export declare const embeddingThemes: readonly ["light", "dark"];
|
|
33
33
|
export declare const embeddingVariants: (reference: string) => string[];
|
|
34
|
+
export declare const pdfType = "application/pdf";
|
|
35
|
+
export declare const codeType = "text/x-code";
|
|
36
|
+
export declare const codeLanguage: (name: string) => string | undefined;
|
|
37
|
+
export declare const markedLines: (mark: string) => {
|
|
38
|
+
has: (line: number) => boolean;
|
|
39
|
+
};
|
|
40
|
+
type FenceInfo = {
|
|
41
|
+
lang: string;
|
|
42
|
+
params: Record<string, string>;
|
|
43
|
+
error?: string;
|
|
44
|
+
};
|
|
45
|
+
export declare const fenceInfo: (info: string | undefined) => FenceInfo;
|
|
46
|
+
export declare const embeddingFragment: (reference: string, type: string) => {
|
|
47
|
+
file: string;
|
|
48
|
+
params: Record<string, string>;
|
|
49
|
+
} | undefined;
|
|
50
|
+
export declare const embeddingFileType: (reference: string) => string | undefined;
|
|
34
51
|
export declare const embeddingMimeType: (reference: string) => string | undefined;
|
|
35
52
|
export declare const embeddingCount: (reference: string | undefined) => number;
|
|
36
53
|
export declare const embeddingDataRegex: RegExp;
|
|
54
|
+
export type DarkMark = "invert" | "none";
|
|
55
|
+
export declare const darkMark: (content: string) => {
|
|
56
|
+
content: string;
|
|
57
|
+
dark?: DarkMark;
|
|
58
|
+
};
|
|
59
|
+
export declare const markDark: (content: string, dark: DarkMark) => string;
|
|
60
|
+
export {};
|