@coinagerie/cli 0.0.0-stage → 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/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ ## 0.0.1 (2026-11-04)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **coinagerie:** 📦️ publish coinagerie to npm ([#2088](https://github.com/organizzolini/codebase/pull/2088), [#1793](https://github.com/organizzolini/codebase/issues/1793))
6
+ - **configuration,coinagerie:** ✨ adopt coinagerie with a root glossary ([#1888](https://github.com/organizzolini/codebase/pull/1888), [#1785](https://github.com/organizzolini/codebase/issues/1785))
7
+ - **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))
8
+ - **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))
9
+ - **coinagerie:** ✨ fold word forms and exclude configured words ([#1882](https://github.com/organizzolini/codebase/pull/1882), [#1762](https://github.com/organizzolini/codebase/issues/1762))
10
+ - **coinagerie:** ✨ build a markdown glossary from typescript ([#1875](https://github.com/organizzolini/codebase/pull/1875), [#1755](https://github.com/organizzolini/codebase/issues/1755))
11
+
12
+ ### 🧱 Updated Dependencies
13
+
14
+ - Updated coinagerie-configuration to 0.0.1
15
+ - Updated coinagerie-vocabulary to 0.0.1
16
+ - Updated coinagerie-output to 0.0.1
17
+ - 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,603 @@
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
+ - **absolute**:
68
+ - **after**:
69
+ - **anchor**:
70
+ - **angle**:
71
+ - **answer**:
72
+ - **aspect**:
73
+ - **assertion**:
74
+ - **bootstrap**:
75
+ - **breadth**:
76
+ - **buffer**:
77
+ - **bug**:
78
+ - **bullet**:
79
+ - **call**:
80
+ - **clear**:
81
+ - **close**:
82
+ - **color**:
83
+ - **comparison**:
84
+ - **compile**:
85
+ - **compiler**:
86
+ - **console**:
87
+ - **constant**:
88
+ - **controller**:
89
+ - **decorator**:
90
+ - **define**:
91
+ - **deliver**:
92
+ - **delivery**:
93
+ - **describe**:
94
+ - **destination**:
95
+ - **difference**:
96
+ - **discovery**:
97
+ - **each**:
98
+ - **empty**:
99
+ - **encode**:
100
+ - **entry**:
101
+ - **equal**:
102
+ - **example**:
103
+ - **experimental**:
104
+ - **factory**:
105
+ - **failure**:
106
+ - **fake**:
107
+ - **field**:
108
+ - **fixture**:
109
+ - **flag**:
110
+ - **force**:
111
+ - **gitkeep**:
112
+ - **glossary**:
113
+ - **handler**:
114
+ - **homepage**:
115
+ - **implementation**:
116
+ - **injectable**:
117
+ - **inside**:
118
+ - **instance**:
119
+ - **invalid**:
120
+ - **least**:
121
+ - **leftover**:
122
+ - **length**:
123
+ - **load**:
124
+ - **logger**:
125
+ - **lunar**:
126
+ - **malformed**:
127
+ - **maximum**:
128
+ - **md**:
129
+ - **meta**:
130
+ - **miss**:
131
+ - **mkdtemp**:
132
+ - **mock**:
133
+ - **other**:
134
+ - **parameter**:
135
+ - **phase**:
136
+ - **polyglot**:
137
+ - **previous**:
138
+ - **promise**:
139
+ - **prototype**:
140
+ - **provide**:
141
+ - **publish**:
142
+ - **readdir**:
143
+ - **real**:
144
+ - **reason**:
145
+ - **reconcile**:
146
+ - **recursive**:
147
+ - **reject**:
148
+ - **rejection**:
149
+ - **relative**:
150
+ - **remove**:
151
+ - **resolution**:
152
+ - **rewrite**:
153
+ - **runner**:
154
+ - **scratch**:
155
+ - **sort**:
156
+ - **spawn**:
157
+ - **spy**:
158
+ - **stack**:
159
+ - **stale**:
160
+ - **stdout**:
161
+ - **strict**:
162
+ - **stringify**:
163
+ - **synthetic**:
164
+ - **timer**:
165
+ - **vanish**:
166
+ - **vi**:
167
+ - **vocabulary**:
168
+
169
+ <!-- coinagerie:end -->
170
+
171
+ <!-- callidescope:start -->
172
+
173
+ ## 🔭 Callidescope
174
+
175
+ 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.
176
+
177
+ | Measure | Value |
178
+ | --- | --- |
179
+ | Callables | 27 |
180
+ | Files | 16 |
181
+ | Calls traced | 24 |
182
+ | Call stacks | 1 |
183
+ | Deepest stack | 13 |
184
+ | Stacks through recursion | 0 |
185
+ | Unfollowable calls | 1 |
186
+
187
+ ### Limits
188
+
189
+ What this project is judged against, as declared in its own `callidescope.config.ts`.
190
+
191
+ | Limit | Value |
192
+ | --- | --- |
193
+ | `maximumDepth` | 13 |
194
+ | `maximumBreadth` | 5 |
195
+
196
+ ### Call stacks (depth)
197
+
198
+ **1. `CollectCommand.run`** — depth ≥ 13 · decorated-method
199
+
200
+ ```text
201
+ 🚀 CollectCommand.run(_passedParameters: string[], options?: CollectCommandOptions): Promise<void> [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:335]
202
+ ↳ Collects the vocabulary and prints, checks, or writes it.
203
+ └─> CollectCommand.deliver(…): void [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:113]
204
+ ↳ Checks or writes, refusing a glossary that cannot be parsed.
205
+ └─> CollectCommand.check(configuration: ResolvedCoinagerieConfiguration, words: string[]): void [projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:67]
206
+ ↳ Checks every destination, failing the run when any disagrees.
207
+ └─> DeliveryService.check(args: DeliverArguments): GlossaryDifference[] [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:102]
208
+ ↳ How each destination differs from the vocabulary, writing nothing.
209
+ └─> DeliveryService.readAll(destinations: ResolvedCoinagerieOutput[]): ReadDestination[] [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:83]
210
+ ↳ Reads and parses every destination, throwing before anything is written.
211
+ └─> DeliveryService.map(…)(…): { content: string | undefined; destination: ResolvedCoinagerieOutput; glossary: Glossary; } [projects/ic-suite/coinagerie/coinagerie-output/src/modules/delivery/delivery.service.ts:84]
212
+ └─> MarkdownService.read(content: string | undefined, filePath: string): Glossary | undefined [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:237]
213
+ ↳ Reads a destination's glossary; a missing file holds none.
214
+ └─> MarkdownService.parse(content: string, filePath: string): Glossary | undefined [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:212]
215
+ ↳ The glossary in a file's block, or `undefined` when it has no anchors.
216
+ └─> MarkdownService.forEach(…)(text: string, index: number): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:228]
217
+ └─> MarkdownService.readLine(state: BlockParserState, text: string, line: number): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:173]
218
+ ↳ Reads one line of the block, or refuses it.
219
+ └─> MarkdownService.readBullet(…): void [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:110]
220
+ ↳ Reads one bullet, starting a new word.
221
+ └─> MarkdownService.fail(state: Pick<BlockParserState, "filePath">, line: number, reason: string): never [projects/ic-suite/coinagerie/coinagerie-output/src/modules/markdown/markdown.service.ts:50]
222
+ ↳ Fails a parse, naming the file and the one-indexed line.
223
+ └─> MalformedGlossaryError.constructor(location: MalformedGlossaryLocation): MalformedGlossaryError [projects/ic-suite/coinagerie/coinagerie-core/src/modules/coinagerie-core/coinagerie-core.constants.ts:47]
224
+ ```
225
+
226
+ ### Breadth
227
+
228
+ | Callable | Breadth | Calls directly | Location |
229
+ | --- | --- | --- | --- |
230
+ | `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` |
231
+ | `CollectCommand.check` | 3 | `CollectCommand.filter(…)`, `DeliveryService.check`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:67` |
232
+ | `CollectCommand.deliver` | 3 | `CollectCommand.fail`, `CollectCommand.check`, `CollectCommand.write` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:113` |
233
+
234
+ <details>
235
+ <summary>5 more callables</summary>
236
+
237
+ | Callable | Breadth | Calls directly | Location |
238
+ | --- | --- | --- | --- |
239
+ | `CollectCommand.loadConfiguration` | 3 | `ConfigurationService.loadConfiguration`, `CollectCommand.overridesFrom`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:149` |
240
+ | `CollectCommand.print` | 3 | `ComparisonService.reconcile`, `JsonService.render`, `MarkdownService.render` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:181` |
241
+ | `CollectCommand.collectWords` | 2 | `VocabularyService.collect`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:97` |
242
+ | `CollectCommand.selectMode` | 2 | `CollectCommand.rejectionOf`, `CollectCommand.fail` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:208` |
243
+ | `CollectCommand.write` | 2 | `DeliveryService.write`, `CollectCommand.filter(…)` | `projects/ic-suite/coinagerie/coinagerie-cli/src/modules/collect/collect.command.ts:224` |
244
+
245
+ </details>
246
+ <!-- callidescope:end -->
247
+
248
+ ## 🕸️ Codependix
249
+
250
+ 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`.
251
+
252
+ ### Nx Neighborhood
253
+
254
+ <!-- codependix:start name="codependix-nx-projects" -->
255
+ ```mermaid
256
+ graph LR
257
+ coinagerie_cli["coinagerie-cli"]
258
+ coinagerie_configuration["coinagerie-configuration"]
259
+ coinagerie_core["coinagerie-core"]
260
+ coinagerie_examples["coinagerie-examples"]
261
+ coinagerie_output["coinagerie-output"]
262
+ coinagerie_vocabulary["coinagerie-vocabulary"]
263
+ observability["observability"]
264
+ coinagerie_cli --> coinagerie_configuration
265
+ coinagerie_cli --> coinagerie_core
266
+ coinagerie_cli --> coinagerie_output
267
+ coinagerie_cli --> coinagerie_vocabulary
268
+ coinagerie_cli --> observability
269
+ coinagerie_examples -.-> coinagerie_cli
270
+ classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
271
+ class coinagerie_cli subject
272
+ ```
273
+
274
+ _Dashed edges are dependencies Nx inferred from configuration rather than from code._
275
+ <!-- codependix:end name="codependix-nx-projects" -->
276
+
277
+ ### NestJS Module Graph
278
+
279
+ <!-- codependix:start name="codependix-nestjs-modules" -->
280
+ ```mermaid
281
+ flowchart LR
282
+ CollectModule
283
+ ComparisonModule
284
+ ConfigModule([ConfigModule])
285
+ ConfigurationModule
286
+ CssModule
287
+ DeliveryModule
288
+ DiscoveryModule
289
+ FoldingModule
290
+ HclModule
291
+ JsonModule
292
+ LanguagesModule
293
+ LoggerModule([LoggerModule])
294
+ MainModule
295
+ MarkdownModule
296
+ PythonModule
297
+ ScannerModule
298
+ ShellModule
299
+ SqlModule
300
+ TomlModule
301
+ TypescriptModule
302
+ VocabularyModule
303
+ WordsModule
304
+ YamlModule
305
+ CollectModule --> ComparisonModule
306
+ CollectModule --> ConfigurationModule
307
+ CollectModule --> DeliveryModule
308
+ CollectModule --> JsonModule
309
+ CollectModule --> MarkdownModule
310
+ CollectModule --> VocabularyModule
311
+ CssModule --> ScannerModule
312
+ DeliveryModule --> ComparisonModule
313
+ DeliveryModule --> JsonModule
314
+ DeliveryModule --> MarkdownModule
315
+ HclModule --> ScannerModule
316
+ JsonModule --> ScannerModule
317
+ LanguagesModule --> CssModule
318
+ LanguagesModule --> HclModule
319
+ LanguagesModule --> JsonModule
320
+ LanguagesModule --> PythonModule
321
+ LanguagesModule --> ShellModule
322
+ LanguagesModule --> SqlModule
323
+ LanguagesModule --> TomlModule
324
+ LanguagesModule --> TypescriptModule
325
+ LanguagesModule --> YamlModule
326
+ MainModule --> CollectModule
327
+ MainModule --> DiscoveryModule
328
+ PythonModule --> ScannerModule
329
+ ShellModule --> ScannerModule
330
+ SqlModule --> ScannerModule
331
+ TomlModule --> ScannerModule
332
+ VocabularyModule --> DiscoveryModule
333
+ VocabularyModule --> FoldingModule
334
+ VocabularyModule --> LanguagesModule
335
+ VocabularyModule --> WordsModule
336
+ ```
337
+
338
+ _Rounded modules are global: every module can inject them, so their edges are left out._
339
+ <!-- codependix:end name="codependix-nestjs-modules" -->
340
+
341
+ ### File Imports
342
+
343
+ <!-- codependix:start name="codependix-file-imports" -->
344
+ ```mermaid
345
+ graph LR
346
+ file_callidescope_config_ts["callidescope.config.ts"]
347
+ file_codependix_config_ts["codependix.config.ts"]
348
+ file_codometer_config_ts["codometer.config.ts"]
349
+ file_coinagerie_config_ts["coinagerie.config.ts"]
350
+ file_eslint_config_ts["eslint.config.ts"]
351
+ file_src_coinagerie_cli_constants_ts["src/coinagerie-cli.constants.ts"]
352
+ file_src_coinagerie_cli_main_end_to_end_test_ts["src/coinagerie-cli.main.end-to-end.test.ts"]
353
+ file_src_coinagerie_cli_main_ts["src/coinagerie-cli.main.ts"]
354
+ file_src_coinagerie_cli_module_ts["src/coinagerie-cli.module.ts"]
355
+ file_src_coinagerie_cli_module_unit_test_ts["src/coinagerie-cli.module.unit.test.ts"]
356
+ file_src_coinagerie_cli_repl_ts["src/coinagerie-cli.repl.ts"]
357
+ file_src_coinagerie_cli_repl_unit_test_ts["src/coinagerie-cli.repl.unit.test.ts"]
358
+ file_src_index_ts["src/index.ts"]
359
+ file_src_modules_collect_collect_command_end_to_end_test_ts["src/modules/collect/collect.command.end-to-end.test.ts"]
360
+ file_src_modules_collect_collect_command_ts["src/modules/collect/collect.command.ts"]
361
+ file_src_modules_collect_collect_command_unit_test_ts["src/modules/collect/collect.command.unit.test.ts"]
362
+ file_src_modules_collect_collect_constants_ts["src/modules/collect/collect.constants.ts"]
363
+ file_src_modules_collect_collect_module_ts["src/modules/collect/collect.module.ts"]
364
+ file_src_modules_collect_collect_types_ts["src/modules/collect/collect.types.ts"]
365
+ file_testing_examples_ts["testing/examples.ts"]
366
+ file_testing_fixture_tree_ts["testing/fixture-tree.ts"]
367
+ file_testing_mocks_ts["testing/mocks.ts"]
368
+ file_testing_run_command_ts["testing/run-command.ts"]
369
+ file_testing_setup_ts["testing/setup.ts"]
370
+ file_vite_config_ts["vite.config.ts"]
371
+ file_vitest_config_ts["vitest.config.ts"]
372
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_src_coinagerie_cli_constants_ts
373
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_examples_ts
374
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_fixture_tree_ts
375
+ file_src_coinagerie_cli_main_end_to_end_test_ts --> file_testing_run_command_ts
376
+ file_src_coinagerie_cli_main_ts --> file_src_coinagerie_cli_module_ts
377
+ file_src_coinagerie_cli_module_ts --> file_src_coinagerie_cli_constants_ts
378
+ file_src_coinagerie_cli_module_ts --> file_src_modules_collect_collect_module_ts
379
+ file_src_coinagerie_cli_module_unit_test_ts --> file_src_coinagerie_cli_module_ts
380
+ file_src_coinagerie_cli_repl_ts --> file_src_coinagerie_cli_module_ts
381
+ file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_examples_ts
382
+ file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_fixture_tree_ts
383
+ file_src_modules_collect_collect_command_end_to_end_test_ts --> file_testing_run_command_ts
384
+ file_src_modules_collect_collect_command_ts --> file_src_modules_collect_collect_constants_ts
385
+ file_src_modules_collect_collect_command_ts --> file_src_modules_collect_collect_types_ts
386
+ file_src_modules_collect_collect_command_unit_test_ts --> file_src_modules_collect_collect_command_ts
387
+ file_src_modules_collect_collect_command_unit_test_ts --> file_src_modules_collect_collect_types_ts
388
+ file_src_modules_collect_collect_command_unit_test_ts --> file_testing_fixture_tree_ts
389
+ file_src_modules_collect_collect_module_ts --> file_src_modules_collect_collect_command_ts
390
+ ```
391
+ <!-- codependix:end name="codependix-file-imports" -->
392
+
393
+ <!-- codometer:start -->
394
+
395
+ ## ⏲️ Codometer
396
+
397
+ ### Project
398
+
399
+ ![Lines of Code](https://img.shields.io/badge/Lines_of_Code-1800-22c55e?style=flat-square)
400
+ ![Repository Size](https://img.shields.io/badge/Repository_Size-67.38_kB-6b7280?style=flat-square)
401
+ ![Folders](https://img.shields.io/badge/Folders-4-4a4a4a?style=flat-square)
402
+ ![Source Files](https://img.shields.io/badge/Source_Files-26-3178c6?style=flat-square)
403
+
404
+ ### TypeScript
405
+
406
+ ![TypeScript Files](https://img.shields.io/badge/TypeScript_Files-26-3178c6?style=flat-square)
407
+ ![Interfaces](https://img.shields.io/badge/Interfaces-2-0ea5e9?style=flat-square)
408
+ ![Generic Declarations](https://img.shields.io/badge/Generic_Declarations-0-0369a1?style=flat-square)
409
+ ![Enums](https://img.shields.io/badge/Enums-0-f97316?style=flat-square)
410
+ ![Decorators](https://img.shields.io/badge/Decorators-13-db2777?style=flat-square)
411
+ ![Doc Comments](https://img.shields.io/badge/Doc_Comments-38-6366f1?style=flat-square)
412
+ ![Static Methods](https://img.shields.io/badge/Static_Methods-0-166534?style=flat-square)
413
+
414
+ ### JavaScript
415
+
416
+ ![JavaScript Files](https://img.shields.io/badge/JavaScript_Files-0-f7df1e?style=flat-square)
417
+ ![Test Files](https://img.shields.io/badge/Test_Files-5-10b981?style=flat-square)
418
+ ![External Packages](https://img.shields.io/badge/External_Packages-18-8b5cf6?style=flat-square)
419
+ ![Classes](https://img.shields.io/badge/Classes-3-7c3aed?style=flat-square)
420
+ ![Functions](https://img.shields.io/badge/Functions-84-16a34a?style=flat-square)
421
+ ![Methods](https://img.shields.io/badge/Methods-23-15803d?style=flat-square)
422
+ ![Sync Functions](https://img.shields.io/badge/Sync_Functions-87-4ade80?style=flat-square)
423
+ ![Async Functions](https://img.shields.io/badge/Async_Functions-20-059669?style=flat-square)
424
+ ![Constants](https://img.shields.io/badge/Constants-100-dc2626?style=flat-square)
425
+ ![Imports](https://img.shields.io/badge/Imports-79-0284c7?style=flat-square)
426
+ ![Exported Symbols](https://img.shields.io/badge/Exported_Symbols-16-ea580c?style=flat-square)
427
+ ![Comments](https://img.shields.io/badge/Comments-56-64748b?style=flat-square)
428
+ ![Comment Lines](https://img.shields.io/badge/Comment_Lines-135-475569?style=flat-square)
429
+ ![TODO Comments](https://img.shields.io/badge/TODO_Comments-0-ca8a04?style=flat-square)
430
+
431
+ ### Python
432
+
433
+ ![Python Files](https://img.shields.io/badge/Python_Files-0-3776ab?style=flat-square)
434
+ ![Python Lines](https://img.shields.io/badge/Python_Lines-0-4b8bbe?style=flat-square)
435
+ ![Python Classes](https://img.shields.io/badge/Python_Classes-0-7c3aed?style=flat-square)
436
+ ![Python Functions](https://img.shields.io/badge/Python_Functions-0-16a34a?style=flat-square)
437
+ ![Python Protocols](https://img.shields.io/badge/Python_Protocols-0-0ea5e9?style=flat-square)
438
+ ![Python Constants](https://img.shields.io/badge/Python_Constants-0-dc2626?style=flat-square)
439
+ ![Python Imports](https://img.shields.io/badge/Python_Imports-0-0284c7?style=flat-square)
440
+ ![Python Decorators](https://img.shields.io/badge/Python_Decorators-0-db2777?style=flat-square)
441
+ ![Docstrings](https://img.shields.io/badge/Docstrings-0-6366f1?style=flat-square)
442
+ ![Docstring Lines](https://img.shields.io/badge/Docstring_Lines-0-818cf8?style=flat-square)
443
+ ![Python Comments](https://img.shields.io/badge/Python_Comments-0-64748b?style=flat-square)
444
+ ![Python Comment Lines](https://img.shields.io/badge/Python_Comment_Lines-0-475569?style=flat-square)
445
+
446
+ ### JSON
447
+
448
+ ![JSON Files](https://img.shields.io/badge/JSON_Files-4-a16207?style=flat-square)
449
+ ![JSON Lines](https://img.shields.io/badge/JSON_Lines-195-ca8a04?style=flat-square)
450
+ ![JSON Objects](https://img.shields.io/badge/JSON_Objects-44-7c3aed?style=flat-square)
451
+ ![JSON Arrays](https://img.shields.io/badge/JSON_Arrays-14-8b5cf6?style=flat-square)
452
+ ![JSON Properties](https://img.shields.io/badge/JSON_Properties-121-0284c7?style=flat-square)
453
+ ![JSON Strings](https://img.shields.io/badge/JSON_Strings-107-16a34a?style=flat-square)
454
+ ![JSON Numbers](https://img.shields.io/badge/JSON_Numbers-1-059669?style=flat-square)
455
+ ![JSON Booleans](https://img.shields.io/badge/JSON_Booleans-7-0ea5e9?style=flat-square)
456
+ ![JSON Nulls](https://img.shields.io/badge/JSON_Nulls-0-64748b?style=flat-square)
457
+ ![JSON Items](https://img.shields.io/badge/JSON_Items-48-475569?style=flat-square)
458
+ ![JSON Nodes](https://img.shields.io/badge/JSON_Nodes-173-dc2626?style=flat-square)
459
+ ![JSON Max Depth](https://img.shields.io/badge/JSON_Max_Depth-7-ea580c?style=flat-square)
460
+
461
+ ### YAML
462
+
463
+ ![YAML Files](https://img.shields.io/badge/YAML_Files-0-cb171e?style=flat-square)
464
+ ![YAML Lines](https://img.shields.io/badge/YAML_Lines-0-e34c26?style=flat-square)
465
+ ![YAML Documents](https://img.shields.io/badge/YAML_Documents-0-f97316?style=flat-square)
466
+ ![YAML Mappings](https://img.shields.io/badge/YAML_Mappings-0-7c3aed?style=flat-square)
467
+ ![YAML Sequences](https://img.shields.io/badge/YAML_Sequences-0-8b5cf6?style=flat-square)
468
+ ![YAML Keys](https://img.shields.io/badge/YAML_Keys-0-0284c7?style=flat-square)
469
+ ![YAML Scalars](https://img.shields.io/badge/YAML_Scalars-0-16a34a?style=flat-square)
470
+ ![YAML Anchors](https://img.shields.io/badge/YAML_Anchors-0-059669?style=flat-square)
471
+ ![YAML Aliases](https://img.shields.io/badge/YAML_Aliases-0-10b981?style=flat-square)
472
+ ![YAML Comments](https://img.shields.io/badge/YAML_Comments-0-64748b?style=flat-square)
473
+ ![YAML Max Depth](https://img.shields.io/badge/YAML_Max_Depth-0-ea580c?style=flat-square)
474
+
475
+ ### TOML
476
+
477
+ ![TOML Files](https://img.shields.io/badge/TOML_Files-0-9c4221?style=flat-square)
478
+ ![TOML Lines](https://img.shields.io/badge/TOML_Lines-0-b45309?style=flat-square)
479
+ ![TOML Tables](https://img.shields.io/badge/TOML_Tables-0-7c3aed?style=flat-square)
480
+ ![TOML Array Tables](https://img.shields.io/badge/TOML_Array_Tables-0-8b5cf6?style=flat-square)
481
+ ![TOML Keys](https://img.shields.io/badge/TOML_Keys-0-0284c7?style=flat-square)
482
+ ![TOML Arrays](https://img.shields.io/badge/TOML_Arrays-0-16a34a?style=flat-square)
483
+ ![TOML Comments](https://img.shields.io/badge/TOML_Comments-0-64748b?style=flat-square)
484
+
485
+ ### Shell
486
+
487
+ ![Shell Files](https://img.shields.io/badge/Shell_Files-0-89e051?style=flat-square)
488
+ ![Shell Lines](https://img.shields.io/badge/Shell_Lines-0-4eaa25?style=flat-square)
489
+ ![Shell Functions](https://img.shields.io/badge/Shell_Functions-0-16a34a?style=flat-square)
490
+ ![Shell Variables](https://img.shields.io/badge/Shell_Variables-0-0284c7?style=flat-square)
491
+ ![Shell Exports](https://img.shields.io/badge/Shell_Exports-0-ea580c?style=flat-square)
492
+ ![Shell Conditionals](https://img.shields.io/badge/Shell_Conditionals-0-7c3aed?style=flat-square)
493
+ ![Shell Loops](https://img.shields.io/badge/Shell_Loops-0-8b5cf6?style=flat-square)
494
+ ![Shell Pipelines](https://img.shields.io/badge/Shell_Pipelines-0-059669?style=flat-square)
495
+ ![Shebangs](https://img.shields.io/badge/Shebangs-0-6b7280?style=flat-square)
496
+ ![Shell Comments](https://img.shields.io/badge/Shell_Comments-0-64748b?style=flat-square)
497
+ ![Shell Comment Lines](https://img.shields.io/badge/Shell_Comment_Lines-0-475569?style=flat-square)
498
+
499
+ ### SQL
500
+
501
+ ![SQL Files](https://img.shields.io/badge/SQL_Files-0-e38c00?style=flat-square)
502
+ ![SQL Lines](https://img.shields.io/badge/SQL_Lines-0-f29111?style=flat-square)
503
+ ![SQL Statements](https://img.shields.io/badge/SQL_Statements-0-7c3aed?style=flat-square)
504
+ ![SQL Selects](https://img.shields.io/badge/SQL_Selects-0-16a34a?style=flat-square)
505
+ ![SQL Inserts](https://img.shields.io/badge/SQL_Inserts-0-22c55e?style=flat-square)
506
+ ![SQL Updates](https://img.shields.io/badge/SQL_Updates-0-0ea5e9?style=flat-square)
507
+ ![SQL Deletes](https://img.shields.io/badge/SQL_Deletes-0-dc2626?style=flat-square)
508
+ ![SQL Creates](https://img.shields.io/badge/SQL_Creates-0-0284c7?style=flat-square)
509
+ ![SQL Joins](https://img.shields.io/badge/SQL_Joins-0-8b5cf6?style=flat-square)
510
+ ![SQL CTEs](https://img.shields.io/badge/SQL_CTEs-0-059669?style=flat-square)
511
+ ![SQL Comments](https://img.shields.io/badge/SQL_Comments-0-64748b?style=flat-square)
512
+
513
+ ### HCL
514
+
515
+ ![HCL Files](https://img.shields.io/badge/HCL_Files-0-844fba?style=flat-square)
516
+ ![HCL Lines](https://img.shields.io/badge/HCL_Lines-0-a78bfa?style=flat-square)
517
+ ![HCL Blocks](https://img.shields.io/badge/HCL_Blocks-0-7c3aed?style=flat-square)
518
+ ![HCL Resources](https://img.shields.io/badge/HCL_Resources-0-0284c7?style=flat-square)
519
+ ![HCL Variables](https://img.shields.io/badge/HCL_Variables-0-16a34a?style=flat-square)
520
+ ![HCL Outputs](https://img.shields.io/badge/HCL_Outputs-0-059669?style=flat-square)
521
+ ![HCL Attributes](https://img.shields.io/badge/HCL_Attributes-0-0ea5e9?style=flat-square)
522
+ ![HCL Interpolations](https://img.shields.io/badge/HCL_Interpolations-0-db2777?style=flat-square)
523
+ ![HCL Comments](https://img.shields.io/badge/HCL_Comments-0-64748b?style=flat-square)
524
+
525
+ ### CSS
526
+
527
+ ![CSS Files](https://img.shields.io/badge/CSS_Files-0-264de4?style=flat-square)
528
+ ![CSS Lines](https://img.shields.io/badge/CSS_Lines-0-2965f1?style=flat-square)
529
+ ![CSS Rules](https://img.shields.io/badge/CSS_Rules-0-7c3aed?style=flat-square)
530
+ ![CSS Selectors](https://img.shields.io/badge/CSS_Selectors-0-8b5cf6?style=flat-square)
531
+ ![CSS Declarations](https://img.shields.io/badge/CSS_Declarations-0-0284c7?style=flat-square)
532
+ ![CSS At Rules](https://img.shields.io/badge/CSS_At_Rules-0-f97316?style=flat-square)
533
+ ![CSS Media Queries](https://img.shields.io/badge/CSS_Media_Queries-0-ea580c?style=flat-square)
534
+ ![CSS Custom Properties](https://img.shields.io/badge/CSS_Custom_Properties-0-16a34a?style=flat-square)
535
+ ![CSS Comments](https://img.shields.io/badge/CSS_Comments-0-64748b?style=flat-square)
536
+
537
+ ### Conventions
538
+
539
+ ![Module Files](https://img.shields.io/badge/Module_Files-2-7c3aed?style=flat-square)
540
+ ![Service Files](https://img.shields.io/badge/Service_Files-0-0284c7?style=flat-square)
541
+ ![Command Files](https://img.shields.io/badge/Command_Files-1-16a34a?style=flat-square)
542
+ ![Constants Files](https://img.shields.io/badge/Constants_Files-2-ea580c?style=flat-square)
543
+ ![Types Files](https://img.shields.io/badge/Types_Files-1-db2777?style=flat-square)
544
+ ![Utilities Files](https://img.shields.io/badge/Utilities_Files-0-0ea5e9?style=flat-square)
545
+ ![TypeORM Entities](https://img.shields.io/badge/TypeORM_Entities-0-059669?style=flat-square)
546
+ ![Unit Tests](https://img.shields.io/badge/Unit_Tests-3-ca8a04?style=flat-square)
547
+ ![Integration Tests](https://img.shields.io/badge/Integration_Tests-0-7c3aed?style=flat-square)
548
+ ![End To End Tests](https://img.shields.io/badge/End_To_End_Tests-2-0284c7?style=flat-square)
549
+ ![CSS Comment Budget](https://img.shields.io/badge/CSS_Comment_Budget-0-16a34a?style=flat-square)
550
+ ![HCL Comment Budget](https://img.shields.io/badge/HCL_Comment_Budget-0-ea580c?style=flat-square)
551
+ ![Python Comment Budget](https://img.shields.io/badge/Python_Comment_Budget-0-db2777?style=flat-square)
552
+ ![SQL Comment Budget](https://img.shields.io/badge/SQL_Comment_Budget-0-0ea5e9?style=flat-square)
553
+ ![TOML Comment Budget](https://img.shields.io/badge/TOML_Comment_Budget-0-059669?style=flat-square)
554
+ ![TypeScript Comment Budget](https://img.shields.io/badge/TypeScript_Comment_Budget-0-ca8a04?style=flat-square)
555
+ ![YAML Comment Budget](https://img.shields.io/badge/YAML_Comment_Budget-0-7c3aed?style=flat-square)
556
+ ![Shell Comment Budget](https://img.shields.io/badge/Shell_Comment_Budget-0-0284c7?style=flat-square)
557
+
558
+ ### Jupyter
559
+
560
+ ![Notebooks](https://img.shields.io/badge/Notebooks-0-f37626?style=flat-square)
561
+ ![Notebook Cells](https://img.shields.io/badge/Notebook_Cells-0-e8a33d?style=flat-square)
562
+ ![Code Cells](https://img.shields.io/badge/Code_Cells-0-3776ab?style=flat-square)
563
+ ![Markdown Cells](https://img.shields.io/badge/Markdown_Cells-0-083fa1?style=flat-square)
564
+ ![Raw Cells](https://img.shields.io/badge/Raw_Cells-0-9ca3af?style=flat-square)
565
+ ![Executed Cells](https://img.shields.io/badge/Executed_Cells-0-16a34a?style=flat-square)
566
+ ![Cell Outputs](https://img.shields.io/badge/Cell_Outputs-0-059669?style=flat-square)
567
+ ![Notebook Code Lines](https://img.shields.io/badge/Notebook_Code_Lines-0-4b8bbe?style=flat-square)
568
+ ![Notebook Classes](https://img.shields.io/badge/Notebook_Classes-0-7c3aed?style=flat-square)
569
+ ![Notebook Functions](https://img.shields.io/badge/Notebook_Functions-0-22c55e?style=flat-square)
570
+ ![Notebook Imports](https://img.shields.io/badge/Notebook_Imports-0-0284c7?style=flat-square)
571
+ ![Notebook Decorators](https://img.shields.io/badge/Notebook_Decorators-0-db2777?style=flat-square)
572
+ ![Notebook Prose Lines](https://img.shields.io/badge/Notebook_Prose_Lines-0-1f6feb?style=flat-square)
573
+ ![Notebook Headings](https://img.shields.io/badge/Notebook_Headings-0-a78bfa?style=flat-square)
574
+ ![Notebook Links](https://img.shields.io/badge/Notebook_Links-0-10b981?style=flat-square)
575
+ ![Notebook Images](https://img.shields.io/badge/Notebook_Images-0-34d399?style=flat-square)
576
+ ![Notebook Code Blocks](https://img.shields.io/badge/Notebook_Code_Blocks-0-dc2626?style=flat-square)
577
+ ![Notebook Properties](https://img.shields.io/badge/Notebook_Properties-0-ca8a04?style=flat-square)
578
+ ![Notebook Nodes](https://img.shields.io/badge/Notebook_Nodes-0-a16207?style=flat-square)
579
+ ![Notebook Max Depth](https://img.shields.io/badge/Notebook_Max_Depth-0-ea580c?style=flat-square)
580
+
581
+ ### Markdown
582
+
583
+ ![Markdown Files](https://img.shields.io/badge/Markdown_Files-2-083fa1?style=flat-square)
584
+ ![Markdown Lines](https://img.shields.io/badge/Markdown_Lines-264-1f6feb?style=flat-square)
585
+ ![H1](https://img.shields.io/badge/H1-1-7c3aed?style=flat-square)
586
+ ![H2](https://img.shields.io/badge/H2-8-8b5cf6?style=flat-square)
587
+ ![H3](https://img.shields.io/badge/H3-16-a78bfa?style=flat-square)
588
+ ![H4](https://img.shields.io/badge/H4-0-c4b5fd?style=flat-square)
589
+ ![H5](https://img.shields.io/badge/H5-0-ddd6fe?style=flat-square)
590
+ ![H6](https://img.shields.io/badge/H6-0-ede9fe?style=flat-square)
591
+ ![Paragraphs](https://img.shields.io/badge/Paragraphs-59-64748b?style=flat-square)
592
+ ![Lists](https://img.shields.io/badge/Lists-8-16a34a?style=flat-square)
593
+ ![List Items](https://img.shields.io/badge/List_Items-38-22c55e?style=flat-square)
594
+ ![Task List Items](https://img.shields.io/badge/Task_List_Items-0-4ade80?style=flat-square)
595
+ ![Tables](https://img.shields.io/badge/Tables-2-0284c7?style=flat-square)
596
+ ![Table Rows](https://img.shields.io/badge/Table_Rows-10-0ea5e9?style=flat-square)
597
+ ![Links](https://img.shields.io/badge/Links-21-059669?style=flat-square)
598
+ ![Images](https://img.shields.io/badge/Images-0-10b981?style=flat-square)
599
+ ![Code Blocks](https://img.shields.io/badge/Code_Blocks-13-dc2626?style=flat-square)
600
+ ![Inline Code](https://img.shields.io/badge/Inline_Code-78-ef4444?style=flat-square)
601
+ ![Block Quotes](https://img.shields.io/badge/Block_Quotes-0-ca8a04?style=flat-square)
602
+ ![Thematic Breaks](https://img.shields.io/badge/Thematic_Breaks-0-a16207?style=flat-square)
603
+ <!-- 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.1",
11
+ "@coinagerie/core": "0.0.1",
12
+ "@coinagerie/output": "0.0.1",
13
+ "@coinagerie/vocabulary": "0.0.1",
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.1"
6
76
  }