@coinagerie/cli 0.0.4 โ†’ 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.0.5 (2026-11-06)
2
+
3
+ ### ๐Ÿ”ฅ Performance
4
+
5
+ - **coinagerie:** โšก๏ธ judge every project's glossary from one batched command-line run ([#2115](https://github.com/organizzolini/codebase/pull/2115))
6
+
7
+ ### ๐Ÿงฑ Updated Dependencies
8
+
9
+ - Updated coinagerie-configuration to 0.0.5
10
+ - Updated coinagerie-vocabulary to 0.0.5
11
+ - Updated coinagerie-output to 0.0.5
12
+ - Updated coinagerie-core to 0.0.5
13
+
1
14
  ## 0.0.4 (2026-11-04)
2
15
 
3
16
  ### ๐Ÿงฑ Updated Dependencies
package/README.md CHANGED
@@ -67,25 +67,15 @@ The words this project uses that the root glossary does not define, regenerated
67
67
  - **anchor**: Start and end marker comments bracketing the coinagerie block in a markdown glossary, so a write replaces only that span.
68
68
  - **angle**: Sample glossary word the end-to-end tests define as the gap between two bodies, used to exercise a failing check.
69
69
  - **aspect**: Sample glossary word in the collect command's JSON and check-failure fixtures, standing for an identifier that must be defined.
70
+ - **batch**: The command that checks or writes the glossaries of many project directories in one process, printing a JSON verdict for each.
70
71
  - **breadth**: Second limit in callidescope's gate, the count of distinct callees one callable may reach, here capped at five in this package.
71
72
  - **bullet**: Glossary entry line in the form dash, bold word, colon, which carries the definition beneath it and is what the parser reads.
72
- - **comparison**: Service that diffs the code's words against each glossary, producing the missing and stale sets that a check reports.
73
- - **deliver**: Private method of the collect command that writes or prints the reconciled glossary for the chosen mode, once words are collected.
74
- - **delivery**: Final stage of a collect run, reached through the deliver method, where words are printed, checked, or written to destinations.
75
- - **destination**: Output target of a glossary, a markdown or JSON file declared in configuration, which a run reads, checks, or rewrites.
76
- - **discovery**: Step of finding the files a run scans, bounded by the include globs and the gitignore rules the run honors.
73
+ - **disagree**: Of a glossary whose words differ from the code's, missing some or listing stale ones, so a check fails on it.
77
74
  - **glossary**: The markdown or JSON file of word-to-definition entries that a run checks against the code and rewrites when asked.
78
- - **leftover**: Word from a scratch-directory fixture file that the end-to-end test asserts stays out of the printed output.
79
75
  - **lunar**: Sample glossary word in the check-failure fixtures, given an empty definition, which a check still passes though it stays undefined.
80
- - **malformed**: Glossary block whose structure cannot be fully parsed, which a run refuses to write, leaving the file untouched.
81
76
  - **phase**: Sample glossary word in the check-failure fixtures, given a short definition that the markdown and JSON tests assert on.
82
- - **polyglot**: Repository mixing several languages, whose identifiers coinagerie gathers across every file type it scans into one glossary.
83
77
  - **reconcile**: Method of the comparison service that merges collected words with existing glossary entries, keeping definitions for words still in use.
84
- - **rejection**: Reason string that rejectionOf returns when a command line is invalid, halting the run before any words are collected.
85
78
  - **rewrite**: Action of the write mode that rewrites every glossary to hold exactly the code's words, keeping definitions for words still present.
86
- - **scratch**: Folder name of a throwaway fixture the end-to-end test writes into a temporary workspace, holding a file whose words must stay out.
87
- - **stale**: Glossary entry for a word the code no longer uses, which a check names and a write deletes along with its definition.
88
- - **vanish**: Condition of a glossary word no longer in the code, so a check reports it stale and a write removes it.
89
79
  - **vocabulary**: Workspace package that collects the words a codebase uses, depended on by coinagerie-cli to gather its vocabulary.
90
80
 
91
81
  <!-- coinagerie:end -->
@@ -98,13 +88,13 @@ Call stacks traced through `projects/ic-suite/coinagerie/coinagerie-cli`, deepes
98
88
 
99
89
  | Measure | Value |
100
90
  | --- | --- |
101
- | Callables | 27 |
102
- | Files | 16 |
103
- | Calls traced | 24 |
104
- | Call stacks | 1 |
91
+ | Callables | 40 |
92
+ | Files | 25 |
93
+ | Calls traced | 37 |
94
+ | Call stacks | 2 |
105
95
  | Deepest stack | 13 |
106
96
  | Stacks through recursion | 0 |
107
- | Unfollowable calls | 1 |
97
+ | Unfollowable calls | 2 |
108
98
 
109
99
  ### Limits
110
100
 
