@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 +17 -0
- package/LICENSE +21 -0
- package/README.md +602 -2
- package/dist/src/coinagerie-cli.main.d.ts +1 -0
- package/dist/src/coinagerie-cli.main.js +457 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +0 -0
- package/package.json +73 -3
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
|
-
#
|
|
1
|
+
# @coinagerie/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](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
|
+

|
|
400
|
+

|
|
401
|
+

|
|
402
|
+

|
|
403
|
+
|
|
404
|
+
### TypeScript
|
|
405
|
+
|
|
406
|
+

|
|
407
|
+

|
|
408
|
+

|
|
409
|
+

|
|
410
|
+

|
|
411
|
+

|
|
412
|
+

|
|
413
|
+
|
|
414
|
+
### JavaScript
|
|
415
|
+
|
|
416
|
+

|
|
417
|
+

|
|
418
|
+

|
|
419
|
+

|
|
420
|
+

|
|
421
|
+

|
|
422
|
+

|
|
423
|
+

|
|
424
|
+

|
|
425
|
+

|
|
426
|
+

|
|
427
|
+

|
|
428
|
+

|
|
429
|
+

|
|
430
|
+
|
|
431
|
+
### Python
|
|
432
|
+
|
|
433
|
+

|
|
434
|
+

|
|
435
|
+

|
|
436
|
+

|
|
437
|
+

|
|
438
|
+

|
|
439
|
+

|
|
440
|
+

|
|
441
|
+

|
|
442
|
+

|
|
443
|
+

|
|
444
|
+

|
|
445
|
+
|
|
446
|
+
### JSON
|
|
447
|
+
|
|
448
|
+

|
|
449
|
+

|
|
450
|
+

|
|
451
|
+

|
|
452
|
+

|
|
453
|
+

|
|
454
|
+

|
|
455
|
+

|
|
456
|
+

|
|
457
|
+

|
|
458
|
+

|
|
459
|
+

|
|
460
|
+
|
|
461
|
+
### YAML
|
|
462
|
+
|
|
463
|
+

|
|
464
|
+

|
|
465
|
+

|
|
466
|
+

|
|
467
|
+

|
|
468
|
+

|
|
469
|
+

|
|
470
|
+

|
|
471
|
+

|
|
472
|
+

|
|
473
|
+

|
|
474
|
+
|
|
475
|
+
### TOML
|
|
476
|
+
|
|
477
|
+

|
|
478
|
+

|
|
479
|
+

|
|
480
|
+

|
|
481
|
+

|
|
482
|
+

|
|
483
|
+

|
|
484
|
+
|
|
485
|
+
### Shell
|
|
486
|
+
|
|
487
|
+

|
|
488
|
+

|
|
489
|
+

|
|
490
|
+

|
|
491
|
+

|
|
492
|
+

|
|
493
|
+

|
|
494
|
+

|
|
495
|
+

|
|
496
|
+

|
|
497
|
+

|
|
498
|
+
|
|
499
|
+
### SQL
|
|
500
|
+
|
|
501
|
+

|
|
502
|
+

|
|
503
|
+

|
|
504
|
+

|
|
505
|
+

|
|
506
|
+

|
|
507
|
+

|
|
508
|
+

|
|
509
|
+

|
|
510
|
+

|
|
511
|
+

|
|
512
|
+
|
|
513
|
+
### HCL
|
|
514
|
+
|
|
515
|
+

|
|
516
|
+

|
|
517
|
+

|
|
518
|
+

|
|
519
|
+

|
|
520
|
+

|
|
521
|
+

|
|
522
|
+

|
|
523
|
+

|
|
524
|
+
|
|
525
|
+
### CSS
|
|
526
|
+
|
|
527
|
+

|
|
528
|
+

|
|
529
|
+

|
|
530
|
+

|
|
531
|
+

|
|
532
|
+

|
|
533
|
+

|
|
534
|
+

|
|
535
|
+

|
|
536
|
+
|
|
537
|
+
### Conventions
|
|
538
|
+
|
|
539
|
+

|
|
540
|
+

|
|
541
|
+

|
|
542
|
+

|
|
543
|
+

|
|
544
|
+

|
|
545
|
+

|
|
546
|
+

|
|
547
|
+

|
|
548
|
+

|
|
549
|
+

|
|
550
|
+

|
|
551
|
+

|
|
552
|
+

|
|
553
|
+

|
|
554
|
+

|
|
555
|
+

|
|
556
|
+

|
|
557
|
+
|
|
558
|
+
### Jupyter
|
|
559
|
+
|
|
560
|
+

|
|
561
|
+

|
|
562
|
+

|
|
563
|
+

|
|
564
|
+

|
|
565
|
+

|
|
566
|
+

|
|
567
|
+

|
|
568
|
+

|
|
569
|
+

|
|
570
|
+

|
|
571
|
+

|
|
572
|
+

|
|
573
|
+

|
|
574
|
+

|
|
575
|
+

|
|
576
|
+

|
|
577
|
+

|
|
578
|
+

|
|
579
|
+

|
|
580
|
+
|
|
581
|
+
### Markdown
|
|
582
|
+
|
|
583
|
+

|
|
584
|
+

|
|
585
|
+

|
|
586
|
+

|
|
587
|
+

|
|
588
|
+

|
|
589
|
+

|
|
590
|
+

|
|
591
|
+

|
|
592
|
+

|
|
593
|
+

|
|
594
|
+

|
|
595
|
+

|
|
596
|
+

|
|
597
|
+

|
|
598
|
+

|
|
599
|
+

|
|
600
|
+

|
|
601
|
+

|
|
602
|
+

|
|
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
|
-
"
|
|
4
|
-
|
|
5
|
-
|
|
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
|
}
|