@coinagerie/cli 0.0.0-stage → 0.0.2

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 ADDED
@@ -0,0 +1,26 @@
1
+ ## 0.0.2 (2026-11-04)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated coinagerie-configuration to 0.0.2
6
+ - Updated coinagerie-vocabulary to 0.0.2
7
+ - Updated coinagerie-output to 0.0.2
8
+ - Updated coinagerie-core to 0.0.2
9
+
10
+ ## 0.0.1 (2026-11-04)
11
+
12
+ ### 🚀 Features
13
+
14
+ - **coinagerie:** 📦️ publish coinagerie to npm ([#2088](https://github.com/organizzolini/codebase/pull/2088), [#1793](https://github.com/organizzolini/codebase/issues/1793))
15
+ - **configuration,coinagerie:** ✨ adopt coinagerie with a root glossary ([#1888](https://github.com/organizzolini/codebase/pull/1888), [#1785](https://github.com/organizzolini/codebase/issues/1785))
16
+ - **coinagerie:** ✨ read identifiers from python, sql, shell, css, hcl, toml, json, and yaml ([#1881](https://github.com/organizzolini/codebase/pull/1881), [#1770](https://github.com/organizzolini/codebase/issues/1770))
17
+ - **coinagerie:** ✨ write json glossaries and override configuration with flags ([#1880](https://github.com/organizzolini/codebase/pull/1880), [#1766](https://github.com/organizzolini/codebase/issues/1766))
18
+ - **coinagerie:** ✨ fold word forms and exclude configured words ([#1882](https://github.com/organizzolini/codebase/pull/1882), [#1762](https://github.com/organizzolini/codebase/issues/1762))
19
+ - **coinagerie:** ✨ build a markdown glossary from typescript ([#1875](https://github.com/organizzolini/codebase/pull/1875), [#1755](https://github.com/organizzolini/codebase/issues/1755))
20
+
21
+ ### 🧱 Updated Dependencies
22
+
23
+ - Updated coinagerie-configuration to 0.0.1
24
+ - Updated coinagerie-vocabulary to 0.0.1
25
+ - Updated coinagerie-output to 0.0.1
26
+ - Updated coinagerie-core to 0.0.1
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 CHANGED
@@ -1,3 +1,525 @@
1
- # Temporary Holding Version
1
+ # @coinagerie/cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm](https://img.shields.io/npm/v/@coinagerie/cli?logo=npm&label=npm)](https://www.npmjs.com/package/@coinagerie/cli)
4
+
5
+ **Keep a glossary of the words your codebase uses.**
6
+
7
+ ```bash
8
+ npm install --save-dev @coinagerie/cli
9
+ ```
10
+
11
+ ```bash
12
+ npx @coinagerie/cli
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ `coinagerie` lists the words a codebase uses — every identifier, object key,
18
+ enum member, folder name, and file name, split into lowercase words — and keeps
19
+ a markdown glossary of them in step with the code.
20
+
21
+ ```bash
22
+ coinagerie # print the glossary block, write nothing
23
+ coinagerie --check # exit 1 naming missing and stale words
24
+ coinagerie --write # rewrite every glossary, keeping definitions
25
+ coinagerie --config path/to/coinagerie.config.ts --check
26
+ ```
27
+
28
+ Without `--config`, a `coinagerie.config.ts` in the working directory is used
29
+ when there is one, and defaults apply when there is not. The folder the
30
+ configuration file sits in is the root the run scans:
31
+
32
+ ```ts
33
+ export default {
34
+ exclude: { paths: ["**/*.test.ts"] },
35
+ include: ["src/**"],
36
+ outputs: [
37
+ { description: "Words this project uses.", path: "README.md", type: "markdown" },
38
+ ],
39
+ };
40
+ ```
41
+
42
+ Every `.gitignore` git would honor is honored, and the files a run writes are
43
+ never scanned. A glossary block that cannot be fully parsed is never written.
44
+
45
+ ## Start
46
+
47
+ ```bash
48
+ nx run coinagerie-cli:start
49
+ ```
50
+
51
+ ## Test
52
+
53
+ ```bash
54
+ nx run coinagerie-cli:vitest
55
+ ```
56
+
57
+ ## 👔 Conformetry
58
+
59
+ This project was generated from the [nestjs-command-project](../../configuration/conformetry-templates/nestjs-command-project) conformetry template.
60
+
61
+ <!-- coinagerie:start -->
62
+
63
+ ## 🪙 Coinagerie
64
+
65
+ The words this project uses that the root glossary does not define, regenerated with `nx run coinagerie-cli:coinagerie-check:write`.
66
+
67
+ - **anchor**:
68
+ - **angle**:
69
+ - **aspect**:
70
+ - **breadth**:
71
+ - **bullet**:
72
+ - **comparison**:
73
+ - **deliver**:
74
+ - **delivery**:
75
+ - **destination**:
76
+ - **discovery**:
77
+ - **glossary**:
78
+ - **leftover**:
79
+ - **lunar**:
80
+ - **malformed**:
81
+ - **phase**:
82
+ - **polyglot**:
83
+ - **reconcile**:
84
+ - **rejection**:
85
+ - **rewrite**:
86
+ - **scratch**:
87
+ - **stale**:
88
+ - **vanish**:
89
+ - **vocabulary**:
90
+
91
+ <!-- coinagerie:end -->
92
+
93
+ <!-- callidescope:start -->
94
+
95
+ ## 🔭 Callidescope
96
+
97
+ Call stacks traced through `projects/ic-suite/coinagerie/coinagerie-cli`, deepest first. Each frame shows what it takes, what it returns, and what its documentation says.
98
+
99
+ | Measure | Value |
100
+ | --- | --- |
101
+ | Callables | 27 |
102
+ | Files | 16 |
103
+ | Calls traced | 24 |
104
+ | Call stacks | 1 |
105
+ | Deepest stack | 13 |
106
+ | Stacks through recursion | 0 |
107
+ | Unfollowable calls | 1 |
108
+
109
+ ### Limits
110
+
111
+ What this project is judged against, as declared in its own `callidescope.config.ts`.
112
+
113
+ | Limit | Value |
114
+ | --- | --- |
115
+ | `maximumDepth` | 13 |
116
+ | `maximumBreadth` | 5 |
117
+
118
+ ### Call stacks (depth)
119
+
120
+ **1. `CollectCommand.run`** — depth ≥ 13 · decorated-method
121
+
122
+ ```text
123
+ 🚀 CollectCommand.run(_passedParameters: string[], options?: CollectCommandOptions): Promise<void> [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:335]
124
+ ↳ Collects the vocabulary and prints, checks, or writes it.
125
+ └─> CollectCommand.deliver(…): void [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:113]
126
+ ↳ Checks or writes, refusing a glossary that cannot be parsed.
127
+ └─> CollectCommand.check(configuration: ResolvedCoinagerieConfiguration, words: string[]): void [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:67]
128
+ ↳ Checks every destination, failing the run when any disagrees.
129
+ └─> DeliveryService.check(args: DeliverArguments): GlossaryDifference[] [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:102]
130
+ ↳ How each destination differs from the vocabulary, writing nothing.
131
+ └─> DeliveryService.readAll(destinations: ResolvedCoinagerieOutput[]): ReadDestination[] [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:83]
132
+ ↳ Reads and parses every destination, throwing before anything is written.
133
+ └─> DeliveryService.map(…)(…): { content: string | undefined; destination: ResolvedCoinagerieOutput; glossary: Glossary; } [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:84]
134
+ └─> MarkdownService.read(content: string | undefined, filePath: string): Glossary | undefined [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:237]
135
+ ↳ Reads a destination's glossary; a missing file holds none.
136
+ └─> MarkdownService.parse(content: string, filePath: string): Glossary | undefined [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:212]
137
+ ↳ The glossary in a file's block, or `undefined` when it has no anchors.
138
+ └─> MarkdownService.forEach(…)(text: string, index: number): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:228]
139
+ └─> MarkdownService.readLine(state: BlockParserState, text: string, line: number): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:173]
140
+ ↳ Reads one line of the block, or refuses it.
141
+ └─> MarkdownService.readBullet(…): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:110]
142
+ ↳ Reads one bullet, starting a new word.
143
+ └─> MarkdownService.fail(state: Pick<BlockParserState, "filePath">, line: number, reason: string): never [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:50]
144
+ ↳ Fails a parse, naming the file and the one-indexed line.
145
+ └─> MalformedGlossaryError.constructor(location: MalformedGlossaryLocation): MalformedGlossaryError [projects/ic-suite/coinagerie/coinagerie-core/src/modules/coinagerie-core/coinagerie-core.constants.ts:47]
146
+ ```
147
+
148
+ ### Breadth
149
+
150
+ | Callable | Breadth | Calls directly | Location |
151
+ | --- | --- | --- | --- |
152
+ | `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` |
155
+
156
+ <details>
157
+ <summary>5 more callables</summary>
158
+
159
+ | Callable | Breadth | Calls directly | Location |
160
+ | --- | --- | --- | --- |
161
+ | `CollectCommand.loadConfiguration` | 3 | `ConfigurationService.loadConfiguration`, `CollectCommand.overridesFrom`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:149` |
162
+ | `CollectCommand.print` | 3 | `ComparisonService.reconcile`, `JsonService.render`, `MarkdownService.render` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:181` |
163
+ | `CollectCommand.collectWords` | 2 | `VocabularyService.collect`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:97` |
164
+ | `CollectCommand.selectMode` | 2 | `CollectCommand.rejectionOf`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:208` |
165
+ | `CollectCommand.write` | 2 | `DeliveryService.write`, `CollectCommand.filter(…)` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:224` |
166
+
167
+ </details>
168
+ <!-- callidescope:end -->
169
+
170
+ ## 🕸️ Codependix
171
+
172
+ Dependency graphs exported by [codependix](https://github.com/Organizzolini/codebase/tree/main/projects/ic-suite/codependix/codependix-cli), regenerated by `nx run configuration:codependix:write`.
173
+
174
+ ### Nx Neighborhood
175
+
176
+ <!-- codependix:start name="codependix-nx-projects" -->
177
+ ```mermaid
178
+ graph LR
179
+ coinagerie_cli["coinagerie-cli"]
180
+ coinagerie_configuration["coinagerie-configuration"]
181
+ coinagerie_core["coinagerie-core"]
182
+ coinagerie_examples["coinagerie-examples"]
183
+ coinagerie_output["coinagerie-output"]
184
+ coinagerie_vocabulary["coinagerie-vocabulary"]
185
+ observability["observability"]
186
+ coinagerie_cli --> coinagerie_configuration
187
+ coinagerie_cli --> coinagerie_core
188
+ coinagerie_cli --> coinagerie_output
189
+ coinagerie_cli --> coinagerie_vocabulary
190
+ coinagerie_cli --> observability
191
+ coinagerie_examples -.-> coinagerie_cli
192
+ classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
193
+ class coinagerie_cli subject
194
+ ```
195
+
196
+ _Dashed edges are dependencies Nx inferred from configuration rather than from code._
197
+ <!-- codependix:end name="codependix-nx-projects" -->
198
+
199
+ ### NestJS Module Graph
200
+
201
+ <!-- codependix:start name="codependix-nestjs-modules" -->
202
+ ```mermaid
203
+ flowchart LR
204
+ CollectModule
205
+ ComparisonModule
206
+ ConfigModule([ConfigModule])
207
+ ConfigurationModule
208
+ CssModule
209
+ DeliveryModule
210
+ DiscoveryModule
211
+ FoldingModule
212
+ HclModule
213
+ JsonModule
214
+ LanguagesModule
215
+ LoggerModule([LoggerModule])
216
+ MainModule
217
+ MarkdownModule
218
+ PythonModule
219
+ ScannerModule
220
+ ShellModule
221
+ SqlModule
222
+ TomlModule
223
+ TypescriptModule
224
+ VocabularyModule
225
+ WordsModule
226
+ YamlModule
227
+ CollectModule --> ComparisonModule
228
+ CollectModule --> ConfigurationModule
229
+ CollectModule --> DeliveryModule
230
+ CollectModule --> JsonModule
231
+ CollectModule --> MarkdownModule
232
+ CollectModule --> VocabularyModule
233
+ CssModule --> ScannerModule
234
+ DeliveryModule --> ComparisonModule
235
+ DeliveryModule --> JsonModule
236
+ DeliveryModule --> MarkdownModule
237
+ HclModule --> ScannerModule
238
+ JsonModule --> ScannerModule
239
+ LanguagesModule --> CssModule
240
+ LanguagesModule --> HclModule
241
+ LanguagesModule --> JsonModule
242
+ LanguagesModule --> PythonModule
243
+ LanguagesModule --> ShellModule
244
+ LanguagesModule --> SqlModule
245
+ LanguagesModule --> TomlModule
246
+ LanguagesModule --> TypescriptModule
247
+ LanguagesModule --> YamlModule
248
+ MainModule --> CollectModule
249
+ MainModule --> DiscoveryModule
250
+ PythonModule --> ScannerModule
251
+ ShellModule --> ScannerModule
252
+ SqlModule --> ScannerModule
253
+ TomlModule --> ScannerModule
254
+ VocabularyModule --> DiscoveryModule
255
+ VocabularyModule --> FoldingModule
256
+ VocabularyModule --> LanguagesModule
257
+ VocabularyModule --> WordsModule
258
+ ```
259
+
260
+ _Rounded modules are global: every module can inject them, so their edges are left out._
261
+ <!-- codependix:end name="codependix-nestjs-modules" -->
262
+
263
+ ### File Imports
264
+
265
+ <!-- codependix:start name="codependix-file-imports" -->
266
+ ```mermaid
267
+ graph LR
268
+ file_callidescope_config_ts["callidescope.config.ts"]
269
+ file_codependix_config_ts["codependix.config.ts"]
270
+ file_codometer_config_ts["codometer.config.ts"]
271
+ file_coinagerie_config_ts["coinagerie.config.ts"]
272
+ file_eslint_config_ts["eslint.config.ts"]
273
+ file_src_coinagerie_cli_constants_ts["src/coinagerie-cli.constants.ts"]
274
+ file_src_coinagerie_cli_main_end_to_end_test_ts["src/coinagerie-cli.main.end-to-end.test.ts"]
275
+ file_src_coinagerie_cli_main_ts["src/coinagerie-cli.main.ts"]
276
+ file_src_coinagerie_cli_module_ts["src/coinagerie-cli.module.ts"]
277
+ file_src_coinagerie_cli_module_unit_test_ts["src/coinagerie-cli.module.unit.test.ts"]
278
+ file_src_coinagerie_cli_repl_ts["src/coinagerie-cli.repl.ts"]
279
+ file_src_coinagerie_cli_repl_unit_test_ts["src/coinagerie-cli.repl.unit.test.ts"]
280
+ file_src_index_ts["src/index.ts"]
281
+ file_src_modules_collect_collect_command_end_to_end_test_ts["src/modules/collect/collect.command.end-to-end.test.ts"]
282
+ file_src_modules_collect_collect_command_ts["src/modules/collect/collect.command.ts"]
283
+ file_src_modules_collect_collect_command_unit_test_ts["src/modules/collect/collect.command.unit.test.ts"]
284
+ file_src_modules_collect_collect_constants_ts["src/modules/collect/collect.constants.ts"]
285
+ file_src_modules_collect_collect_module_ts["src/modules/collect/collect.module.ts"]
286
+ file_src_modules_collect_collect_types_ts["src/modules/collect/collect.types.ts"]
287
+ file_testing_examples_ts["testing/examples.ts"]
288
+ file_testing_fixture_tree_ts["testing/fixture-tree.ts"]
289
+ file_testing_mocks_ts["testing/mocks.ts"]
290
+ file_testing_run_command_ts["testing/run-command.ts"]
291
+ file_testing_setup_ts["testing/setup.ts"]
292
+ file_vite_config_ts["vite.config.ts"]
293
+ file_vitest_config_ts["vitest.config.ts"]
294
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_src_coinagerie_cli_constants_ts
295
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_examples_ts
296
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_fixture_tree_ts
297
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_run_command_ts
298
+ file_src_coinagerie_cli_main_ts --> file_src_coinagerie_cli_module_ts
299
+ file_src_coinagerie_cli_module_ts --> file_src_coinagerie_cli_constants_ts
300
+ file_src_coinagerie_cli_module_ts --> file_src_modules_collect_collect_module_ts
301
+ file_src_coinagerie_cli_module_unit_test_ts --> file_src_coinagerie_cli_module_ts
302
+ file_src_coinagerie_cli_repl_ts --> file_src_coinagerie_cli_module_ts
303
+ file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_examples_ts
304
+ file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_fixture_tree_ts
305
+ file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_run_command_ts
306
+ file_src_modules_collect_collect_command_ts --> file_src_modules_collect_collect_constants_ts
307
+ file_src_modules_collect_collect_command_ts --> file_src_modules_collect_collect_types_ts
308
+ file_src_modules_collect_collect_command_unit_test_ts --> file_src_modules_collect_collect_command_ts
309
+ file_src_modules_collect_collect_command_unit_test_ts --> file_src_modules_collect_collect_types_ts
310
+ file_src_modules_collect_collect_command_unit_test_ts --> file_testing_fixture_tree_ts
311
+ file_src_modules_collect_collect_module_ts --> file_src_modules_collect_collect_command_ts
312
+ ```
313
+ <!-- codependix:end name="codependix-file-imports" -->
314
+
315
+ <!-- codometer:start -->
316
+
317
+ ## ⏲️ Codometer
318
+
319
+ ### Project
320
+
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-67.59_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)
325
+
326
+ ### TypeScript
327
+
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)
330
+ ![Generic Declarations](https://img.shields.io/badge/Generic_Declarations-0-0369a1?style=flat-square)
331
+ ![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)
334
+ ![Static Methods](https://img.shields.io/badge/Static_Methods-0-166534?style=flat-square)
335
+
336
+ ### JavaScript
337
+
338
+ ![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)
340
+ ![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)
351
+ ![TODO Comments](https://img.shields.io/badge/TODO_Comments-0-ca8a04?style=flat-square)
352
+
353
+ ### Python
354
+
355
+ ![Python Files](https://img.shields.io/badge/Python_Files-0-3776ab?style=flat-square)
356
+ ![Python Lines](https://img.shields.io/badge/Python_Lines-0-4b8bbe?style=flat-square)
357
+ ![Python Classes](https://img.shields.io/badge/Python_Classes-0-7c3aed?style=flat-square)
358
+ ![Python Functions](https://img.shields.io/badge/Python_Functions-0-16a34a?style=flat-square)
359
+ ![Python Protocols](https://img.shields.io/badge/Python_Protocols-0-0ea5e9?style=flat-square)
360
+ ![Python Constants](https://img.shields.io/badge/Python_Constants-0-dc2626?style=flat-square)
361
+ ![Python Imports](https://img.shields.io/badge/Python_Imports-0-0284c7?style=flat-square)
362
+ ![Python Decorators](https://img.shields.io/badge/Python_Decorators-0-db2777?style=flat-square)
363
+ ![Docstrings](https://img.shields.io/badge/Docstrings-0-6366f1?style=flat-square)
364
+ ![Docstring Lines](https://img.shields.io/badge/Docstring_Lines-0-818cf8?style=flat-square)
365
+ ![Python Comments](https://img.shields.io/badge/Python_Comments-0-64748b?style=flat-square)
366
+ ![Python Comment Lines](https://img.shields.io/badge/Python_Comment_Lines-0-475569?style=flat-square)
367
+
368
+ ### JSON
369
+
370
+ ![JSON Files](https://img.shields.io/badge/JSON_Files-4-a16207?style=flat-square)
371
+ ![JSON Lines](https://img.shields.io/badge/JSON_Lines-195-ca8a04?style=flat-square)
372
+ ![JSON Objects](https://img.shields.io/badge/JSON_Objects-44-7c3aed?style=flat-square)
373
+ ![JSON Arrays](https://img.shields.io/badge/JSON_Arrays-14-8b5cf6?style=flat-square)
374
+ ![JSON Properties](https://img.shields.io/badge/JSON_Properties-121-0284c7?style=flat-square)
375
+ ![JSON Strings](https://img.shields.io/badge/JSON_Strings-107-16a34a?style=flat-square)
376
+ ![JSON Numbers](https://img.shields.io/badge/JSON_Numbers-1-059669?style=flat-square)
377
+ ![JSON Booleans](https://img.shields.io/badge/JSON_Booleans-7-0ea5e9?style=flat-square)
378
+ ![JSON Nulls](https://img.shields.io/badge/JSON_Nulls-0-64748b?style=flat-square)
379
+ ![JSON Items](https://img.shields.io/badge/JSON_Items-48-475569?style=flat-square)
380
+ ![JSON Nodes](https://img.shields.io/badge/JSON_Nodes-173-dc2626?style=flat-square)
381
+ ![JSON Max Depth](https://img.shields.io/badge/JSON_Max_Depth-7-ea580c?style=flat-square)
382
+
383
+ ### YAML
384
+
385
+ ![YAML Files](https://img.shields.io/badge/YAML_Files-0-cb171e?style=flat-square)
386
+ ![YAML Lines](https://img.shields.io/badge/YAML_Lines-0-e34c26?style=flat-square)
387
+ ![YAML Documents](https://img.shields.io/badge/YAML_Documents-0-f97316?style=flat-square)
388
+ ![YAML Mappings](https://img.shields.io/badge/YAML_Mappings-0-7c3aed?style=flat-square)
389
+ ![YAML Sequences](https://img.shields.io/badge/YAML_Sequences-0-8b5cf6?style=flat-square)
390
+ ![YAML Keys](https://img.shields.io/badge/YAML_Keys-0-0284c7?style=flat-square)
391
+ ![YAML Scalars](https://img.shields.io/badge/YAML_Scalars-0-16a34a?style=flat-square)
392
+ ![YAML Anchors](https://img.shields.io/badge/YAML_Anchors-0-059669?style=flat-square)
393
+ ![YAML Aliases](https://img.shields.io/badge/YAML_Aliases-0-10b981?style=flat-square)
394
+ ![YAML Comments](https://img.shields.io/badge/YAML_Comments-0-64748b?style=flat-square)
395
+ ![YAML Max Depth](https://img.shields.io/badge/YAML_Max_Depth-0-ea580c?style=flat-square)
396
+
397
+ ### TOML
398
+
399
+ ![TOML Files](https://img.shields.io/badge/TOML_Files-0-9c4221?style=flat-square)
400
+ ![TOML Lines](https://img.shields.io/badge/TOML_Lines-0-b45309?style=flat-square)
401
+ ![TOML Tables](https://img.shields.io/badge/TOML_Tables-0-7c3aed?style=flat-square)
402
+ ![TOML Array Tables](https://img.shields.io/badge/TOML_Array_Tables-0-8b5cf6?style=flat-square)
403
+ ![TOML Keys](https://img.shields.io/badge/TOML_Keys-0-0284c7?style=flat-square)
404
+ ![TOML Arrays](https://img.shields.io/badge/TOML_Arrays-0-16a34a?style=flat-square)
405
+ ![TOML Comments](https://img.shields.io/badge/TOML_Comments-0-64748b?style=flat-square)
406
+
407
+ ### Shell
408
+
409
+ ![Shell Files](https://img.shields.io/badge/Shell_Files-0-89e051?style=flat-square)
410
+ ![Shell Lines](https://img.shields.io/badge/Shell_Lines-0-4eaa25?style=flat-square)
411
+ ![Shell Functions](https://img.shields.io/badge/Shell_Functions-0-16a34a?style=flat-square)
412
+ ![Shell Variables](https://img.shields.io/badge/Shell_Variables-0-0284c7?style=flat-square)
413
+ ![Shell Exports](https://img.shields.io/badge/Shell_Exports-0-ea580c?style=flat-square)
414
+ ![Shell Conditionals](https://img.shields.io/badge/Shell_Conditionals-0-7c3aed?style=flat-square)
415
+ ![Shell Loops](https://img.shields.io/badge/Shell_Loops-0-8b5cf6?style=flat-square)
416
+ ![Shell Pipelines](https://img.shields.io/badge/Shell_Pipelines-0-059669?style=flat-square)
417
+ ![Shebangs](https://img.shields.io/badge/Shebangs-0-6b7280?style=flat-square)
418
+ ![Shell Comments](https://img.shields.io/badge/Shell_Comments-0-64748b?style=flat-square)
419
+ ![Shell Comment Lines](https://img.shields.io/badge/Shell_Comment_Lines-0-475569?style=flat-square)
420
+
421
+ ### SQL
422
+
423
+ ![SQL Files](https://img.shields.io/badge/SQL_Files-0-e38c00?style=flat-square)
424
+ ![SQL Lines](https://img.shields.io/badge/SQL_Lines-0-f29111?style=flat-square)
425
+ ![SQL Statements](https://img.shields.io/badge/SQL_Statements-0-7c3aed?style=flat-square)
426
+ ![SQL Selects](https://img.shields.io/badge/SQL_Selects-0-16a34a?style=flat-square)
427
+ ![SQL Inserts](https://img.shields.io/badge/SQL_Inserts-0-22c55e?style=flat-square)
428
+ ![SQL Updates](https://img.shields.io/badge/SQL_Updates-0-0ea5e9?style=flat-square)
429
+ ![SQL Deletes](https://img.shields.io/badge/SQL_Deletes-0-dc2626?style=flat-square)
430
+ ![SQL Creates](https://img.shields.io/badge/SQL_Creates-0-0284c7?style=flat-square)
431
+ ![SQL Joins](https://img.shields.io/badge/SQL_Joins-0-8b5cf6?style=flat-square)
432
+ ![SQL CTEs](https://img.shields.io/badge/SQL_CTEs-0-059669?style=flat-square)
433
+ ![SQL Comments](https://img.shields.io/badge/SQL_Comments-0-64748b?style=flat-square)
434
+
435
+ ### HCL
436
+
437
+ ![HCL Files](https://img.shields.io/badge/HCL_Files-0-844fba?style=flat-square)
438
+ ![HCL Lines](https://img.shields.io/badge/HCL_Lines-0-a78bfa?style=flat-square)
439
+ ![HCL Blocks](https://img.shields.io/badge/HCL_Blocks-0-7c3aed?style=flat-square)
440
+ ![HCL Resources](https://img.shields.io/badge/HCL_Resources-0-0284c7?style=flat-square)
441
+ ![HCL Variables](https://img.shields.io/badge/HCL_Variables-0-16a34a?style=flat-square)
442
+ ![HCL Outputs](https://img.shields.io/badge/HCL_Outputs-0-059669?style=flat-square)
443
+ ![HCL Attributes](https://img.shields.io/badge/HCL_Attributes-0-0ea5e9?style=flat-square)
444
+ ![HCL Interpolations](https://img.shields.io/badge/HCL_Interpolations-0-db2777?style=flat-square)
445
+ ![HCL Comments](https://img.shields.io/badge/HCL_Comments-0-64748b?style=flat-square)
446
+
447
+ ### CSS
448
+
449
+ ![CSS Files](https://img.shields.io/badge/CSS_Files-0-264de4?style=flat-square)
450
+ ![CSS Lines](https://img.shields.io/badge/CSS_Lines-0-2965f1?style=flat-square)
451
+ ![CSS Rules](https://img.shields.io/badge/CSS_Rules-0-7c3aed?style=flat-square)
452
+ ![CSS Selectors](https://img.shields.io/badge/CSS_Selectors-0-8b5cf6?style=flat-square)
453
+ ![CSS Declarations](https://img.shields.io/badge/CSS_Declarations-0-0284c7?style=flat-square)
454
+ ![CSS At Rules](https://img.shields.io/badge/CSS_At_Rules-0-f97316?style=flat-square)
455
+ ![CSS Media Queries](https://img.shields.io/badge/CSS_Media_Queries-0-ea580c?style=flat-square)
456
+ ![CSS Custom Properties](https://img.shields.io/badge/CSS_Custom_Properties-0-16a34a?style=flat-square)
457
+ ![CSS Comments](https://img.shields.io/badge/CSS_Comments-0-64748b?style=flat-square)
458
+
459
+ ### Conventions
460
+
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)
467
+ ![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)
469
+ ![Integration Tests](https://img.shields.io/badge/Integration_Tests-0-7c3aed?style=flat-square)
470
+ ![End To End Tests](https://img.shields.io/badge/End_To_End_Tests-2-0284c7?style=flat-square)
471
+ ![CSS Comment Budget](https://img.shields.io/badge/CSS_Comment_Budget-0-16a34a?style=flat-square)
472
+ ![HCL Comment Budget](https://img.shields.io/badge/HCL_Comment_Budget-0-ea580c?style=flat-square)
473
+ ![Python Comment Budget](https://img.shields.io/badge/Python_Comment_Budget-0-db2777?style=flat-square)
474
+ ![SQL Comment Budget](https://img.shields.io/badge/SQL_Comment_Budget-0-0ea5e9?style=flat-square)
475
+ ![TOML Comment Budget](https://img.shields.io/badge/TOML_Comment_Budget-0-059669?style=flat-square)
476
+ ![TypeScript Comment Budget](https://img.shields.io/badge/TypeScript_Comment_Budget-0-ca8a04?style=flat-square)
477
+ ![YAML Comment Budget](https://img.shields.io/badge/YAML_Comment_Budget-0-7c3aed?style=flat-square)
478
+ ![Shell Comment Budget](https://img.shields.io/badge/Shell_Comment_Budget-0-0284c7?style=flat-square)
479
+
480
+ ### Jupyter
481
+
482
+ ![Notebooks](https://img.shields.io/badge/Notebooks-0-f37626?style=flat-square)
483
+ ![Notebook Cells](https://img.shields.io/badge/Notebook_Cells-0-e8a33d?style=flat-square)
484
+ ![Code Cells](https://img.shields.io/badge/Code_Cells-0-3776ab?style=flat-square)
485
+ ![Markdown Cells](https://img.shields.io/badge/Markdown_Cells-0-083fa1?style=flat-square)
486
+ ![Raw Cells](https://img.shields.io/badge/Raw_Cells-0-9ca3af?style=flat-square)
487
+ ![Executed Cells](https://img.shields.io/badge/Executed_Cells-0-16a34a?style=flat-square)
488
+ ![Cell Outputs](https://img.shields.io/badge/Cell_Outputs-0-059669?style=flat-square)
489
+ ![Notebook Code Lines](https://img.shields.io/badge/Notebook_Code_Lines-0-4b8bbe?style=flat-square)
490
+ ![Notebook Classes](https://img.shields.io/badge/Notebook_Classes-0-7c3aed?style=flat-square)
491
+ ![Notebook Functions](https://img.shields.io/badge/Notebook_Functions-0-22c55e?style=flat-square)
492
+ ![Notebook Imports](https://img.shields.io/badge/Notebook_Imports-0-0284c7?style=flat-square)
493
+ ![Notebook Decorators](https://img.shields.io/badge/Notebook_Decorators-0-db2777?style=flat-square)
494
+ ![Notebook Prose Lines](https://img.shields.io/badge/Notebook_Prose_Lines-0-1f6feb?style=flat-square)
495
+ ![Notebook Headings](https://img.shields.io/badge/Notebook_Headings-0-a78bfa?style=flat-square)
496
+ ![Notebook Links](https://img.shields.io/badge/Notebook_Links-0-10b981?style=flat-square)
497
+ ![Notebook Images](https://img.shields.io/badge/Notebook_Images-0-34d399?style=flat-square)
498
+ ![Notebook Code Blocks](https://img.shields.io/badge/Notebook_Code_Blocks-0-dc2626?style=flat-square)
499
+ ![Notebook Properties](https://img.shields.io/badge/Notebook_Properties-0-ca8a04?style=flat-square)
500
+ ![Notebook Nodes](https://img.shields.io/badge/Notebook_Nodes-0-a16207?style=flat-square)
501
+ ![Notebook Max Depth](https://img.shields.io/badge/Notebook_Max_Depth-0-ea580c?style=flat-square)
502
+
503
+ ### Markdown
504
+
505
+ ![Markdown Files](https://img.shields.io/badge/Markdown_Files-2-083fa1?style=flat-square)
506
+ ![Markdown Lines](https://img.shields.io/badge/Markdown_Lines-273-1f6feb?style=flat-square)
507
+ ![H1](https://img.shields.io/badge/H1-1-7c3aed?style=flat-square)
508
+ ![H2](https://img.shields.io/badge/H2-9-8b5cf6?style=flat-square)
509
+ ![H3](https://img.shields.io/badge/H3-17-a78bfa?style=flat-square)
510
+ ![H4](https://img.shields.io/badge/H4-0-c4b5fd?style=flat-square)
511
+ ![H5](https://img.shields.io/badge/H5-0-ddd6fe?style=flat-square)
512
+ ![H6](https://img.shields.io/badge/H6-0-ede9fe?style=flat-square)
513
+ ![Paragraphs](https://img.shields.io/badge/Paragraphs-63-64748b?style=flat-square)
514
+ ![Lists](https://img.shields.io/badge/Lists-9-16a34a?style=flat-square)
515
+ ![List Items](https://img.shields.io/badge/List_Items-42-22c55e?style=flat-square)
516
+ ![Task List Items](https://img.shields.io/badge/Task_List_Items-0-4ade80?style=flat-square)
517
+ ![Tables](https://img.shields.io/badge/Tables-2-0284c7?style=flat-square)
518
+ ![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)
520
+ ![Images](https://img.shields.io/badge/Images-0-10b981?style=flat-square)
521
+ ![Code Blocks](https://img.shields.io/badge/Code_Blocks-13-dc2626?style=flat-square)
522
+ ![Inline Code](https://img.shields.io/badge/Inline_Code-78-ef4444?style=flat-square)
523
+ ![Block Quotes](https://img.shields.io/badge/Block_Quotes-0-ca8a04?style=flat-square)
524
+ ![Thematic Breaks](https://img.shields.io/badge/Thematic_Breaks-0-a16207?style=flat-square)
525
+ <!-- codometer:end -->
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,457 @@
1
+ #!/usr/bin/env node
2
+ import "reflect-metadata";
3
+ import { Command as e, CommandFactory as t, CommandRunner as n, Option as r } from "nest-commander";
4
+ import { ConsoleLogger as i, Global as a, Injectable as o, Module as s, Scope as c } from "@nestjs/common";
5
+ import { existsSync as l, mkdirSync as u } from "node:fs";
6
+ import d from "node:path";
7
+ import f from "pino";
8
+ import { ConfigModule as p } from "@nestjs/config";
9
+ import { DiscoveryModule as m } from "@nestjs/core";
10
+ import { z as h } from "zod";
11
+ import { ConfigurationModule as g, ConfigurationService as _ } from "@coinagerie/configuration";
12
+ import { ComparisonModule as v, ComparisonService as y, DeliveryModule as b, DeliveryService as x, JsonModule as S, JsonService as C, MarkdownModule as w, MarkdownService as T } from "@coinagerie/output";
13
+ import { VocabularyModule as E, VocabularyService as D } from "@coinagerie/vocabulary";
14
+ import { InvalidConfigurationError as O, MalformedGlossaryError as k } from "@coinagerie/core";
15
+ // \0rolldown/runtime.js
16
+ var A = /^(\p{Extended_Pictographic}️?(?:‍\p{Extended_Pictographic}️?)*)\s+/u, j = /^([A-Za-z]+)/, M = /* @__PURE__ */ new Set([
17
+ "built",
18
+ "cut",
19
+ "found",
20
+ "got",
21
+ "kept",
22
+ "left",
23
+ "lost",
24
+ "made",
25
+ "put",
26
+ "ran",
27
+ "read",
28
+ "rebuilt",
29
+ "sent",
30
+ "set",
31
+ "split",
32
+ "took",
33
+ "wrote"
34
+ ]), N = /* @__PURE__ */ new Set([
35
+ "CommandFactory",
36
+ "ExceptionHandler",
37
+ "GraphQLModule",
38
+ "InstanceLoader",
39
+ "NestApplication",
40
+ "NestFactory",
41
+ "RouterExplorer",
42
+ "RoutesResolver",
43
+ "TypeOrmModule"
44
+ ]);
45
+ // \0@oxc-project+runtime@0.155.0/helpers/esm/decorateMetadata.js
46
+ function __decorateMetadata(e, t) {
47
+ if (typeof Reflect == "object" && typeof Reflect.metadata == "function") return Reflect.metadata(e, t);
48
+ }
49
+ // \0@oxc-project+runtime@0.155.0/helpers/esm/decorate.js
50
+ function __decorate(e, t, n, r) {
51
+ var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
52
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
53
+ 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);
54
+ return i > 3 && a && Object.defineProperty(t, n, a), a;
55
+ }
56
+ // ../../../common/observability/src/modules/logger/logger.service.ts
57
+ var P, F = class LoggerService extends i {
58
+ static {
59
+ P = this;
60
+ }
61
+ constructor() {
62
+ super();
63
+ }
64
+ static isProduction = process.env.NODE_ENV === "production";
65
+ static rootLogger;
66
+ static writesToStandardError = !1;
67
+ child = P.root;
68
+ static createRootLogger() {
69
+ let e = process.env.LOG_LEVEL ?? "info";
70
+ return P.isProduction ? P.writesToStandardError ? f({ level: e }, f.destination(2)) : f({ level: e }) : f({
71
+ level: e,
72
+ transport: {
73
+ options: {
74
+ colorize: !0,
75
+ destination: P.writesToStandardError ? 2 : 1,
76
+ ignore: "pid,hostname,emoji",
77
+ messageFormat: "{emoji} {msg}",
78
+ singleLine: !0
79
+ },
80
+ target: "pino-pretty"
81
+ }
82
+ });
83
+ }
84
+ static logToStandardError() {
85
+ P.rootLogger === void 0 ? P.writesToStandardError = !0 : process.emitWarning("LoggerService.logToStandardError() was called after the first log line, so log lines still go to standard output and anything piping that stream will read them as data. Call it as the first statement of the application's bootstrap.");
86
+ }
87
+ assertConventionalMessage(e) {
88
+ if (P.isProduction || this.shouldSkipConventionalMessageValidation(e.context)) return;
89
+ let t = this.getConventionalMessageViolation(e.parsed);
90
+ if (t !== void 0) throw Error(t);
91
+ }
92
+ buildBindings(e) {
93
+ return this.assertConventionalMessage({
94
+ context: e.context,
95
+ parsed: e.parsed
96
+ }), {
97
+ ...e.data,
98
+ context: e.context,
99
+ ...P.isProduction ? {} : { emoji: e.parsed.emoji }
100
+ };
101
+ }
102
+ getConventionalMessageViolation(e) {
103
+ let t = e.emoji, n = e.text;
104
+ if (t === void 0) return `Log message must start with an emoji naming its subject, then a verb: "${n}"`;
105
+ let r = j.exec(n)?.[1];
106
+ if (r === void 0 || !this.isConventionalVerb(r)) return `Log message must begin with a verb in present progressive or past tense, got "${r ?? ""}": "${t} ${n}"`;
107
+ }
108
+ isConventionalVerb(e) {
109
+ let t = e.toLowerCase();
110
+ return t.endsWith("ing") || t.endsWith("ed") || M.has(t);
111
+ }
112
+ parseMessage(e) {
113
+ let t = String(e), n = A.exec(t), r = n?.[1];
114
+ return r === void 0 ? {
115
+ emoji: void 0,
116
+ text: t
117
+ } : {
118
+ emoji: r,
119
+ text: t.slice(n?.[0].length)
120
+ };
121
+ }
122
+ shouldSkipConventionalMessageValidation(e) {
123
+ return e !== void 0 && N.has(e);
124
+ }
125
+ static get root() {
126
+ return P.rootLogger ??= P.createRootLogger(), P.rootLogger;
127
+ }
128
+ buildErrorLogEntry(e, t) {
129
+ let n = t instanceof Error ? t.stack || t.message : String(t);
130
+ return {
131
+ errorMessage: n,
132
+ logLine: `[${(/* @__PURE__ */ new Date()).toISOString()}] ${e}: ${n}\n`
133
+ };
134
+ }
135
+ createTimestampedOutputLogFilePath(e) {
136
+ let t = d.join(process.cwd(), "output");
137
+ return l(t) || u(t, { recursive: !0 }), d.join(t, `${e}-${(/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g, "-")}.log`);
138
+ }
139
+ debug(e, t, n) {
140
+ let r = this.parseMessage(e);
141
+ this.child.debug(this.buildBindings({
142
+ context: t ?? this.context,
143
+ data: n,
144
+ parsed: r
145
+ }), r.text);
146
+ }
147
+ error(e, t, n) {
148
+ let r = this.parseMessage(e), i = typeof n == "object" ? n : void 0, a = typeof n == "string" ? n : this.context;
149
+ this.child.error({
150
+ ...this.buildBindings({
151
+ context: a,
152
+ data: i,
153
+ parsed: r
154
+ }),
155
+ stack: t
156
+ }, r.text);
157
+ }
158
+ info(e, t, n) {
159
+ let r = this.parseMessage(e);
160
+ this.child.info(this.buildBindings({
161
+ context: t ?? this.context,
162
+ data: n,
163
+ parsed: r
164
+ }), r.text);
165
+ }
166
+ log(e, t, n) {
167
+ this.info(e, t, n);
168
+ }
169
+ setContext(e) {
170
+ super.setContext(e), this.child = P.root.child({ context: e });
171
+ }
172
+ verbose(e, t, n) {
173
+ let r = this.parseMessage(e);
174
+ this.child.trace(this.buildBindings({
175
+ context: t ?? this.context,
176
+ data: n,
177
+ parsed: r
178
+ }), r.text);
179
+ }
180
+ warn(e, t, n) {
181
+ let r = this.parseMessage(e);
182
+ this.child.warn(this.buildBindings({
183
+ context: t ?? this.context,
184
+ data: n,
185
+ parsed: r
186
+ }), r.text);
187
+ }
188
+ };
189
+ F = P = __decorate([o({ scope: c.TRANSIENT }), __decorateMetadata("design:paramtypes", [])], F);
190
+ // ../../../common/observability/src/modules/logger/logger.module.ts
191
+ var I = class LoggerModule {};
192
+ I = __decorate([a(), s({
193
+ controllers: [],
194
+ exports: [F],
195
+ imports: [],
196
+ providers: [F]
197
+ })], I);
198
+ // src/coinagerie-cli.constants.ts
199
+ var L = h.object({}), R = ["markdown", "json"], z, B = z = class CollectCommand extends n {
200
+ configurationService;
201
+ vocabularyService;
202
+ comparisonService;
203
+ deliveryService;
204
+ jsonService;
205
+ markdownService;
206
+ logger;
207
+ 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);
209
+ }
210
+ check(e, t) {
211
+ let n = this.deliveryService.check({
212
+ destinations: e.outputs,
213
+ words: t
214
+ }).filter((e) => e.missing.length > 0 || e.stale.length > 0);
215
+ for (let { missing: e, path: t, stale: r } of n) this.fail("🪙 Found a glossary out of step with the code", {
216
+ missing: e,
217
+ path: t,
218
+ stale: r
219
+ });
220
+ n.length === 0 && this.logger.info("✅ Found every glossary in step with the code");
221
+ }
222
+ async collectWords(e) {
223
+ try {
224
+ return await this.vocabularyService.collect(e);
225
+ } catch (e) {
226
+ if (!(e instanceof O)) throw e;
227
+ this.fail("🪙 Rejected the configuration", { reason: e.message });
228
+ return;
229
+ }
230
+ }
231
+ deliver(e) {
232
+ if (e.configuration.outputs.length === 0) this.fail(`🪙 Found no glossary destination to ${e.mode}`, { configurationPath: e.configuration.configurationPath });
233
+ else try {
234
+ e.mode === "check" ? this.check(e.configuration, e.words) : this.write(e.configuration, e.words);
235
+ } catch (e) {
236
+ if (!(e instanceof k)) throw e;
237
+ this.fail("🪙 Refused a glossary it cannot parse", { reason: e.message });
238
+ }
239
+ }
240
+ fail(e, t) {
241
+ this.logger.error(e, void 0, t), process.exitCode = 1;
242
+ }
243
+ async loadConfiguration(e) {
244
+ try {
245
+ return await this.configurationService.loadConfiguration({
246
+ configurationPath: e.config,
247
+ overrides: this.overridesFrom(e),
248
+ workingDirectory: process.cwd()
249
+ });
250
+ } catch (e) {
251
+ this.fail("🪙 Rejected the configuration", { reason: String(e) });
252
+ return;
253
+ }
254
+ }
255
+ overridesFrom(e) {
256
+ return {
257
+ description: e.description,
258
+ excludePaths: e.excludePaths,
259
+ include: e.include,
260
+ outputJson: e.outputJson,
261
+ outputMarkdown: e.outputMarkdown
262
+ };
263
+ }
264
+ print(e, t) {
265
+ let n = this.comparisonService.reconcile(e, /* @__PURE__ */ new Map());
266
+ process.stdout.write(t === "json" ? this.jsonService.render(n) : `${this.markdownService.render({ glossary: n })}\n`);
267
+ }
268
+ rejectionOf(e) {
269
+ 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}"`;
271
+ }
272
+ selectMode(e) {
273
+ let t = this.rejectionOf(e);
274
+ if (t !== void 0) this.fail("🪙 Rejected the command line", { reason: t });
275
+ else return e.check === !0 ? "check" : e.write === !0 ? "write" : "print";
276
+ }
277
+ write(e, t) {
278
+ let n = this.deliveryService.write({
279
+ destinations: e.outputs,
280
+ words: t
281
+ });
282
+ for (let { missing: e, path: t, stale: r } of n.filter((e) => e.written)) this.logger.info("🪙 Wrote the glossary", void 0, {
283
+ added: e,
284
+ deleted: r,
285
+ path: t
286
+ });
287
+ }
288
+ parseCheck() {
289
+ return !0;
290
+ }
291
+ parseConfig(e) {
292
+ return e;
293
+ }
294
+ parseDescription(e) {
295
+ return e;
296
+ }
297
+ parseExcludePaths(e, t = []) {
298
+ return [...t, e];
299
+ }
300
+ parseFormat(e) {
301
+ return e;
302
+ }
303
+ parseInclude(e, t = []) {
304
+ return [...t, e];
305
+ }
306
+ parseOutputJson(e) {
307
+ return e;
308
+ }
309
+ parseOutputMarkdown(e) {
310
+ return e;
311
+ }
312
+ parseWrite() {
313
+ return !0;
314
+ }
315
+ async run(e, t = {}) {
316
+ let n = this.selectMode(t);
317
+ if (n === void 0) return;
318
+ let r = await this.loadConfiguration(t);
319
+ if (r === void 0) return;
320
+ let i = await this.collectWords(r);
321
+ i !== void 0 && (n === "print" ? this.print(i, t.format) : this.deliver({
322
+ configuration: r,
323
+ mode: n,
324
+ words: i
325
+ }));
326
+ }
327
+ };
328
+ __decorate([
329
+ r({
330
+ description: "Fail when a glossary's words disagree with the code's",
331
+ flags: "--check"
332
+ }),
333
+ __decorateMetadata("design:type", Function),
334
+ __decorateMetadata("design:paramtypes", []),
335
+ __decorateMetadata("design:returntype", Boolean)
336
+ ], B.prototype, "parseCheck", null), __decorate([
337
+ r({
338
+ description: "Path to a coinagerie configuration file; coinagerie.config.ts in the working directory is used when omitted",
339
+ flags: "--config <config>"
340
+ }),
341
+ __decorateMetadata("design:type", Function),
342
+ __decorateMetadata("design:paramtypes", [String]),
343
+ __decorateMetadata("design:returntype", String)
344
+ ], B.prototype, "parseConfig", null), __decorate([
345
+ r({
346
+ description: "Text rendered under the heading of every markdown destination, replacing the configured description",
347
+ flags: "--description <description>"
348
+ }),
349
+ __decorateMetadata("design:type", Function),
350
+ __decorateMetadata("design:paramtypes", [String]),
351
+ __decorateMetadata("design:returntype", String)
352
+ ], B.prototype, "parseDescription", null), __decorate([
353
+ r({
354
+ description: "Glob of files to leave out of the scan, replacing the configured exclude.paths; repeat for several",
355
+ flags: "--exclude-paths <glob>"
356
+ }),
357
+ __decorateMetadata("design:type", Function),
358
+ __decorateMetadata("design:paramtypes", [String, Array]),
359
+ __decorateMetadata("design:returntype", Array)
360
+ ], B.prototype, "parseExcludePaths", null), __decorate([
361
+ r({
362
+ description: `Format printed to standard output when neither --check nor --write is given: ${R.join(" or ")}`,
363
+ flags: "--format <format>"
364
+ }),
365
+ __decorateMetadata("design:type", Function),
366
+ __decorateMetadata("design:paramtypes", [String]),
367
+ __decorateMetadata("design:returntype", String)
368
+ ], B.prototype, "parseFormat", null), __decorate([
369
+ r({
370
+ description: "Glob of files to scan, replacing the configured include; repeat for several",
371
+ flags: "--include <glob>"
372
+ }),
373
+ __decorateMetadata("design:type", Function),
374
+ __decorateMetadata("design:paramtypes", [String, Array]),
375
+ __decorateMetadata("design:returntype", Array)
376
+ ], B.prototype, "parseInclude", null), __decorate([
377
+ r({
378
+ description: "JSON glossary to check or write, replacing the configured outputs",
379
+ flags: "--output-json <path>"
380
+ }),
381
+ __decorateMetadata("design:type", Function),
382
+ __decorateMetadata("design:paramtypes", [String]),
383
+ __decorateMetadata("design:returntype", String)
384
+ ], B.prototype, "parseOutputJson", null), __decorate([
385
+ r({
386
+ description: "Markdown file holding a glossary block to check or write, replacing the configured outputs",
387
+ flags: "--output-markdown <path>"
388
+ }),
389
+ __decorateMetadata("design:type", Function),
390
+ __decorateMetadata("design:paramtypes", [String]),
391
+ __decorateMetadata("design:returntype", String)
392
+ ], B.prototype, "parseOutputMarkdown", null), __decorate([
393
+ r({
394
+ description: "Rewrite every glossary to hold exactly the code's words, keeping definitions",
395
+ flags: "--write"
396
+ }),
397
+ __decorateMetadata("design:type", Function),
398
+ __decorateMetadata("design:paramtypes", []),
399
+ __decorateMetadata("design:returntype", Boolean)
400
+ ], B.prototype, "parseWrite", null), B = z = __decorate([
401
+ e({
402
+ description: "List the words the code uses, and check or write a glossary of them",
403
+ name: "collect",
404
+ options: { isDefault: !0 }
405
+ }),
406
+ o(),
407
+ __decorateMetadata("design:paramtypes", [
408
+ _ === void 0 ? Object : _,
409
+ D === void 0 ? Object : D,
410
+ y === void 0 ? Object : y,
411
+ x === void 0 ? Object : x,
412
+ C === void 0 ? Object : C,
413
+ T === void 0 ? Object : T,
414
+ F === void 0 ? Object : F
415
+ ])
416
+ ], B);
417
+ // src/modules/collect/collect.module.ts
418
+ var V = class CollectModule {};
419
+ V = __decorate([s({
420
+ controllers: [],
421
+ exports: [B],
422
+ imports: [
423
+ v,
424
+ g,
425
+ b,
426
+ S,
427
+ I,
428
+ w,
429
+ E
430
+ ],
431
+ providers: [B]
432
+ })], V);
433
+ // src/coinagerie-cli.module.ts
434
+ var H = class MainModule {};
435
+ H = __decorate([s({ imports: [
436
+ p.forRoot({
437
+ envFilePath: ".env",
438
+ isGlobal: !0,
439
+ validate: (e) => L.parse(e)
440
+ }),
441
+ m,
442
+ I,
443
+ V
444
+ ] })], H);
445
+ // src/coinagerie-cli.main.ts
446
+ async function main() {
447
+ F.logToStandardError();
448
+ let e = new F();
449
+ e.setContext("CommandFactory"), await t.run(H, {
450
+ bufferLogs: !0,
451
+ logger: e,
452
+ serviceErrorHandler: (t) => {
453
+ e.error(t.message, t.stack), process.exitCode = 1;
454
+ }
455
+ });
456
+ }
457
+ main();
@@ -0,0 +1 @@
1
+ export {}
File without changes
package/package.json CHANGED
@@ -1,6 +1,76 @@
1
1
  {
2
+ "author": "Jimmy Paolini",
3
+ "bin": {
4
+ "coinagerie": "./dist/src/coinagerie-cli.main.js"
5
+ },
6
+ "bugs": {
7
+ "url": "https://github.com/organizzolini/codebase/issues"
8
+ },
9
+ "dependencies": {
10
+ "@coinagerie/configuration": "0.0.2",
11
+ "@coinagerie/core": "0.0.2",
12
+ "@coinagerie/output": "0.0.2",
13
+ "@coinagerie/vocabulary": "0.0.2",
14
+ "@nestjs/common": "^11.1.21 || ^12.0.1",
15
+ "@nestjs/config": "^12.0.0",
16
+ "@nestjs/core": "^11.1.21 || ^12.0.1",
17
+ "nest-commander": "^3.21.0",
18
+ "pino": "^10.3.1",
19
+ "pino-pretty": "^13.1.3",
20
+ "reflect-metadata": "^0.2.2",
21
+ "zod": "^4.4.3"
22
+ },
23
+ "description": "Command-line tool that lists the vocabulary of a codebase and keeps a glossary of it in step with the code",
24
+ "devDependencies": {
25
+ "@codebase/observability": "0.0.1",
26
+ "@golevelup/ts-vitest": "^4.0.0",
27
+ "@nestjs/testing": "^12.0.1",
28
+ "@nx/eslint-plugin": "^24.0.0",
29
+ "@swc-node/register": "^1.11.1",
30
+ "@swc/core": "^1.15.40",
31
+ "@swc/helpers": "^0.5.21",
32
+ "@types/node": "^26.5.1",
33
+ "@vitest/coverage-v8": "^5.0.0",
34
+ "typescript": "^6.0.3",
35
+ "vitest": "^5.0.0"
36
+ },
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/src/index.d.ts",
40
+ "default": "./dist/src/index.js"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "files": [
45
+ "CHANGELOG.md",
46
+ "dist",
47
+ "LICENSE",
48
+ "README.md"
49
+ ],
50
+ "homepage": "https://github.com/organizzolini/codebase/tree/main/projects/ic-suite/coinagerie/coinagerie-cli#readme",
51
+ "keywords": [
52
+ "cli",
53
+ "coinagerie",
54
+ "glossary",
55
+ "vocabulary"
56
+ ],
57
+ "license": "MIT",
58
+ "main": "./dist/src/index.js",
2
59
  "name": "@coinagerie/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
60
+ "publishConfig": {
61
+ "access": "public",
62
+ "registry": "https://registry.npmjs.org"
63
+ },
64
+ "repository": {
65
+ "directory": "projects/ic-suite/coinagerie/coinagerie-cli",
66
+ "type": "git",
67
+ "url": "git+https://github.com/organizzolini/codebase.git"
68
+ },
69
+ "type": "module",
70
+ "typeCoverage": {
71
+ "atLeast": 100,
72
+ "strict": true
73
+ },
74
+ "types": "./dist/src/index.d.ts",
75
+ "version": "0.0.2"
6
76
  }