@@ -117,7 +107,35 @@ What this project is judged against, as declared in its own `callidescope.config
117
107
 
118
108
  ### Call stacks (depth)
119
109
 
120
- **1. `CollectCommand.run`** โ€” depth โ‰ฅ 13 ยท decorated-method
110
+ **1. `BatchCommand.run`** โ€” depth โ‰ฅ 13 ยท decorated-method
111
+
112
+ ```text
113
+ ๐Ÿš€ BatchCommand.run(directories: string[], options?: BatchCommandOptions): Promise<void> [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/batch/batch.command.ts:61]
114
+ โ†ณ Judges or rewrites each named project, then prints every verdict.
115
+ โ””โ”€> CheckService.run(args: RunCheckArguments): Promise<CheckVerdict> [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/check/check.service.ts:70]
116
+ โ†ณ Runs one project's check or write, failing with the reason on any fault.
117
+ โ””โ”€> CheckService.deliver(โ€ฆ): CheckVerdict [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/check/check.service.ts:40]
118
+ โ†ณ Checks or writes every destination against the collected words.
119
+ โ””โ”€> DeliveryService.write(args: DeliverArguments): DeliveryResult[] [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:113]
120
+ โ†ณ Rewrites every destination to hold exactly the vocabulary, keeping every definition still in use.
121
+ โ””โ”€> DeliveryService.readAll(destinations: ResolvedCoinagerieOutput[]): ReadDestination[] [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:83]
122
+ โ†ณ Reads and parses every destination, throwing before anything is written.
123
+ โ””โ”€> DeliveryService.map(โ€ฆ)(โ€ฆ): { content: string | undefined; destination: ResolvedCoinagerieOutput; glossary: Glossary; } [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:84]
124
+ โ””โ”€> MarkdownService.read(content: string | undefined, filePath: string): Glossary | undefined [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:237]
125
+ โ†ณ Reads a destination's glossary; a missing file holds none.
126
+ โ””โ”€> MarkdownService.parse(content: string, filePath: string): Glossary | undefined [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:212]
127
+ โ†ณ The glossary in a file's block, or `undefined` when it has no anchors.
128
+ โ””โ”€> MarkdownService.forEach(โ€ฆ)(text: string, index: number): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:228]
129
+ โ””โ”€> MarkdownService.readLine(state: BlockParserState, text: string, line: number): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:173]
130
+ โ†ณ Reads one line of the block, or refuses it.
131
+ โ””โ”€> MarkdownService.readBullet(โ€ฆ): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:110]
132
+ โ†ณ Reads one bullet, starting a new word.
133
+ โ””โ”€> MarkdownService.fail(state: Pick<BlockParserState, "filePath">, line: number, reason: string): never [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:50]
134
+ โ†ณ Fails a parse, naming the file and the one-indexed line.
135
+ โ””โ”€> MalformedGlossaryError.constructor(location: MalformedGlossaryLocation): MalformedGlossaryError [projects/ic-suite/coinagerie/coinagerie-core/src/modules/coinagerie-core/coinagerie-core.constants.ts:47]
136
+ ```
137
+
138
+ **2. `CollectCommand.run`** โ€” depth โ‰ฅ 13 ยท decorated-method
121
139
 
122
140
  ```text
123
141
  ๐Ÿš€ CollectCommand.run(_passedParameters: string[], options?: CollectCommandOptions): Promise<void> [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:335]
@@ -150,16 +168,21 @@ What this project is judged against, as declared in its own `callidescope.config
150
168
  | Callable | Breadth | Calls directly | Location |
151
169
  | --- | --- | --- | --- |
152
170
  | `CollectCommand.run` | 5 | `CollectCommand.selectMode`, `CollectCommand.loadConfiguration`, `CollectCommand.collectWords`, `CollectCommand.print`, `CollectCommand.deliver` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:335` |
153
- | `CollectCommand.check` | 3 | `CollectCommand.filter(โ€ฆ)`, `DeliveryService.check`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:67` |
154
- | `CollectCommand.deliver` | 3 | `CollectCommand.fail`, `CollectCommand.check`, `CollectCommand.write` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:113` |
171
+ | `CheckService.deliver` | 4 | `reportWritten`, `DeliveryService.write`, `judgeDifferences`, `DeliveryService.check` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/check/check.service.ts:40` |
172
+ | `CheckService.run` | 3 | `ConfigurationService.loadConfiguration`, `VocabularyService.collect`, `CheckService.deliver` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/check/check.service.ts:70` |
155
173
 
156
174
  <details>
157
- <summary>5 more callables</summary>
175
+ <summary>10 more callables</summary>
158
176
 
159
177
  | Callable | Breadth | Calls directly | Location |
160
178
  | --- | --- | --- | --- |
179
+ | `CollectCommand.check` | 3 | `CollectCommand.filter(โ€ฆ)`, `DeliveryService.check`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:67` |
180
+ | `CollectCommand.deliver` | 3 | `CollectCommand.fail`, `CollectCommand.check`, `CollectCommand.write` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:113` |
161
181
  | `CollectCommand.loadConfiguration` | 3 | `ConfigurationService.loadConfiguration`, `CollectCommand.overridesFrom`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:149` |
162
182
  | `CollectCommand.print` | 3 | `ComparisonService.reconcile`, `JsonService.render`, `MarkdownService.render` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:181` |
183
+ | `judgeDifferences` | 2 | `filter(โ€ฆ)`, `map(โ€ฆ)` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/check/check.utilities.ts:13` |
184
+ | `reportWritten` | 2 | `map(โ€ฆ)`, `filter(โ€ฆ)` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/check/check.utilities.ts:33` |
185
+ | `BatchCommand.run` | 2 | `CheckService.run`, `BatchCommand.every(โ€ฆ)` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/batch/batch.command.ts:61` |
163
186
  | `CollectCommand.collectWords` | 2 | `VocabularyService.collect`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:97` |
