@conformetry/output 0.0.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/LICENSE +21 -0
- package/README.md +414 -0
- package/dist/src/index.d.ts +173 -0
- package/dist/src/index.js +185 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jimmy Paolini
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
# π Conformetry Output
|
|
2
|
+
|
|
3
|
+
Every render target [Conformetry](../conformetry-cli/README.md) has. It sits at
|
|
4
|
+
the output layer of the five-layer spine β `core <- configuration <- analysis
|
|
5
|
+
<- output <- cli` β so it reads what analysis produced and turns it into text,
|
|
6
|
+
and runs no analysis of its own.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install --save-dev @conformetry/output
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What it owns
|
|
13
|
+
|
|
14
|
+
| Module | Responsibility |
|
|
15
|
+
| ------ | -------------- |
|
|
16
|
+
| `reporting` | Renders structured conformance differences, and the per-instance score summary above them, as readable and actionable text |
|
|
17
|
+
| `inventory` | Renders the template and instance inventory: the indent ladder, the headings, and the match percentage |
|
|
18
|
+
|
|
19
|
+
Both are rendering, and both used to live in
|
|
20
|
+
[`@conformetry/core`](../conformetry-core/README.md) β which is why that package
|
|
21
|
+
could not be a contracts leaf. They are here so that "the host composes, the
|
|
22
|
+
output renders" is true of conformetry the way it is of its three siblings, and
|
|
23
|
+
so that adding a render format has exactly one home.
|
|
24
|
+
|
|
25
|
+
## Where a host gets them
|
|
26
|
+
|
|
27
|
+
`ReportingModule` and `InventoryModule` are named explicitly by whichever host
|
|
28
|
+
wants them. Neither is re-exported by `ValidationModule`: validation is an
|
|
29
|
+
analysis package and sits _beneath_ this one, so it cannot reach up to hand a
|
|
30
|
+
renderer on.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
@Module({ imports: [ReportingModule, ValidationModule] })
|
|
34
|
+
class EmbeddedConformetryModule {}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Paths
|
|
38
|
+
|
|
39
|
+
Paths arrive absolute, because that is the only stable way for discovery to
|
|
40
|
+
name an instance to another process. Shortening them against a working
|
|
41
|
+
directory is offered as a separate step rather than folded into rendering β
|
|
42
|
+
only a host knows which directory a person is standing in.
|
|
43
|
+
|
|
44
|
+
## Test
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
nx run conformetry-output:vitest
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
MIT β see [LICENSE](../../../../LICENSE).
|
|
53
|
+
|
|
54
|
+
## π Conformetry
|
|
55
|
+
|
|
56
|
+
This project was generated from the [nestjs-service-project](../../configuration/conformetry-templates/nestjs-service-project) conformetry template.
|
|
57
|
+
|
|
58
|
+
## πΈοΈ Codependix
|
|
59
|
+
|
|
60
|
+
Dependency graphs exported by [codependix](https://github.com/Organizzolini/codebase/tree/main/packages/ic-suite/codependix/codependix-cli), regenerated by `nx run codebase:codependix:write`.
|
|
61
|
+
|
|
62
|
+
### Nx Neighborhood
|
|
63
|
+
|
|
64
|
+
<!-- codependix:start name="codependix-nx-projects" -->
|
|
65
|
+
```mermaid
|
|
66
|
+
graph LR
|
|
67
|
+
conformetry_cli["conformetry-cli"]
|
|
68
|
+
conformetry_core["conformetry-core"]
|
|
69
|
+
conformetry_examples["conformetry-examples"]
|
|
70
|
+
conformetry_languages["conformetry-languages"]
|
|
71
|
+
conformetry_nx["conformetry-nx"]
|
|
72
|
+
conformetry_output["conformetry-output"]
|
|
73
|
+
conformetry_cli --> conformetry_output
|
|
74
|
+
conformetry_examples --> conformetry_output
|
|
75
|
+
conformetry_nx --> conformetry_output
|
|
76
|
+
conformetry_output --> conformetry_core
|
|
77
|
+
conformetry_output --> conformetry_languages
|
|
78
|
+
classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
|
|
79
|
+
class conformetry_output subject
|
|
80
|
+
```
|
|
81
|
+
<!-- codependix:end name="codependix-nx-projects" -->
|
|
82
|
+
|
|
83
|
+
### NestJS Module Graph
|
|
84
|
+
|
|
85
|
+
<!-- codependix:start name="codependix-nestjs-modules" -->
|
|
86
|
+
```mermaid
|
|
87
|
+
flowchart LR
|
|
88
|
+
InventoryModule
|
|
89
|
+
ReportingModule
|
|
90
|
+
ScoringModule
|
|
91
|
+
ReportingModule --> ScoringModule
|
|
92
|
+
```
|
|
93
|
+
<!-- codependix:end name="codependix-nestjs-modules" -->
|
|
94
|
+
|
|
95
|
+
### File Imports
|
|
96
|
+
|
|
97
|
+
<!-- codependix:start name="codependix-file-imports" -->
|
|
98
|
+
```mermaid
|
|
99
|
+
graph LR
|
|
100
|
+
file_callidescope_config_ts["callidescope.config.ts"]
|
|
101
|
+
file_codependix_config_ts["codependix.config.ts"]
|
|
102
|
+
file_codometer_config_ts["codometer.config.ts"]
|
|
103
|
+
file_eslint_config_ts["eslint.config.ts"]
|
|
104
|
+
file_src_index_ts["src/index.ts"]
|
|
105
|
+
file_src_modules_inventory_inventory_constants_ts["src/modules/inventory/inventory.constants.ts"]
|
|
106
|
+
file_src_modules_inventory_inventory_module_ts["src/modules/inventory/inventory.module.ts"]
|
|
107
|
+
file_src_modules_inventory_inventory_module_unit_test_ts["src/modules/inventory/inventory.module.unit.test.ts"]
|
|
108
|
+
file_src_modules_inventory_inventory_service_ts["src/modules/inventory/inventory.service.ts"]
|
|
109
|
+
file_src_modules_inventory_inventory_service_unit_test_ts["src/modules/inventory/inventory.service.unit.test.ts"]
|
|
110
|
+
file_src_modules_inventory_inventory_types_ts["src/modules/inventory/inventory.types.ts"]
|
|
111
|
+
file_src_modules_reporting_reporting_constants_ts["src/modules/reporting/reporting.constants.ts"]
|
|
112
|
+
file_src_modules_reporting_reporting_module_ts["src/modules/reporting/reporting.module.ts"]
|
|
113
|
+
file_src_modules_reporting_reporting_module_unit_test_ts["src/modules/reporting/reporting.module.unit.test.ts"]
|
|
114
|
+
file_src_modules_reporting_reporting_service_ts["src/modules/reporting/reporting.service.ts"]
|
|
115
|
+
file_src_modules_reporting_reporting_service_unit_test_ts["src/modules/reporting/reporting.service.unit.test.ts"]
|
|
116
|
+
file_src_modules_reporting_reporting_types_ts["src/modules/reporting/reporting.types.ts"]
|
|
117
|
+
file_testing_mocks_ts["testing/mocks.ts"]
|
|
118
|
+
file_testing_setup_ts["testing/setup.ts"]
|
|
119
|
+
file_vite_config_ts["vite.config.ts"]
|
|
120
|
+
file_vitest_config_ts["vitest.config.ts"]
|
|
121
|
+
file_src_modules_inventory_inventory_module_ts --> file_src_modules_inventory_inventory_service_ts
|
|
122
|
+
file_src_modules_inventory_inventory_module_unit_test_ts --> file_src_modules_inventory_inventory_module_ts
|
|
123
|
+
file_src_modules_inventory_inventory_module_unit_test_ts --> file_src_modules_inventory_inventory_service_ts
|
|
124
|
+
file_src_modules_inventory_inventory_service_ts --> file_src_modules_inventory_inventory_constants_ts
|
|
125
|
+
file_src_modules_inventory_inventory_service_unit_test_ts --> file_src_modules_inventory_inventory_service_ts
|
|
126
|
+
file_src_modules_reporting_reporting_module_ts --> file_src_modules_reporting_reporting_service_ts
|
|
127
|
+
file_src_modules_reporting_reporting_module_unit_test_ts --> file_src_modules_reporting_reporting_module_ts
|
|
128
|
+
file_src_modules_reporting_reporting_module_unit_test_ts --> file_src_modules_reporting_reporting_service_ts
|
|
129
|
+
file_src_modules_reporting_reporting_service_ts --> file_src_modules_reporting_reporting_constants_ts
|
|
130
|
+
file_src_modules_reporting_reporting_service_ts --> file_src_modules_reporting_reporting_types_ts
|
|
131
|
+
file_src_modules_reporting_reporting_service_unit_test_ts --> file_src_modules_reporting_reporting_service_ts
|
|
132
|
+
```
|
|
133
|
+
<!-- codependix:end name="codependix-file-imports" -->
|
|
134
|
+
|
|
135
|
+
<!-- callidescope:start -->
|
|
136
|
+
|
|
137
|
+
## π Callidescope
|
|
138
|
+
|
|
139
|
+
Call stacks traced through `packages/ic-suite/conformetry/conformetry-output`, deepest first. Each frame shows what it takes, what it returns, and what its documentation says.
|
|
140
|
+
|
|
141
|
+
| Measure | Value |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| Callables | 32 |
|
|
144
|
+
| Files | 15 |
|
|
145
|
+
| Calls traced | 34 |
|
|
146
|
+
| Call stacks | 0 |
|
|
147
|
+
| Deepest stack | 0 |
|
|
148
|
+
| Stacks through recursion | 0 |
|
|
149
|
+
| Unfollowable calls | 0 |
|
|
150
|
+
|
|
151
|
+
### Limits
|
|
152
|
+
|
|
153
|
+
What this project is judged against, as declared in its own `callidescope.config.ts`.
|
|
154
|
+
|
|
155
|
+
| Limit | Value |
|
|
156
|
+
| --- | --- |
|
|
157
|
+
| `maximumDepth` | 6 |
|
|
158
|
+
| `maximumBreadth` | 4 |
|
|
159
|
+
|
|
160
|
+
### Call stacks (depth)
|
|
161
|
+
|
|
162
|
+
None.
|
|
163
|
+
|
|
164
|
+
### Breadth
|
|
165
|
+
|
|
166
|
+
| Callable | Breadth | Calls directly | Location |
|
|
167
|
+
| --- | --- | --- | --- |
|
|
168
|
+
| `ReportingService.formatTotal` | 4 | `ReportingService.reduce(β¦)`, `ReportingService.reduce(β¦)`, `ReportingService.filter(β¦)`, `ReportingService.formatFraction` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:234` |
|
|
169
|
+
| `ReportingService.formatFileResult` | 3 | `ReportingService.formatFraction`, `ScoringService.sumWeights`, `ReportingService.flatMap(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:98` |
|
|
170
|
+
| `ReportingService.formatScores` | 3 | `ReportingService.filter(β¦)`, `ReportingService.map(β¦)`, `ReportingService.formatTotal` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:197` |
|
|
171
|
+
|
|
172
|
+
<details>
|
|
173
|
+
<summary>19 more callables</summary>
|
|
174
|
+
|
|
175
|
+
| Callable | Breadth | Calls directly | Location |
|
|
176
|
+
| --- | --- | --- | --- |
|
|
177
|
+
| `ReportingService.formatFraction` | 2 | `ScoringService.calculateScore`, `ReportingService.formatPercentage` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:131` |
|
|
178
|
+
| `ReportingService.formatScore` | 2 | `ReportingService.formatPercentage`, `ReportingService.formatFraction` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:166` |
|
|
179
|
+
| `ReportingService.formatReport` | 2 | `ReportingService.formatScores`, `ReportingService.flatMap(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:262` |
|
|
180
|
+
| `InventoryService.describePairing` | 1 | `InventoryService.formatRatio` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:48` |
|
|
181
|
+
| `InventoryService.describeInstances` | 1 | `InventoryService.flatMap(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:77` |
|
|
182
|
+
| `InventoryService.flatMap(β¦)` | 1 | `InventoryService.map(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:78` |
|
|
183
|
+
| `InventoryService.map(β¦)` | 1 | `InventoryService.describePairing` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:82` |
|
|
184
|
+
| `InventoryService.describeTemplates` | 1 | `InventoryService.flatMap(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:94` |
|
|
185
|
+
| `InventoryService.flatMap(β¦)` | 1 | `InventoryService.map(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:98` |
|
|
186
|
+
| `InventoryService.map(β¦)` | 1 | `InventoryService.describePairing` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:109` |
|
|
187
|
+
| `InventoryService.shortenInstancePaths` | 1 | `InventoryService.map(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:120` |
|
|
188
|
+
| `InventoryService.map(β¦)` | 1 | `InventoryService.shortenPath` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:124` |
|
|
189
|
+
| `InventoryService.shortenTemplatePairings` | 1 | `InventoryService.map(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:136` |
|
|
190
|
+
| `InventoryService.map(β¦)` | 1 | `InventoryService.map(β¦)` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:140` |
|
|
191
|
+
| `InventoryService.map(β¦)` | 1 | `InventoryService.shortenPath` | `packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts:143` |
|
|
192
|
+
| `ReportingService.formatError` | 1 | `ReportingService.formatLocation` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:54` |
|
|
193
|
+
| `ReportingService.flatMap(β¦)` | 1 | `ReportingService.formatError` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:115` |
|
|
194
|
+
| `ReportingService.map(β¦)` | 1 | `ReportingService.formatScore` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:211` |
|
|
195
|
+
| `ReportingService.flatMap(β¦)` | 1 | `ReportingService.formatFileResult` | `packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.service.ts:274` |
|
|
196
|
+
|
|
197
|
+
</details>
|
|
198
|
+
<!-- callidescope:end -->
|
|
199
|
+
|
|
200
|
+
<!-- codometer:start -->
|
|
201
|
+
|
|
202
|
+
## β²οΈ Codometer
|
|
203
|
+
|
|
204
|
+
### Project
|
|
205
|
+
|
|
206
|
+

|
|
207
|
+

|
|
208
|
+

|
|
209
|
+

|
|
210
|
+
|
|
211
|
+
### Measured Targets
|
|
212
|
+
|
|
213
|
+

|
|
214
|
+
|
|
215
|
+
### TypeScript
|
|
216
|
+
|
|
217
|
+

|
|
218
|
+

|
|
219
|
+

|
|
220
|
+

|
|
221
|
+

|
|
222
|
+

|
|
223
|
+

|
|
224
|
+
|
|
225
|
+
### JavaScript
|
|
226
|
+
|
|
227
|
+

|
|
228
|
+

|
|
229
|
+

|
|
230
|
+

|
|
231
|
+

|
|
232
|
+

|
|
233
|
+

|
|
234
|
+

|
|
235
|
+

|
|
236
|
+

|
|
237
|
+

|
|
238
|
+

|
|
239
|
+

|
|
240
|
+

|
|
241
|
+
|
|
242
|
+
### Python
|
|
243
|
+
|
|
244
|
+

|
|
245
|
+

|
|
246
|
+

|
|
247
|
+

|
|
248
|
+

|
|
249
|
+

|
|
250
|
+

|
|
251
|
+

|
|
252
|
+

|
|
253
|
+

|
|
254
|
+

|
|
255
|
+

|
|
256
|
+
|
|
257
|
+
### JSON
|
|
258
|
+
|
|
259
|
+

|
|
260
|
+

|
|
261
|
+

|
|
262
|
+

|
|
263
|
+

|
|
264
|
+

|
|
265
|
+

|
|
266
|
+

|
|
267
|
+

|
|
268
|
+

|
|
269
|
+

|
|
270
|
+

|
|
271
|
+
|
|
272
|
+
### YAML
|
|
273
|
+
|
|
274
|
+

|
|
275
|
+

|
|
276
|
+

|
|
277
|
+

|
|
278
|
+

|
|
279
|
+

|
|
280
|
+

|
|
281
|
+

|
|
282
|
+

|
|
283
|
+

|
|
284
|
+

|
|
285
|
+
|
|
286
|
+
### TOML
|
|
287
|
+
|
|
288
|
+

|
|
289
|
+

|
|
290
|
+

|
|
291
|
+

|
|
292
|
+

|
|
293
|
+

|
|
294
|
+

|
|
295
|
+
|
|
296
|
+
### Shell
|
|
297
|
+
|
|
298
|
+

|
|
299
|
+

|
|
300
|
+

|
|
301
|
+

|
|
302
|
+

|
|
303
|
+

|
|
304
|
+

|
|
305
|
+

|
|
306
|
+

|
|
307
|
+

|
|
308
|
+

|
|
309
|
+
|
|
310
|
+
### SQL
|
|
311
|
+
|
|
312
|
+

|
|
313
|
+

|
|
314
|
+

|
|
315
|
+

|
|
316
|
+

|
|
317
|
+

|
|
318
|
+

|
|
319
|
+

|
|
320
|
+

|
|
321
|
+

|
|
322
|
+

|
|
323
|
+
|
|
324
|
+
### HCL
|
|
325
|
+
|
|
326
|
+

|
|
327
|
+

|
|
328
|
+

|
|
329
|
+

|
|
330
|
+

|
|
331
|
+

|
|
332
|
+

|
|
333
|
+

|
|
334
|
+

|
|
335
|
+
|
|
336
|
+
### CSS
|
|
337
|
+
|
|
338
|
+

|
|
339
|
+

|
|
340
|
+

|
|
341
|
+

|
|
342
|
+

|
|
343
|
+

|
|
344
|
+

|
|
345
|
+

|
|
346
|
+

|
|
347
|
+
|
|
348
|
+
### Conventions
|
|
349
|
+
|
|
350
|
+

|
|
351
|
+

|
|
352
|
+

|
|
353
|
+

|
|
354
|
+

|
|
355
|
+

|
|
356
|
+

|
|
357
|
+

|
|
358
|
+

|
|
359
|
+

|
|
360
|
+

|
|
361
|
+

|
|
362
|
+

|
|
363
|
+

|
|
364
|
+

|
|
365
|
+

|
|
366
|
+

|
|
367
|
+

|
|
368
|
+
|
|
369
|
+
### Jupyter
|
|
370
|
+
|
|
371
|
+

|
|
372
|
+

|
|
373
|
+

|
|
374
|
+

|
|
375
|
+

|
|
376
|
+

|
|
377
|
+

|
|
378
|
+

|
|
379
|
+

|
|
380
|
+

|
|
381
|
+

|
|
382
|
+

|
|
383
|
+

|
|
384
|
+

|
|
385
|
+

|
|
386
|
+

|
|
387
|
+

|
|
388
|
+

|
|
389
|
+

|
|
390
|
+

|
|
391
|
+
|
|
392
|
+
### Markdown
|
|
393
|
+
|
|
394
|
+

|
|
395
|
+

|
|
396
|
+

|
|
397
|
+

|
|
398
|
+

|
|
399
|
+

|
|
400
|
+

|
|
401
|
+

|
|
402
|
+

|
|
403
|
+

|
|
404
|
+

|
|
405
|
+

|
|
406
|
+

|
|
407
|
+

|
|
408
|
+

|
|
409
|
+

|
|
410
|
+

|
|
411
|
+

|
|
412
|
+

|
|
413
|
+

|
|
414
|
+
<!-- codometer:end -->
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { InstanceScore } from '@conformetry/core';
|
|
2
|
+
import { InventoriedInstance } from '@conformetry/core';
|
|
3
|
+
import { InventoriedTemplate } from '@conformetry/core';
|
|
4
|
+
import { ScoringService } from '@conformetry/languages';
|
|
5
|
+
import { ValidationFileResult } from '@conformetry/core';
|
|
6
|
+
|
|
7
|
+
/** Arguments for rendering a full validation report. */
|
|
8
|
+
declare interface FormatReportArguments {
|
|
9
|
+
/** Failing files, already grouped by `PluginService` or `FilesService`. */
|
|
10
|
+
readonly fileResults: ValidationFileResult[];
|
|
11
|
+
/**
|
|
12
|
+
* Per-instance scores to summarize above the findings.
|
|
13
|
+
*
|
|
14
|
+
* Optional so a caller with nothing to score β a single ad-hoc comparison β
|
|
15
|
+
* still gets a report. Instances that scored perfectly are left out of the
|
|
16
|
+
* summary: printing a full line for each would bury the ones that did not.
|
|
17
|
+
*/
|
|
18
|
+
readonly scores?: InstanceScore[];
|
|
19
|
+
/**
|
|
20
|
+
* Directory that absolute paths are made relative to, so reports stay
|
|
21
|
+
* readable and machine-independent. Passed in rather than discovered, since
|
|
22
|
+
* this package deliberately has no workspace awareness.
|
|
23
|
+
*/
|
|
24
|
+
readonly workingDirectory: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Provides the template and instance inventory renderer.
|
|
29
|
+
*/
|
|
30
|
+
export declare class InventoryModule {
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Renders the template and instance inventory as readable lines.
|
|
35
|
+
*
|
|
36
|
+
* The whole rendered form lives here rather than in the host that prints it,
|
|
37
|
+
* because the indent ladder, the headings, and the percentage are one visual
|
|
38
|
+
* grammar: split across two packages, half of it would drift from the other.
|
|
39
|
+
* Hosts decide what to ask for and where the lines go; this decides how a
|
|
40
|
+
* pairing reads.
|
|
41
|
+
*
|
|
42
|
+
* Paths arrive absolute, because that is the only stable way for discovery to
|
|
43
|
+
* name an instance to another process. Shortening them is a host's concern β
|
|
44
|
+
* only a host knows which directory a person is standing in β so it is offered
|
|
45
|
+
* here as a separate step rather than folded into rendering.
|
|
46
|
+
*/
|
|
47
|
+
export declare class InventoryService {
|
|
48
|
+
constructor();
|
|
49
|
+
/** Renders one pairing as an indented line beneath its entry. */
|
|
50
|
+
private describePairing;
|
|
51
|
+
/**
|
|
52
|
+
* Renders a file-overlap ratio as a whole percentage.
|
|
53
|
+
*
|
|
54
|
+
* Deliberately coarser than the score percentage reporting renders. A score
|
|
55
|
+
* is read against a threshold, where a tenth of a percent decides whether an
|
|
56
|
+
* instance passes; this is "how much of the template is here", scanned down
|
|
57
|
+
* a list, where a decimal is noise.
|
|
58
|
+
*/
|
|
59
|
+
private formatRatio;
|
|
60
|
+
/** Shortens an absolute path against the directory a host was run in. */
|
|
61
|
+
private shortenPath;
|
|
62
|
+
/** Renders every instance found, with the templates that explain each. */
|
|
63
|
+
describeInstances(instances: InventoriedInstance[]): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Renders every declared template, with the instances each explains.
|
|
66
|
+
*
|
|
67
|
+
* The instances are listed only when the caller narrowed by path. A bare
|
|
68
|
+
* listing is a registry β naming every instance of every template there
|
|
69
|
+
* would bury the handful somebody actually asked about.
|
|
70
|
+
*/
|
|
71
|
+
describeTemplates(args: {
|
|
72
|
+
showInstances: boolean;
|
|
73
|
+
templates: InventoriedTemplate[];
|
|
74
|
+
}): string[];
|
|
75
|
+
/** Shortens the path naming each instance found. */
|
|
76
|
+
shortenInstancePaths(args: {
|
|
77
|
+
instances: InventoriedInstance[];
|
|
78
|
+
workingDirectory: string;
|
|
79
|
+
}): InventoriedInstance[];
|
|
80
|
+
/** Shortens the path naming each instance a template explains. */
|
|
81
|
+
shortenTemplatePairings(args: {
|
|
82
|
+
templates: InventoriedTemplate[];
|
|
83
|
+
workingDirectory: string;
|
|
84
|
+
}): InventoriedTemplate[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Owns rendering of structured conformance differences into readable text.
|
|
89
|
+
*
|
|
90
|
+
* Imported by `conformetry-validation` and by the CLI, so that a validation
|
|
91
|
+
* run reports identically no matter which surface invoked it.
|
|
92
|
+
*/
|
|
93
|
+
export declare class ReportingModule {
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Renders structured conformance differences as human-readable text.
|
|
98
|
+
*
|
|
99
|
+
* Reports are grouped by file and then by error, and every error prints the
|
|
100
|
+
* template requirement that produced it plus a concrete `fix` line. That last
|
|
101
|
+
* part is the point: the output is meant to be actionable by whoever β or
|
|
102
|
+
* whatever β is asked to make the file conform.
|
|
103
|
+
*/
|
|
104
|
+
export declare class ReportingService {
|
|
105
|
+
private readonly scoringService;
|
|
106
|
+
constructor(scoringService: ScoringService);
|
|
107
|
+
/**
|
|
108
|
+
* Renders one error: its message, where it was found in both the instance
|
|
109
|
+
* and the template, the expected and actual values when known, and the fix.
|
|
110
|
+
*/
|
|
111
|
+
private formatError;
|
|
112
|
+
/**
|
|
113
|
+
* Renders one failing file: a numbered heading, the instance and template
|
|
114
|
+
* paths relative to the working directory, then each of its differences.
|
|
115
|
+
*/
|
|
116
|
+
private formatFileResult;
|
|
117
|
+
/**
|
|
118
|
+
* Renders a weight pair as ` β met/total requirements met (percentage)`.
|
|
119
|
+
*
|
|
120
|
+
* One renderer for every level β file, instance, and run total β so the same
|
|
121
|
+
* three numbers appear in the same order wherever a reader looks.
|
|
122
|
+
*/
|
|
123
|
+
private formatFraction;
|
|
124
|
+
/**
|
|
125
|
+
* Renders a single location line, preferring line/column over a JSON path.
|
|
126
|
+
* Returns nothing when the error carries neither, which is normal for
|
|
127
|
+
* whole-file differences such as a missing file.
|
|
128
|
+
*/
|
|
129
|
+
private formatLocation;
|
|
130
|
+
/** Renders one instance's score as a fraction, a percentage, and a verdict. */
|
|
131
|
+
private formatScore;
|
|
132
|
+
/**
|
|
133
|
+
* Renders the summary of instances that did not score perfectly.
|
|
134
|
+
*
|
|
135
|
+
* The fraction is printed alongside the percentage because the percentage
|
|
136
|
+
* alone hides its own scale: "99.3%" reads the same whether one requirement
|
|
137
|
+
* of 151 went missing or thirty of four thousand did, and only the first is
|
|
138
|
+
* a five-minute fix.
|
|
139
|
+
*
|
|
140
|
+
* Both sides of the comparison are printed too, because a score alone does
|
|
141
|
+
* not say whether the run failed: 94% passes under a threshold of 90 and
|
|
142
|
+
* fails under 95, and a reader should not have to go looking for which
|
|
143
|
+
* applied.
|
|
144
|
+
*/
|
|
145
|
+
private formatScores;
|
|
146
|
+
/**
|
|
147
|
+
* Renders the run's total across every scored instance.
|
|
148
|
+
*
|
|
149
|
+
* Totalled over all of them rather than only the ones listed above, because
|
|
150
|
+
* the question the total answers is how the run did overall, and a total of
|
|
151
|
+
* just the failures would always read close to zero.
|
|
152
|
+
*
|
|
153
|
+
* The unit is the instance/template pair, not the file. One file governed by
|
|
154
|
+
* two templates owes both of them, so its requirements genuinely count twice
|
|
155
|
+
* β which is why this is labelled by instances rather than presented as a
|
|
156
|
+
* share of the codebase.
|
|
157
|
+
*/
|
|
158
|
+
private formatTotal;
|
|
159
|
+
/** Renders a 0-to-1 score as a percentage. */
|
|
160
|
+
formatPercentage(score: number): string;
|
|
161
|
+
/**
|
|
162
|
+
* Renders every failing file as one report string, with a score summary
|
|
163
|
+
* above it. Returns a success message when there is nothing to report, so
|
|
164
|
+
* callers never print an empty report.
|
|
165
|
+
*
|
|
166
|
+
* Findings print whether or not their instance cleared its threshold: a
|
|
167
|
+
* lowered threshold is permission to ship the drift, not a reason to stop
|
|
168
|
+
* showing it.
|
|
169
|
+
*/
|
|
170
|
+
formatReport(args: FormatReportArguments): string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { }
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Injectable as e, Module as t } from "@nestjs/common";
|
|
2
|
+
import n from "node:path";
|
|
3
|
+
import { DEFAULT_ERROR_WEIGHT as r, PERFECT_SCORE as i, ScoringModule as a, ScoringService as o } from "@conformetry/languages";
|
|
4
|
+
//#region packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.constants.ts
|
|
5
|
+
var s = " ", c = " ", l = "Instances:", u = "Templates:", d = "Template: ";
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorateMetadata.js
|
|
8
|
+
function f(e, t) {
|
|
9
|
+
if (typeof Reflect == "object" && typeof Reflect.metadata == "function") return Reflect.metadata(e, t);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
|
|
13
|
+
function p(e, t, n, r) {
|
|
14
|
+
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
15
|
+
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
16
|
+
else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
|
|
17
|
+
return i > 3 && a && Object.defineProperty(t, n, a), a;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.service.ts
|
|
21
|
+
var m = class {
|
|
22
|
+
constructor() {}
|
|
23
|
+
describePairing(e) {
|
|
24
|
+
let t = `${String(e.matchedFileCount)}/${String(e.templateFileCount)}`;
|
|
25
|
+
return `${c}${e.name} ${t} files ${this.formatRatio(e.matchRatio)}`;
|
|
26
|
+
}
|
|
27
|
+
formatRatio(e) {
|
|
28
|
+
return `${String(Math.round(e * 100))}%`;
|
|
29
|
+
}
|
|
30
|
+
shortenPath(e) {
|
|
31
|
+
return n.relative(e.workingDirectory, e.absolutePath);
|
|
32
|
+
}
|
|
33
|
+
describeInstances(e) {
|
|
34
|
+
return e.flatMap((e) => [
|
|
35
|
+
` ${e.path}`,
|
|
36
|
+
`${s}${u}`,
|
|
37
|
+
...e.templates.map((e) => this.describePairing(e))
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
describeTemplates(e) {
|
|
41
|
+
return e.templates.flatMap((t) => {
|
|
42
|
+
let n = [` ${t.name}`];
|
|
43
|
+
return t.description !== "" && n.push(`${s}${t.description}`), n.push(`${s}${d}${t.templatePath}`), e.showInstances && t.instances.length > 0 && n.push(`${s}${l}`, ...t.instances.map((e) => this.describePairing(e))), n;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
shortenInstancePaths(e) {
|
|
47
|
+
return e.instances.map((t) => ({
|
|
48
|
+
...t,
|
|
49
|
+
path: this.shortenPath({
|
|
50
|
+
absolutePath: t.path,
|
|
51
|
+
workingDirectory: e.workingDirectory
|
|
52
|
+
})
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
shortenTemplatePairings(e) {
|
|
56
|
+
return e.templates.map((t) => ({
|
|
57
|
+
...t,
|
|
58
|
+
instances: t.instances.map((t) => ({
|
|
59
|
+
...t,
|
|
60
|
+
name: this.shortenPath({
|
|
61
|
+
absolutePath: t.name,
|
|
62
|
+
workingDirectory: e.workingDirectory
|
|
63
|
+
})
|
|
64
|
+
}))
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
m = p([e(), f("design:paramtypes", [])], m);
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region packages/ic-suite/conformetry/conformetry-output/src/modules/inventory/inventory.module.ts
|
|
71
|
+
var h = class {};
|
|
72
|
+
h = p([t({
|
|
73
|
+
controllers: [],
|
|
74
|
+
exports: [m],
|
|
75
|
+
imports: [],
|
|
76
|
+
providers: [m]
|
|
77
|
+
})], h);
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.constants.ts
|
|
80
|
+
var g = " ", _ = " ", v = "Conformance scores:", y = "All checked files conform.", b = class {
|
|
81
|
+
scoringService;
|
|
82
|
+
constructor(e) {
|
|
83
|
+
this.scoringService = e;
|
|
84
|
+
}
|
|
85
|
+
formatError(e) {
|
|
86
|
+
let { error: t } = e;
|
|
87
|
+
return [
|
|
88
|
+
"",
|
|
89
|
+
`${_}${String(e.index + 1)}. ${t.message}`,
|
|
90
|
+
...this.formatLocation({
|
|
91
|
+
column: t.instanceColumn,
|
|
92
|
+
jsonPath: t.instancePath,
|
|
93
|
+
line: t.instanceLine,
|
|
94
|
+
prefix: "Instance"
|
|
95
|
+
}),
|
|
96
|
+
...this.formatLocation({
|
|
97
|
+
column: t.templateColumn,
|
|
98
|
+
jsonPath: t.templatePath,
|
|
99
|
+
line: t.templateLine,
|
|
100
|
+
prefix: "Template"
|
|
101
|
+
}),
|
|
102
|
+
...t.expected === void 0 ? [] : [`${g}Expected: \`${t.expected}\``],
|
|
103
|
+
...t.actual === void 0 ? [] : [`${g}Actual : \`${t.actual}\``],
|
|
104
|
+
...(t.weight ?? r) <= r ? [] : [`${g}Weight : ${String(t.weight)} of the ${String(e.totalWeight)} requirements in this file`],
|
|
105
|
+
`${g}Fix : ${t.fix}`
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
formatFileResult(e) {
|
|
109
|
+
let { fileResult: t } = e;
|
|
110
|
+
return [
|
|
111
|
+
"",
|
|
112
|
+
` ${String(e.index + 1)}. file: ${t.filename}${this.formatFraction({
|
|
113
|
+
failedWeight: this.scoringService.sumWeights(t.differences),
|
|
114
|
+
totalWeight: t.totalWeight
|
|
115
|
+
})}`,
|
|
116
|
+
`${_}Instance: ${n.relative(e.workingDirectory, t.instanceFilePath)}`,
|
|
117
|
+
`${_}Template: ${n.relative(e.workingDirectory, t.templateFilePath)}`,
|
|
118
|
+
...t.differences.flatMap((e, n) => this.formatError({
|
|
119
|
+
error: e,
|
|
120
|
+
index: n,
|
|
121
|
+
totalWeight: t.totalWeight
|
|
122
|
+
}))
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
formatFraction(e) {
|
|
126
|
+
let t = e.totalWeight - e.failedWeight, n = this.scoringService.calculateScore(e);
|
|
127
|
+
return ` β ${String(t)}/${String(e.totalWeight)} requirements met (${this.formatPercentage(n)})`;
|
|
128
|
+
}
|
|
129
|
+
formatLocation(e) {
|
|
130
|
+
if (e.line !== void 0) {
|
|
131
|
+
let t = e.column === void 0 ? "" : `, Column ${String(e.column)}`;
|
|
132
|
+
return [`${g}${e.prefix}: Line ${String(e.line)}${t}`];
|
|
133
|
+
}
|
|
134
|
+
return e.jsonPath === void 0 ? [] : [`${g}${e.prefix}: JSON path "${e.jsonPath}"`];
|
|
135
|
+
}
|
|
136
|
+
formatScore(e) {
|
|
137
|
+
let { score: t } = e, r = t.ok ? `meets threshold ${this.formatPercentage(t.threshold)}` : `below threshold ${this.formatPercentage(t.threshold)}`, i = n.relative(e.workingDirectory, t.instancePath);
|
|
138
|
+
return ` ${t.ok ? "β" : "β"} ${i} (${t.templateName})${this.formatFraction(t)}, ${r}`;
|
|
139
|
+
}
|
|
140
|
+
formatScores(e) {
|
|
141
|
+
let t = e.scores.filter((e) => e.score < i);
|
|
142
|
+
return t.length === 0 ? [] : [
|
|
143
|
+
v,
|
|
144
|
+
...t.map((t) => this.formatScore({
|
|
145
|
+
score: t,
|
|
146
|
+
workingDirectory: e.workingDirectory
|
|
147
|
+
})),
|
|
148
|
+
this.formatTotal(e.scores),
|
|
149
|
+
""
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
formatTotal(e) {
|
|
153
|
+
let t = e.reduce((e, t) => e + t.failedWeight, 0), n = e.reduce((e, t) => e + t.totalWeight, 0), r = e.filter((e) => !e.ok).length;
|
|
154
|
+
return ` Total${this.formatFraction({
|
|
155
|
+
failedWeight: t,
|
|
156
|
+
totalWeight: n
|
|
157
|
+
})} across ${String(e.length)} instance(s), ${String(r)} below threshold`;
|
|
158
|
+
}
|
|
159
|
+
formatPercentage(e) {
|
|
160
|
+
return `${(e * 100).toFixed(1)}%`;
|
|
161
|
+
}
|
|
162
|
+
formatReport(e) {
|
|
163
|
+
let t = this.formatScores({
|
|
164
|
+
scores: e.scores ?? [],
|
|
165
|
+
workingDirectory: e.workingDirectory
|
|
166
|
+
});
|
|
167
|
+
return e.fileResults.length === 0 ? [...t, y].join("\n") : [...t, ...e.fileResults.flatMap((t, n) => this.formatFileResult({
|
|
168
|
+
fileResult: t,
|
|
169
|
+
index: n,
|
|
170
|
+
workingDirectory: e.workingDirectory
|
|
171
|
+
}))].join("\n").trimStart();
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
b = p([e(), f("design:paramtypes", [o === void 0 ? Object : o])], b);
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region packages/ic-suite/conformetry/conformetry-output/src/modules/reporting/reporting.module.ts
|
|
177
|
+
var x = class {};
|
|
178
|
+
x = p([t({
|
|
179
|
+
controllers: [],
|
|
180
|
+
exports: [b],
|
|
181
|
+
imports: [a],
|
|
182
|
+
providers: [b]
|
|
183
|
+
})], x);
|
|
184
|
+
//#endregion
|
|
185
|
+
export { h as InventoryModule, m as InventoryService, x as ReportingModule, b as ReportingService };
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "Jimmy Paolini",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/Organizzolini/codebase/issues"
|
|
5
|
+
},
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@conformetry/core": "0.0.1",
|
|
8
|
+
"@conformetry/languages": "0.0.1",
|
|
9
|
+
"@nestjs/common": "^11.1.21 || ^12.0.1",
|
|
10
|
+
"reflect-metadata": "^0.2.2"
|
|
11
|
+
},
|
|
12
|
+
"description": "Console rendering, JSON reporting, and formatting for Conformetry conformance results",
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@golevelup/ts-vitest": "^4.0.0",
|
|
15
|
+
"@nestjs/testing": "^12.0.1",
|
|
16
|
+
"@nx/eslint-plugin": "^23.0.0",
|
|
17
|
+
"@swc/helpers": "^0.5.21",
|
|
18
|
+
"@types/node": "^26.5.1",
|
|
19
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
20
|
+
"vitest": "^5.0.0"
|
|
21
|
+
},
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/src/index.d.ts",
|
|
25
|
+
"default": "./dist/src/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"homepage": "https://github.com/Organizzolini/codebase/tree/main/packages/ic-suite/conformetry/conformetry-output#readme",
|
|
35
|
+
"keywords": [
|
|
36
|
+
"cli-reporter",
|
|
37
|
+
"conformetry",
|
|
38
|
+
"formatting",
|
|
39
|
+
"output",
|
|
40
|
+
"reporting"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"main": "./dist/src/index.js",
|
|
44
|
+
"name": "@conformetry/output",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"registry": "https://registry.npmjs.org"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"directory": "packages/ic-suite/conformetry/conformetry-output",
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/Organizzolini/codebase.git"
|
|
53
|
+
},
|
|
54
|
+
"type": "module",
|
|
55
|
+
"typeCoverage": {
|
|
56
|
+
"atLeast": 100,
|
|
57
|
+
"strict": true
|
|
58
|
+
},
|
|
59
|
+
"types": "./dist/src/index.d.ts",
|
|
60
|
+
"version": "0.0.1"
|
|
61
|
+
}
|