164
187
  | `CollectCommand.selectMode` | 2 | `CollectCommand.rejectionOf`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:208` |
165
188
  | `CollectCommand.write` | 2 | `DeliveryService.write`, `CollectCommand.filter(โ€ฆ)` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:224` |
@@ -201,6 +224,8 @@ _Dashed edges are dependencies Nx inferred from configuration rather than from c
201
224
  <!-- codependix:start name="codependix-nestjs-modules" -->
202
225
  ```mermaid
203
226
  flowchart LR
227
+ BatchModule
228
+ CheckModule
204
229
  CollectModule
205
230
  ComparisonModule
206
231
  ConfigModule([ConfigModule])
@@ -224,6 +249,10 @@ flowchart LR
224
249
  VocabularyModule
225
250
  WordsModule
226
251
  YamlModule
252
+ BatchModule --> CheckModule
253
+ CheckModule --> ConfigurationModule
254
+ CheckModule --> DeliveryModule
255
+ CheckModule --> VocabularyModule
227
256
  CollectModule --> ComparisonModule
228
257
  CollectModule --> ConfigurationModule
229
258
  CollectModule --> DeliveryModule
@@ -245,6 +274,7 @@ flowchart LR
245
274
  LanguagesModule --> TomlModule
246
275
  LanguagesModule --> TypescriptModule
247
276
  LanguagesModule --> YamlModule
277
+ MainModule --> BatchModule
248
278
  MainModule --> CollectModule
249
279
  MainModule --> DiscoveryModule
250
280
  PythonModule --> ScannerModule
@@ -278,6 +308,17 @@ graph LR
278
308
  file_src_coinagerie_cli_repl_ts["src/coinagerie-cli.repl.ts"]
279
309
  file_src_coinagerie_cli_repl_unit_test_ts["src/coinagerie-cli.repl.unit.test.ts"]
280
310
  file_src_index_ts["src/index.ts"]
311
+ file_src_modules_batch_batch_command_ts["src/modules/batch/batch.command.ts"]
312
+ file_src_modules_batch_batch_command_unit_test_ts["src/modules/batch/batch.command.unit.test.ts"]
313
+ file_src_modules_batch_batch_constants_ts["src/modules/batch/batch.constants.ts"]
314
+ file_src_modules_batch_batch_module_ts["src/modules/batch/batch.module.ts"]
315
+ file_src_modules_batch_batch_types_ts["src/modules/batch/batch.types.ts"]
316
+ file_src_modules_check_check_constants_ts["src/modules/check/check.constants.ts"]
317
+ file_src_modules_check_check_module_ts["src/modules/check/check.module.ts"]
318
+ file_src_modules_check_check_service_ts["src/modules/check/check.service.ts"]
319
+ file_src_modules_check_check_service_unit_test_ts["src/modules/check/check.service.unit.test.ts"]
320
+ file_src_modules_check_check_types_ts["src/modules/check/check.types.ts"]
321
+ file_src_modules_check_check_utilities_ts["src/modules/check/check.utilities.ts"]
281
322
  file_src_modules_collect_collect_command_end_to_end_test_ts["src/modules/collect/collect.command.end-to-end.test.ts"]
282
323
  file_src_modules_collect_collect_command_ts["src/modules/collect/collect.command.ts"]
283
324
  file_src_modules_collect_collect_command_unit_test_ts["src/modules/collect/collect.command.unit.test.ts"]
@@ -297,9 +338,26 @@ graph LR
297
338
  file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_run_command_ts
298
339
  file_src_coinagerie_cli_main_ts --> file_src_coinagerie_cli_module_ts
299
340
  file_src_coinagerie_cli_module_ts --> file_src_coinagerie_cli_constants_ts
341
+ file_src_coinagerie_cli_module_ts --> file_src_modules_batch_batch_module_ts
300
342
  file_src_coinagerie_cli_module_ts --> file_src_modules_collect_collect_module_ts
301
343
  file_src_coinagerie_cli_module_unit_test_ts --> file_src_coinagerie_cli_module_ts
302
344
  file_src_coinagerie_cli_repl_ts --> file_src_coinagerie_cli_module_ts
345
+ file_src_modules_batch_batch_command_ts --> file_src_modules_batch_batch_constants_ts
346
+ file_src_modules_batch_batch_command_ts --> file_src_modules_batch_batch_types_ts
347
+ file_src_modules_batch_batch_command_ts --> file_src_modules_check_check_service_ts
348
+ file_src_modules_batch_batch_command_unit_test_ts --> file_src_modules_batch_batch_command_ts
349
+ file_src_modules_batch_batch_command_unit_test_ts --> file_src_modules_check_check_service_ts
350
+ file_src_modules_batch_batch_command_unit_test_ts --> file_src_modules_check_check_types_ts
351
+ file_src_modules_batch_batch_module_ts --> file_src_modules_batch_batch_command_ts
352
+ file_src_modules_batch_batch_module_ts --> file_src_modules_check_check_module_ts
353
+ file_src_modules_batch_batch_types_ts --> file_src_modules_check_check_types_ts
354
+ file_src_modules_check_check_module_ts --> file_src_modules_check_check_service_ts
355
+ file_src_modules_check_check_service_ts --> file_src_modules_check_check_constants_ts
356
+ file_src_modules_check_check_service_ts --> file_src_modules_check_check_types_ts
357
+ file_src_modules_check_check_service_ts --> file_src_modules_check_check_utilities_ts
358
+ file_src_modules_check_check_service_unit_test_ts --> file_src_modules_check_check_service_ts
359
+ file_src_modules_check_check_utilities_ts --> file_src_modules_check_check_constants_ts
360
+ file_src_modules_check_check_utilities_ts --> file_src_modules_check_check_types_ts
303
361
  file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_examples_ts
304
362
  file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_fixture_tree_ts
305
363
  file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_run_command_ts
@@ -318,36 +376,36 @@ graph LR
318
376
 
319
377
  ### Project
320
378
 
321
- ![Lines of Code](https://img.shields.io/badge/Lines_of_Code-1800-22c55e?style=flat-square)
322
- ![Repository Size](https://img.shields.io/badge/Repository_Size-68.01_kB-6b7280?style=flat-square)
323
- ![Folders](https://img.shields.io/badge/Folders-4-4a4a4a?style=flat-square)
324
- ![Source Files](https://img.shields.io/badge/Source_Files-26-3178c6?style=flat-square)
379
+ ![Lines of Code](https://img.shields.io/badge/Lines_of_Code-2424-22c55e?style=flat-square)
380
+ ![Repository Size](https://img.shields.io/badge/Repository_Size-86.66_kB-6b7280?style=flat-square)
381
+ ![Folders](https://img.shields.io/badge/Folders-6-4a4a4a?style=flat-square)
382
+ ![Source Files](https://img.shields.io/badge/Source_Files-37-3178c6?style=flat-square)
325
383
 
326
384
  ### TypeScript
327
385
 
328
- ![TypeScript Files](https://img.shields.io/badge/TypeScript_Files-26-3178c6?style=flat-square)
329
- ![Interfaces](https://img.shields.io/badge/Interfaces-2-0ea5e9?style=flat-square)
386
+ ![TypeScript Files](https://img.shields.io/badge/TypeScript_Files-37-3178c6?style=flat-square)
387
+ ![Interfaces](https://img.shields.io/badge/Interfaces-8-0ea5e9?style=flat-square)
330
388
  ![Generic Declarations](https://img.shields.io/badge/Generic_Declarations-0-0369a1?style=flat-square)
331
389
  ![Enums](https://img.shields.io/badge/Enums-0-f97316?style=flat-square)
332
- ![Decorators](https://img.shields.io/badge/Decorators-13-db2777?style=flat-square)
333
- ![Doc Comments](https://img.shields.io/badge/Doc_Comments-38-6366f1?style=flat-square)
390
+ ![Decorators](https://img.shields.io/badge/Decorators-19-db2777?style=flat-square)
391
+ ![Doc Comments](https://img.shields.io/badge/Doc_Comments-60-6366f1?style=flat-square)
334
392
  ![Static Methods](https://img.shields.io/badge/Static_Methods-0-166534?style=flat-square)
335
393
 
336
394
  ### JavaScript
337
395
 
338
396
  ![JavaScript Files](https://img.shields.io/badge/JavaScript_Files-0-f7df1e?style=flat-square)
339
- ![Test Files](https://img.shields.io/badge/Test_Files-5-10b981?style=flat-square)
397
+ ![Test Files](https://img.shields.io/badge/Test_Files-7-10b981?style=flat-square)
340
398
  ![External Packages](https://img.shields.io/badge/External_Packages-18-8b5cf6?style=flat-square)
341
- ![Classes](https://img.shields.io/badge/Classes-3-7c3aed?style=flat-square)
342
- ![Functions](https://img.shields.io/badge/Functions-84-16a34a?style=flat-square)
343
- ![Methods](https://img.shields.io/badge/Methods-23-15803d?style=flat-square)
344
- ![Sync Functions](https://img.shields.io/badge/Sync_Functions-87-4ade80?style=flat-square)
345
- ![Async Functions](https://img.shields.io/badge/Async_Functions-20-059669?style=flat-square)
346
- ![Constants](https://img.shields.io/badge/Constants-100-dc2626?style=flat-square)
347
- ![Imports](https://img.shields.io/badge/Imports-79-0284c7?style=flat-square)
348
- ![Exported Symbols](https://img.shields.io/badge/Exported_Symbols-16-ea580c?style=flat-square)
349
- ![Comments](https://img.shields.io/badge/Comments-56-64748b?style=flat-square)
350
- ![Comment Lines](https://img.shields.io/badge/Comment_Lines-135-475569?style=flat-square)
399
+ ![Classes](https://img.shields.io/badge/Classes-7-7c3aed?style=flat-square)
400
+ ![Functions](https://img.shields.io/badge/Functions-113-16a34a?style=flat-square)
401
+ ![Methods](https://img.shields.io/badge/Methods-28-15803d?style=flat-square)
402
+ ![Sync Functions](https://img.shields.io/badge/Sync_Functions-108-4ade80?style=flat-square)
403
+ ![Async Functions](https://img.shields.io/badge/Async_Functions-33-059669?style=flat-square)
404
+ ![Constants](https://img.shields.io/badge/Constants-124-dc2626?style=flat-square)
405
+ ![Imports](https://img.shields.io/badge/Imports-124-0284c7?style=flat-square)
406
+ ![Exported Symbols](https://img.shields.io/badge/Exported_Symbols-31-ea580c?style=flat-square)
407
+ ![Comments](https://img.shields.io/badge/Comments-92-64748b?style=flat-square)
408
+ ![Comment Lines](https://img.shields.io/badge/Comment_Lines-190-475569?style=flat-square)
351
409
  ![TODO Comments](https://img.shields.io/badge/TODO_Comments-0-ca8a04?style=flat-square)
352
410
 
353
411
  ### Python
@@ -458,14 +516,14 @@ graph LR
458
516
 
459
517
  ### Conventions
460
518
 
461
- ![Module Files](https://img.shields.io/badge/Module_Files-2-7c3aed?style=flat-square)
462
- ![Service Files](https://img.shields.io/badge/Service_Files-0-0284c7?style=flat-square)
463
- ![Command Files](https://img.shields.io/badge/Command_Files-1-16a34a?style=flat-square)
464
- ![Constants Files](https://img.shields.io/badge/Constants_Files-2-ea580c?style=flat-square)
465
- ![Types Files](https://img.shields.io/badge/Types_Files-1-db2777?style=flat-square)
466
- ![Utilities Files](https://img.shields.io/badge/Utilities_Files-0-0ea5e9?style=flat-square)
519
+ ![Module Files](https://img.shields.io/badge/Module_Files-4-7c3aed?style=flat-square)
520
+ ![Service Files](https://img.shields.io/badge/Service_Files-1-0284c7?style=flat-square)
521
+ ![Command Files](https://img.shields.io/badge/Command_Files-2-16a34a?style=flat-square)
522
+ ![Constants Files](https://img.shields.io/badge/Constants_Files-4-ea580c?style=flat-square)
523
+ ![Types Files](https://img.shields.io/badge/Types_Files-3-db2777?style=flat-square)
524
+ ![Utilities Files](https://img.shields.io/badge/Utilities_Files-1-0ea5e9?style=flat-square)
467
525
  ![TypeORM Entities](https://img.shields.io/badge/TypeORM_Entities-0-059669?style=flat-square)
468
- ![Unit Tests](https://img.shields.io/badge/Unit_Tests-3-ca8a04?style=flat-square)
526
+ ![Unit Tests](https://img.shields.io/badge/Unit_Tests-5-ca8a04?style=flat-square)
469
527
  ![Integration Tests](https://img.shields.io/badge/Integration_Tests-0-7c3aed?style=flat-square)
470
528
  ![End To End Tests](https://img.shields.io/badge/End_To_End_Tests-2-0284c7?style=flat-square)
471
529
  ![CSS Comment Budget](https://img.shields.io/badge/CSS_Comment_Budget-0-16a34a?style=flat-square)
@@ -503,20 +561,20 @@ graph LR
503
561
  ### Markdown
504
562
 
505
563
  ![Markdown Files](https://img.shields.io/badge/Markdown_Files-2-083fa1?style=flat-square)
506
- ![Markdown Lines](https://img.shields.io/badge/Markdown_Lines-291-1f6feb?style=flat-square)
564
+ ![Markdown Lines](https://img.shields.io/badge/Markdown_Lines-304-1f6feb?style=flat-square)
507
565
  ![H1](https://img.shields.io/badge/H1-1-7c3aed?style=flat-square)
508
- ![H2](https://img.shields.io/badge/H2-11-8b5cf6?style=flat-square)
509
- ![H3](https://img.shields.io/badge/H3-19-a78bfa?style=flat-square)
566
+ ![H2](https://img.shields.io/badge/H2-12-8b5cf6?style=flat-square)
567
+ ![H3](https://img.shields.io/badge/H3-21-a78bfa?style=flat-square)
510
568
  ![H4](https://img.shields.io/badge/H4-0-c4b5fd?style=flat-square)
511
569
  ![H5](https://img.shields.io/badge/H5-0-ddd6fe?style=flat-square)
512
570
  ![H6](https://img.shields.io/badge/H6-0-ede9fe?style=flat-square)
513
- ![Paragraphs](https://img.shields.io/badge/Paragraphs-71-64748b?style=flat-square)
514
- ![Lists](https://img.shields.io/badge/Lists-11-16a34a?style=flat-square)
515
- ![List Items](https://img.shields.io/badge/List_Items-50-22c55e?style=flat-square)
571
+ ![Paragraphs](https://img.shields.io/badge/Paragraphs-76-64748b?style=flat-square)
572
+ ![Lists](https://img.shields.io/badge/Lists-13-16a34a?style=flat-square)
573
+ ![List Items](https://img.shields.io/badge/List_Items-55-22c55e?style=flat-square)
516
574
  ![Task List Items](https://img.shields.io/badge/Task_List_Items-0-4ade80?style=flat-square)
517
575
  ![Tables](https://img.shields.io/badge/Tables-2-0284c7?style=flat-square)
518
576
  ![Table Rows](https://img.shields.io/badge/Table_Rows-10-0ea5e9?style=flat-square)
519
- ![Links](https://img.shields.io/badge/Links-21-059669?style=flat-square)
577
+ ![Links](https://img.shields.io/badge/Links-22-059669?style=flat-square)
520
578
  ![Images](https://img.shields.io/badge/Images-0-10b981?style=flat-square)
521
579
  ![Code Blocks](https://img.shields.io/badge/Code_Blocks-13-dc2626?style=flat-square)
522
580
  ![Inline Code](https://img.shields.io/badge/Inline_Code-78-ef4444?style=flat-square)
@@ -196,7 +196,139 @@ I = __decorate([a(), s({
196
196
  providers: [F]
197
197
  })], I);
198
198
  // src/coinagerie-cli.constants.ts
199
- var L = h.object({}), R = ["markdown", "json"], z, B = z = class CollectCommand extends n {
199
+ var L = h.object({}), R = "๐Ÿช™";
200
+ // src/modules/check/check.utilities.ts
201
+ function judgeDifferences(e) {
202
+ let t = e.differences.filter(({ missing: e, stale: t }) => e.length > 0 || t.length > 0);
203
+ return {
204
+ ok: t.length === 0,
205
+ report: t.map(({ missing: t, path: n, stale: r }) => `${R} Found a glossary out of step with the code: ${d.relative(e.workspaceRoot, n)}\n missing: ${t.join(", ")}\n stale: ${r.join(", ")}`).join("\n")
206
+ };
207
+ }
208
+ function reportWritten(e) {
209
+ return {
210
+ ok: !0,
211
+ report: e.results.filter(({ written: e }) => e).map(({ path: t }) => `${R} Wrote the glossary: ${d.relative(e.workspaceRoot, t)}`).join("\n")
212
+ };
213
+ }
214
+ // src/modules/check/check.service.ts
215
+ var z = class CheckService {
216
+ configurationService;
217
+ vocabularyService;
218
+ deliveryService;
219
+ constructor(e, t, n) {
220
+ this.configurationService = e, this.vocabularyService = t, this.deliveryService = n;
221
+ }
222
+ deliver(e) {
223
+ let { configuration: t, mode: n, words: r, workspaceRoot: i } = e, a = t.outputs;
224
+ return a.length === 0 ? {
225
+ ok: !1,
226
+ report: `${R} Found no glossary destination to ${n}: ${d.relative(i, t.configurationPath ?? "")}`
227
+ } : n === "write" ? reportWritten({
228
+ results: this.deliveryService.write({
229
+ destinations: a,
230
+ words: r
231
+ }),
232
+ workspaceRoot: i
233
+ }) : judgeDifferences({
234
+ differences: this.deliveryService.check({
235
+ destinations: a,
236
+ words: r
237
+ }),
238
+ workspaceRoot: i
239
+ });
240
+ }
241
+ async run(e) {
242
+ try {
243
+ let t = await this.configurationService.loadConfiguration({
244
+ configurationPath: void 0,
245
+ overrides: {},
246
+ workingDirectory: e.directory
247
+ }), n = await this.vocabularyService.collect(t);
248
+ return this.deliver({
249
+ configuration: t,
250
+ mode: e.mode,
251
+ words: n,
252
+ workspaceRoot: e.workspaceRoot
253
+ });
254
+ } catch (t) {
255
+ return {
256
+ ok: !1,
257
+ report: `${R} Could not ${e.mode} ${d.relative(e.workspaceRoot, e.directory)}: ${t instanceof Error ? t.message : String(t)}`
258
+ };
259
+ }
260
+ }
261
+ };
262
+ z = __decorate([o(), __decorateMetadata("design:paramtypes", [
263
+ _ === void 0 ? Object : _,
264
+ D === void 0 ? Object : D,
265
+ x === void 0 ? Object : x
266
+ ])], z);
267
+ // src/modules/check/check.module.ts
268
+ var B = class CheckModule {};
269
+ B = __decorate([s({
270
+ controllers: [],
271
+ exports: [z],
272
+ imports: [
273
+ g,
274
+ b,
275
+ E
276
+ ],
277
+ providers: [z]
278
+ })], B);
279
+ // src/modules/batch/batch.constants.ts
280
+ var V = "<directories...>", H, U = H = class BatchCommand extends n {
281
+ checkService;
282
+ logger;
283
+ constructor(e, t) {
284
+ super(), this.checkService = e, this.logger = t, this.logger.setContext(H.name);
285
+ }
286
+ parseWrite() {
287
+ return !0;
288
+ }
289
+ async run(e, t = {}) {
290
+ let n = [];
291
+ for (let r of e) {
292
+ let e = await this.checkService.run({
293
+ directory: d.resolve(r),
294
+ mode: t.write === !0 ? "write" : "check",
295
+ workspaceRoot: process.cwd()
296
+ });
297
+ n.push({
298
+ directory: r,
299
+ ...e
300
+ });
301
+ }
302
+ process.stdout.write(`${JSON.stringify(n)}\n`), process.exitCode = +!n.every(({ ok: e }) => e);
303
+ }
304
+ };
305
+ __decorate([
306
+ r({
307
+ description: "Rewrite every glossary to hold exactly the code's words, keeping definitions",
308
+ flags: "--write"
309
+ }),
310
+ __decorateMetadata("design:type", Function),
311
+ __decorateMetadata("design:paramtypes", []),
312
+ __decorateMetadata("design:returntype", Boolean)
313
+ ], U.prototype, "parseWrite", null), U = H = __decorate([
314
+ e({
315
+ arguments: V,
316
+ description: "Check or write the glossaries of every named project directory, printing a JSON verdict for each",
317
+ name: "batch"
318
+ }),
319
+ o(),
320
+ __decorateMetadata("design:paramtypes", [z === void 0 ? Object : z, F === void 0 ? Object : F])
321
+ ], U);
322
+ // src/modules/batch/batch.module.ts
323
+ var W = class BatchModule {};
324
+ W = __decorate([s({
325
+ controllers: [],
326
+ exports: [U],
327
+ imports: [B, I],
328
+ providers: [U]
329
+ })], W);
330
+ // src/modules/collect/collect.constants.ts
331
+ var G = ["markdown", "json"], K, q = K = class CollectCommand extends n {
200
332
  configurationService;
201
333
  vocabularyService;
202
334
  comparisonService;
@@ -205,7 +337,7 @@ var L = h.object({}), R = ["markdown", "json"], z, B = z = class CollectCommand
205
337
  markdownService;
206
338
  logger;
207
339
  constructor(e, t, n, r, i, a, o) {
208
- super(), this.configurationService = e, this.vocabularyService = t, this.comparisonService = n, this.deliveryService = r, this.jsonService = i, this.markdownService = a, this.logger = o, this.logger.setContext(z.name);
340
+ super(), this.configurationService = e, this.vocabularyService = t, this.comparisonService = n, this.deliveryService = r, this.jsonService = i, this.markdownService = a, this.logger = o, this.logger.setContext(K.name);
209
341
  }
210
342
  check(e, t) {
211
343
  let n = this.deliveryService.check({
@@ -267,7 +399,7 @@ var L = h.object({}), R = ["markdown", "json"], z, B = z = class CollectCommand
267
399
  }
268
400
  rejectionOf(e) {
269
401
  if (e.check === !0 && e.write === !0) return "--check and --write cannot be combined";
270
- if (e.format !== void 0 && !R.includes(e.format)) return `--format must be one of ${R.join(", ")}, not "${e.format}"`;
402
+ if (e.format !== void 0 && !G.includes(e.format)) return `--format must be one of ${G.join(", ")}, not "${e.format}"`;
271
403
  }
272
404
  selectMode(e) {
273
405
  let t = this.rejectionOf(e);
@@ -333,7 +465,7 @@ __decorate([
333
465
  __decorateMetadata("design:type", Function),
334
466
  __decorateMetadata("design:paramtypes", []),
335
467
  __decorateMetadata("design:returntype", Boolean)
336
- ], B.prototype, "parseCheck", null), __decorate([
468
+ ], q.prototype, "parseCheck", null), __decorate([
337
469
  r({
338
470
  description: "Path to a coinagerie configuration file; coinagerie.config.ts in the working directory is used when omitted",
339
471
  flags: "--config <config>"
@@ -341,7 +473,7 @@ __decorate([
341
473
  __decorateMetadata("design:type", Function),
342
474
  __decorateMetadata("design:paramtypes", [String]),
343
475
  __decorateMetadata("design:returntype", String)
344
- ], B.prototype, "parseConfig", null), __decorate([
476
+ ], q.prototype, "parseConfig", null), __decorate([
345
477
  r({
346
478
  description: "Text rendered under the heading of every markdown destination, replacing the configured description",
347
479
  flags: "--description <description>"
@@ -349,7 +481,7 @@ __decorate([
349
481
  __decorateMetadata("design:type", Function),
350
482
  __decorateMetadata("design:paramtypes", [String]),
351
483
  __decorateMetadata("design:returntype", String)
352
- ], B.prototype, "parseDescription", null), __decorate([
484
+ ], q.prototype, "parseDescription", null), __decorate([
353
485
  r({
354
486
  description: "Glob of files to leave out of the scan, replacing the configured exclude.paths; repeat for several",
355
487
  flags: "--exclude-paths <glob>"
@@ -357,15 +489,15 @@ __decorate([
357
489
  __decorateMetadata("design:type", Function),
358
490
  __decorateMetadata("design:paramtypes", [String, Array]),
359
491
  __decorateMetadata("design:returntype", Array)
360
- ], B.prototype, "parseExcludePaths", null), __decorate([
492
+ ], q.prototype, "parseExcludePaths", null), __decorate([
361
493
  r({
362
- description: `Format printed to standard output when neither --check nor --write is given: ${R.join(" or ")}`,
494
+ description: `Format printed to standard output when neither --check nor --write is given: ${G.join(" or ")}`,
363
495
  flags: "--format <format>"
364
496
  }),
365
497
  __decorateMetadata("design:type", Function),
366
498
  __decorateMetadata("design:paramtypes", [String]),
367
499
  __decorateMetadata("design:returntype", String)
368
- ], B.prototype, "parseFormat", null), __decorate([
500
+ ], q.prototype, "parseFormat", null), __decorate([
369
501
  r({
370
502
  description: "Glob of files to scan, replacing the configured include; repeat for several",
371
503
  flags: "--include <glob>"
@@ -373,7 +505,7 @@ __decorate([
373
505
  __decorateMetadata("design:type", Function),
374
506
  __decorateMetadata("design:paramtypes", [String, Array]),
375
507
  __decorateMetadata("design:returntype", Array)
376
- ], B.prototype, "parseInclude", null), __decorate([
508
+ ], q.prototype, "parseInclude", null), __decorate([
377
509
  r({
378
510
  description: "JSON glossary to check or write, replacing the configured outputs",
379
511
  flags: "--output-json <path>"
@@ -381,7 +513,7 @@ __decorate([
381
513
  __decorateMetadata("design:type", Function),
382
514
  __decorateMetadata("design:paramtypes", [String]),
383
515
  __decorateMetadata("design:returntype", String)
384
- ], B.prototype, "parseOutputJson", null), __decorate([
516
+ ], q.prototype, "parseOutputJson", null), __decorate([
385
517
  r({
386
518
  description: "Markdown file holding a glossary block to check or write, replacing the configured outputs",
387
519
  flags: "--output-markdown <path>"
@@ -389,7 +521,7 @@ __decorate([
389
521
  __decorateMetadata("design:type", Function),
390
522
  __decorateMetadata("design:paramtypes", [String]),
391
523
  __decorateMetadata("design:returntype", String)
392
- ], B.prototype, "parseOutputMarkdown", null), __decorate([
524
+ ], q.prototype, "parseOutputMarkdown", null), __decorate([
393
525
  r({
394
526
  description: "Rewrite every glossary to hold exactly the code's words, keeping definitions",
395
527
  flags: "--write"
@@ -397,7 +529,7 @@ __decorate([
397
529
  __decorateMetadata("design:type", Function),
398
530
  __decorateMetadata("design:paramtypes", []),
399
531
  __decorateMetadata("design:returntype", Boolean)
400
- ], B.prototype, "parseWrite", null), B = z = __decorate([
532
+ ], q.prototype, "parseWrite", null), q = K = __decorate([
401
533
  e({
402
534
  description: "List the words the code uses, and check or write a glossary of them",
403
535
  name: "collect",
@@ -413,12 +545,12 @@ __decorate([
413
545
  T === void 0 ? Object : T,
414
546
  F === void 0 ? Object : F
415
547
  ])
416
- ], B);
548
+ ], q);
417
549
  // src/modules/collect/collect.module.ts
418
- var V = class CollectModule {};
419
- V = __decorate([s({
550
+ var J = class CollectModule {};
551
+ J = __decorate([s({
420
552
  controllers: [],
421
- exports: [B],
553
+ exports: [q],
422
554
  imports: [
423
555
  v,
424
556
  g,
@@ -428,11 +560,11 @@ V = __decorate([s({
428
560
  w,
429
561
  E
430
562
  ],
431
- providers: [B]
432
- })], V);
563
+ providers: [q]
564
+ })], J);
433
565
  // src/coinagerie-cli.module.ts
434
- var H = class MainModule {};
435
- H = __decorate([s({ imports: [
566
+ var Y = class MainModule {};
567
+ Y = __decorate([s({ imports: [
436
568
  p.forRoot({
437
569
  envFilePath: ".env",
438
570
  isGlobal: !0,
@@ -440,13 +572,14 @@ H = __decorate([s({ imports: [
440
572
  }),
441
573
  m,
442
574
  I,
443
- V
444
- ] })], H);
575
+ W,
576
+ J
577
+ ] })], Y);
445
578
  // src/coinagerie-cli.main.ts
446
579
  async function main() {
447
580
  F.logToStandardError();
448
581
  let e = new F();
449
- e.setContext("CommandFactory"), await t.run(H, {
582
+ e.setContext("CommandFactory"), await t.run(Y, {
450
583
  bufferLogs: !0,
451
584
  logger: e,
452
585
  serviceErrorHandler: (t) => {
package/package.json CHANGED
@@ -7,10 +7,10 @@
7
7
  "url": "https://github.com/organizzolini/codebase/issues"
8
8
  },
9
9
  "dependencies": {
10
- "@coinagerie/configuration": "0.0.4",
11
- "@coinagerie/core": "0.0.4",
12
- "@coinagerie/output": "0.0.4",
13
- "@coinagerie/vocabulary": "0.0.4",
10
+ "@coinagerie/configuration": "0.0.5",
11
+ "@coinagerie/core": "0.0.5",
12
+ "@coinagerie/output": "0.0.5",
13
+ "@coinagerie/vocabulary": "0.0.5",
14
14
  "@nestjs/common": "^11.1.21 || ^12.0.1",
15
15
  "@nestjs/config": "^12.0.0",
16
16
  "@nestjs/core": "^11.1.21 || ^12.0.1",
@@ -72,5 +72,5 @@
72
72
  "strict": true
73
73
  },
74
74
  "types": "./dist/src/index.d.ts",
75
- "version": "0.0.4"
75
+ "version": "0.0.5"
76
76
  }