@coinagerie/configuration 0.0.0-stage โ 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +363 -2
- package/dist/src/index.d.ts +242 -0
- package/dist/src/index.js +193 -0
- package/package.json +60 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## 0.0.2 (2026-11-04)
|
|
2
|
+
|
|
3
|
+
### ๐ Features
|
|
4
|
+
|
|
5
|
+
- **coinagerie:** โจ accept regular expressions in exclude.words ([#2109](https://github.com/organizzolini/codebase/pull/2109))
|
|
6
|
+
|
|
7
|
+
### ๐งฑ Updated Dependencies
|
|
8
|
+
|
|
9
|
+
- Updated coinagerie-core to 0.0.2
|
|
10
|
+
|
|
11
|
+
## 0.0.1 (2026-11-04)
|
|
12
|
+
|
|
13
|
+
### ๐ Features
|
|
14
|
+
|
|
15
|
+
- **coinagerie:** ๐ฆ๏ธ publish coinagerie to npm ([#2088](https://github.com/organizzolini/codebase/pull/2088), [#1793](https://github.com/organizzolini/codebase/issues/1793))
|
|
16
|
+
- **configuration,coinagerie:** โจ adopt coinagerie with a root glossary ([#1888](https://github.com/organizzolini/codebase/pull/1888), [#1785](https://github.com/organizzolini/codebase/issues/1785))
|
|
17
|
+
- **coinagerie:** โจ write json glossaries and override configuration with flags ([#1880](https://github.com/organizzolini/codebase/pull/1880), [#1766](https://github.com/organizzolini/codebase/issues/1766))
|
|
18
|
+
- **coinagerie:** โจ fold word forms and exclude configured words ([#1882](https://github.com/organizzolini/codebase/pull/1882), [#1762](https://github.com/organizzolini/codebase/issues/1762))
|
|
19
|
+
- **coinagerie:** โจ build a markdown glossary from typescript ([#1875](https://github.com/organizzolini/codebase/pull/1875), [#1755](https://github.com/organizzolini/codebase/issues/1755))
|
|
20
|
+
|
|
21
|
+
### ๐งฑ Updated Dependencies
|
|
22
|
+
|
|
23
|
+
- Updated coinagerie-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,364 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @coinagerie/configuration
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@coinagerie/configuration)
|
|
4
|
+
|
|
5
|
+
The configuration schema, loader, and command-line flag resolution for coinagerie. It reads a `coinagerie.config.ts` and resolves the folder a run scans, what it includes and excludes, and where its glossaries are written.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @coinagerie/configuration
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Test
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
nx run coinagerie-configuration:vitest
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## ๐ Conformetry
|
|
18
|
+
|
|
19
|
+
This project was generated from the [nestjs-service-project](../../configuration/conformetry-templates/nestjs-service-project) conformetry template.
|
|
20
|
+
|
|
21
|
+
<!-- coinagerie:start -->
|
|
22
|
+
|
|
23
|
+
## ๐ช Coinagerie
|
|
24
|
+
|
|
25
|
+
The words this package uses that the root glossary does not define, regenerated with `nx run coinagerie-configuration:coinagerie-check:write`.
|
|
26
|
+
|
|
27
|
+
- **breadth**:
|
|
28
|
+
- **discriminate**:
|
|
29
|
+
- **exact**:
|
|
30
|
+
- **forbid**:
|
|
31
|
+
- **prettify**:
|
|
32
|
+
- **refine**:
|
|
33
|
+
|
|
34
|
+
<!-- coinagerie:end -->
|
|
35
|
+
|
|
36
|
+
<!-- callidescope:start -->
|
|
37
|
+
|
|
38
|
+
## ๐ญ Callidescope
|
|
39
|
+
|
|
40
|
+
Call stacks traced through `projects/ic-suite/coinagerie/coinagerie-configuration`, deepest first. Each frame shows what it takes, what it returns, and what its documentation says.
|
|
41
|
+
|
|
42
|
+
| Measure | Value |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| Callables | 14 |
|
|
45
|
+
| Files | 12 |
|
|
46
|
+
| Calls traced | 20 |
|
|
47
|
+
| Call stacks | 1 |
|
|
48
|
+
| Deepest stack | 2 |
|
|
49
|
+
| Stacks through recursion | 0 |
|
|
50
|
+
| Unfollowable calls | 2 |
|
|
51
|
+
|
|
52
|
+
### Limits
|
|
53
|
+
|
|
54
|
+
What this project is judged against, as declared in its own `callidescope.config.ts`.
|
|
55
|
+
|
|
56
|
+
| Limit | Value |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `maximumDepth` | 3 |
|
|
59
|
+
| `maximumBreadth` | 3 |
|
|
60
|
+
|
|
61
|
+
### Call stacks (depth)
|
|
62
|
+
|
|
63
|
+
**1. `ConfigurationService.anonymous`** โ depth โฅ 2 ยท orphan-root
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
๐ ConfigurationService.anonymous(word: string): string [projects/ic-suite/coinagerie/coinagerie-configuration/src/modules/configuration/configuration.service.ts:67]
|
|
67
|
+
โโ> InvalidConfigurationError.constructor(filePath: string, reason: string): InvalidConfigurationError [projects/ic-suite/coinagerie/coinagerie-core/src/modules/coinagerie-core/coinagerie-core.constants.ts:32]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Breadth
|
|
71
|
+
|
|
72
|
+
| Callable | Breadth | Calls directly | Location |
|
|
73
|
+
| --- | --- | --- | --- |
|
|
74
|
+
| `ConfigurationService.locate` | 3 | `ConfigurationFileNotFoundError.constructor`, `ConfigurationService.find(โฆ)`, `ConfigurationService.map(โฆ)` | `projects/ic-suite/coinagerie/coinagerie-configuration/src/modules/configuration/configuration.service.ts:99` |
|
|
75
|
+
| `ConfigurationService.read` | 3 | `InvalidConfigurationError.constructor`, `ConfigurationService.describe`, `ConfigurationService.resolveWords` | `projects/ic-suite/coinagerie/coinagerie-configuration/src/modules/configuration/configuration.service.ts:169` |
|
|
76
|
+
| `ConfigurationService.resolve` | 3 | `InvalidConfigurationError.constructor`, `ConfigurationService.override`, `ConfigurationService.guardFold` | `projects/ic-suite/coinagerie/coinagerie-configuration/src/modules/configuration/configuration.service.ts:205` |
|
|
77
|
+
|
|
78
|
+
<details>
|
|
79
|
+
<summary>2 more callables</summary>
|
|
80
|
+
|
|
81
|
+
| Callable | Breadth | Calls directly | Location |
|
|
82
|
+
| --- | --- | --- | --- |
|
|
83
|
+
| `ConfigurationService.loadConfiguration` | 3 | `ConfigurationService.locate`, `ConfigurationService.resolve`, `ConfigurationService.read` | `projects/ic-suite/coinagerie/coinagerie-configuration/src/modules/configuration/configuration.service.ts:320` |
|
|
84
|
+
| `ConfigurationService.anonymous` | 2 | `InvalidConfigurationError.constructor`, `ConfigurationService.describe` | `projects/ic-suite/coinagerie/coinagerie-configuration/src/modules/configuration/configuration.service.ts:67` |
|
|
85
|
+
|
|
86
|
+
</details>
|
|
87
|
+
<!-- callidescope:end -->
|
|
88
|
+
|
|
89
|
+
## ๐ธ๏ธ Codependix
|
|
90
|
+
|
|
91
|
+
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`.
|
|
92
|
+
|
|
93
|
+
### Nx Neighborhood
|
|
94
|
+
|
|
95
|
+
<!-- codependix:start name="codependix-nx-projects" -->
|
|
96
|
+
```mermaid
|
|
97
|
+
graph LR
|
|
98
|
+
coinagerie_cli["coinagerie-cli"]
|
|
99
|
+
coinagerie_configuration["coinagerie-configuration"]
|
|
100
|
+
coinagerie_core["coinagerie-core"]
|
|
101
|
+
coinagerie_nx["coinagerie-nx"]
|
|
102
|
+
coinagerie_output["coinagerie-output"]
|
|
103
|
+
coinagerie_vocabulary["coinagerie-vocabulary"]
|
|
104
|
+
coinagerie_cli --> coinagerie_configuration
|
|
105
|
+
coinagerie_configuration --> coinagerie_core
|
|
106
|
+
coinagerie_nx --> coinagerie_configuration
|
|
107
|
+
coinagerie_output --> coinagerie_configuration
|
|
108
|
+
coinagerie_vocabulary --> coinagerie_configuration
|
|
109
|
+
classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
|
|
110
|
+
class coinagerie_configuration subject
|
|
111
|
+
```
|
|
112
|
+
<!-- codependix:end name="codependix-nx-projects" -->
|
|
113
|
+
|
|
114
|
+
### NestJS Module Graph
|
|
115
|
+
|
|
116
|
+
<!-- codependix:start name="codependix-nestjs-modules" -->
|
|
117
|
+
```mermaid
|
|
118
|
+
flowchart LR
|
|
119
|
+
ConfigurationModule
|
|
120
|
+
```
|
|
121
|
+
<!-- codependix:end name="codependix-nestjs-modules" -->
|
|
122
|
+
|
|
123
|
+
### File Imports
|
|
124
|
+
|
|
125
|
+
<!-- codependix:start name="codependix-file-imports" -->
|
|
126
|
+
```mermaid
|
|
127
|
+
graph LR
|
|
128
|
+
file_callidescope_config_ts["callidescope.config.ts"]
|
|
129
|
+
file_codependix_config_ts["codependix.config.ts"]
|
|
130
|
+
file_codometer_config_ts["codometer.config.ts"]
|
|
131
|
+
file_coinagerie_config_ts["coinagerie.config.ts"]
|
|
132
|
+
file_eslint_config_ts["eslint.config.ts"]
|
|
133
|
+
file_src_index_ts["src/index.ts"]
|
|
134
|
+
file_src_index_unit_test_ts["src/index.unit.test.ts"]
|
|
135
|
+
file_src_modules_configuration_configuration_constants_ts["src/modules/configuration/configuration.constants.ts"]
|
|
136
|
+
file_src_modules_configuration_configuration_module_ts["src/modules/configuration/configuration.module.ts"]
|
|
137
|
+
file_src_modules_configuration_configuration_service_ts["src/modules/configuration/configuration.service.ts"]
|
|
138
|
+
file_src_modules_configuration_configuration_service_unit_test_ts["src/modules/configuration/configuration.service.unit.test.ts"]
|
|
139
|
+
file_src_modules_configuration_configuration_types_ts["src/modules/configuration/configuration.types.ts"]
|
|
140
|
+
file_testing_mocks_ts["testing/mocks.ts"]
|
|
141
|
+
file_testing_setup_ts["testing/setup.ts"]
|
|
142
|
+
file_vite_config_ts["vite.config.ts"]
|
|
143
|
+
file_vitest_config_ts["vitest.config.ts"]
|
|
144
|
+
file_src_index_unit_test_ts --> file_src_index_ts
|
|
145
|
+
file_src_modules_configuration_configuration_constants_ts --> file_src_modules_configuration_configuration_types_ts
|
|
146
|
+
file_src_modules_configuration_configuration_module_ts --> file_src_modules_configuration_configuration_service_ts
|
|
147
|
+
file_src_modules_configuration_configuration_service_ts --> file_src_modules_configuration_configuration_constants_ts
|
|
148
|
+
file_src_modules_configuration_configuration_service_ts --> file_src_modules_configuration_configuration_types_ts
|
|
149
|
+
file_src_modules_configuration_configuration_service_unit_test_ts --> file_src_modules_configuration_configuration_constants_ts
|
|
150
|
+
file_src_modules_configuration_configuration_service_unit_test_ts --> file_src_modules_configuration_configuration_service_ts
|
|
151
|
+
```
|
|
152
|
+
<!-- codependix:end name="codependix-file-imports" -->
|
|
153
|
+
|
|
154
|
+
<!-- codometer:start -->
|
|
155
|
+
|
|
156
|
+
## โฒ๏ธ Codometer
|
|
157
|
+
|
|
158
|
+
### Project
|
|
159
|
+
|
|
160
|
+

|
|
161
|
+

|
|
162
|
+

|
|
163
|
+

|
|
164
|
+
|
|
165
|
+
### TypeScript
|
|
166
|
+
|
|
167
|
+

|
|
168
|
+

|
|
169
|
+

|
|
170
|
+

|
|
171
|
+

|
|
172
|
+

|
|
173
|
+

|
|
174
|
+
|
|
175
|
+
### JavaScript
|
|
176
|
+
|
|
177
|
+

|
|
178
|
+

|
|
179
|
+

|
|
180
|
+

|
|
181
|
+

|
|
182
|
+

|
|
183
|
+

|
|
184
|
+

|
|
185
|
+

|
|
186
|
+

|
|
187
|
+

|
|
188
|
+

|
|
189
|
+

|
|
190
|
+

|
|
191
|
+
|
|
192
|
+
### Python
|
|
193
|
+
|
|
194
|
+

|
|
195
|
+

|
|
196
|
+

|
|
197
|
+

|
|
198
|
+

|
|
199
|
+

|
|
200
|
+

|
|
201
|
+

|
|
202
|
+

|
|
203
|
+

|
|
204
|
+

|
|
205
|
+

|
|
206
|
+
|
|
207
|
+
### JSON
|
|
208
|
+
|
|
209
|
+

|
|
210
|
+

|
|
211
|
+

|
|
212
|
+

|
|
213
|
+

|
|
214
|
+

|
|
215
|
+

|
|
216
|
+

|
|
217
|
+

|
|
218
|
+

|
|
219
|
+

|
|
220
|
+

|
|
221
|
+
|
|
222
|
+
### YAML
|
|
223
|
+
|
|
224
|
+

|
|
225
|
+

|
|
226
|
+

|
|
227
|
+

|
|
228
|
+

|
|
229
|
+

|
|
230
|
+

|
|
231
|
+

|
|
232
|
+

|
|
233
|
+

|
|
234
|
+

|
|
235
|
+
|
|
236
|
+
### TOML
|
|
237
|
+
|
|
238
|
+

|
|
239
|
+

|
|
240
|
+

|
|
241
|
+

|
|
242
|
+

|
|
243
|
+

|
|
244
|
+

|
|
245
|
+
|
|
246
|
+
### Shell
|
|
247
|
+
|
|
248
|
+

|
|
249
|
+

|
|
250
|
+

|
|
251
|
+

|
|
252
|
+

|
|
253
|
+

|
|
254
|
+

|
|
255
|
+

|
|
256
|
+

|
|
257
|
+

|
|
258
|
+

|
|
259
|
+
|
|
260
|
+
### SQL
|
|
261
|
+
|
|
262
|
+

|
|
263
|
+

|
|
264
|
+

|
|
265
|
+

|
|
266
|
+

|
|
267
|
+

|
|
268
|
+

|
|
269
|
+

|
|
270
|
+

|
|
271
|
+

|
|
272
|
+

|
|
273
|
+
|
|
274
|
+
### HCL
|
|
275
|
+
|
|
276
|
+

|
|
277
|
+

|
|
278
|
+

|
|
279
|
+

|
|
280
|
+

|
|
281
|
+

|
|
282
|
+

|
|
283
|
+

|
|
284
|
+

|
|
285
|
+
|
|
286
|
+
### CSS
|
|
287
|
+
|
|
288
|
+

|
|
289
|
+

|
|
290
|
+

|
|
291
|
+

|
|
292
|
+

|
|
293
|
+

|
|
294
|
+

|
|
295
|
+

|
|
296
|
+

|
|
297
|
+
|
|
298
|
+
### Conventions
|
|
299
|
+
|
|
300
|
+

|
|
301
|
+

|
|
302
|
+

|
|
303
|
+

|
|
304
|
+

|
|
305
|
+

|
|
306
|
+

|
|
307
|
+

|
|
308
|
+

|
|
309
|
+

|
|
310
|
+

|
|
311
|
+

|
|
312
|
+

|
|
313
|
+

|
|
314
|
+

|
|
315
|
+

|
|
316
|
+

|
|
317
|
+

|
|
318
|
+
|
|
319
|
+
### Jupyter
|
|
320
|
+
|
|
321
|
+

|
|
322
|
+

|
|
323
|
+

|
|
324
|
+

|
|
325
|
+

|
|
326
|
+

|
|
327
|
+

|
|
328
|
+

|
|
329
|
+

|
|
330
|
+

|
|
331
|
+

|
|
332
|
+

|
|
333
|
+

|
|
334
|
+

|
|
335
|
+

|
|
336
|
+

|
|
337
|
+

|
|
338
|
+

|
|
339
|
+

|
|
340
|
+

|
|
341
|
+
|
|
342
|
+
### Markdown
|
|
343
|
+
|
|
344
|
+

|
|
345
|
+

|
|
346
|
+

|
|
347
|
+

|
|
348
|
+

|
|
349
|
+

|
|
350
|
+

|
|
351
|
+

|
|
352
|
+

|
|
353
|
+

|
|
354
|
+

|
|
355
|
+

|
|
356
|
+

|
|
357
|
+

|
|
358
|
+

|
|
359
|
+

|
|
360
|
+

|
|
361
|
+

|
|
362
|
+

|
|
363
|
+

|
|
364
|
+
<!-- codometer:end -->
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a `coinagerie.config.ts` exports by default.
|
|
3
|
+
*
|
|
4
|
+
* Every field is optional, and every path in it is relative to the folder the
|
|
5
|
+
* file sits in โ that folder is also the root the run scans.
|
|
6
|
+
*/
|
|
7
|
+
export declare interface CoinagerieConfiguration {
|
|
8
|
+
exclude?: CoinagerieExclusions | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Merges a derivational family into one headword, such as `configuration`
|
|
11
|
+
* into `configure`. Runs after plurals and inflections have been folded, so
|
|
12
|
+
* it sees lemmas rather than every surface form, and must return a
|
|
13
|
+
* non-empty string.
|
|
14
|
+
*/
|
|
15
|
+
fold?: FoldWord | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Globs naming the files the run scans, matched with `path.matchesGlob`.
|
|
18
|
+
* Defaults to every file, dot-files included.
|
|
19
|
+
*/
|
|
20
|
+
include?: string[] | undefined;
|
|
21
|
+
/** Where the glossary is kept. With none, a run only prints it. */
|
|
22
|
+
outputs?: CoinagerieOutput[] | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** What a run leaves out, on top of whatever `.gitignore` already ignores. */
|
|
26
|
+
export declare interface CoinagerieExclusions {
|
|
27
|
+
/** Globs naming files left out of the scan. */
|
|
28
|
+
paths?: string[] | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Words left out of the glossary, as a list or as a function returning one,
|
|
31
|
+
* synchronously or not โ the function is where a configuration reads
|
|
32
|
+
* whatever else it wants to exclude. A string leaves out that exact word.
|
|
33
|
+
* A regular expression leaves out every word it matches, tested against the
|
|
34
|
+
* lowercase word and against its folded headword. Exclusion applies after
|
|
35
|
+
* folding, so excluding `service` also covers `services`. Defaults to none.
|
|
36
|
+
*/
|
|
37
|
+
words?: ExcludedWords | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A JSON destination: the whole file is the glossary, a flat object sorted by
|
|
42
|
+
* word with `""` for a word nobody has defined yet.
|
|
43
|
+
*/
|
|
44
|
+
export declare interface CoinagerieJsonOutput {
|
|
45
|
+
path: string;
|
|
46
|
+
type: "json";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A markdown destination: the glossary block is kept between the
|
|
51
|
+
* `coinagerie:start` and `coinagerie:end` anchors of this file, and appended
|
|
52
|
+
* to its end when the file has no anchors yet.
|
|
53
|
+
*/
|
|
54
|
+
export declare interface CoinagerieMarkdownOutput {
|
|
55
|
+
/** Rendered under the heading, telling a reader what the block is. */
|
|
56
|
+
description?: string | undefined;
|
|
57
|
+
path: string;
|
|
58
|
+
type: "markdown";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** One place a glossary is kept. */
|
|
62
|
+
export declare type CoinagerieOutput = CoinagerieJsonOutput | CoinagerieMarkdownOutput;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* File names a run looks for in its working directory when no `--config` is
|
|
66
|
+
* given, in order of preference.
|
|
67
|
+
*/
|
|
68
|
+
export declare const CONFIGURATION_FILE_NAMES: readonly ["coinagerie.config.ts", "coinagerie.config.mts", "coinagerie.config.cts", "coinagerie.config.js", "coinagerie.config.mjs", "coinagerie.config.cjs"];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Provides the configuration layer: reading a `coinagerie.config.ts` into a
|
|
72
|
+
* configuration every other coinagerie package can trust.
|
|
73
|
+
*/
|
|
74
|
+
export declare class ConfigurationModule {
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* What the command line says, layered over the configuration file: a flag
|
|
79
|
+
* that is given replaces the field it names, and a field with no flag keeps
|
|
80
|
+
* what the file says.
|
|
81
|
+
*
|
|
82
|
+
* The two destination flags together replace the file's `outputs` with just
|
|
83
|
+
* the destinations they name. Their paths are relative to the working
|
|
84
|
+
* directory, as a path typed in a shell is; globs stay relative to the scan
|
|
85
|
+
* root.
|
|
86
|
+
*/
|
|
87
|
+
export declare interface ConfigurationOverrides {
|
|
88
|
+
/** Replaces the description of every markdown destination. */
|
|
89
|
+
description?: string | undefined;
|
|
90
|
+
/** Replaces `exclude.paths`. */
|
|
91
|
+
excludePaths?: string[] | undefined;
|
|
92
|
+
/** Replaces `include`. */
|
|
93
|
+
include?: string[] | undefined;
|
|
94
|
+
/** A JSON destination that replaces the file's `outputs`. */
|
|
95
|
+
outputJson?: string | undefined;
|
|
96
|
+
/** A markdown destination that replaces the file's `outputs`. */
|
|
97
|
+
outputMarkdown?: string | undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Finds, reads, validates, and resolves a `coinagerie.config.ts`.
|
|
102
|
+
*
|
|
103
|
+
* The one place a configuration is interpreted: what leaves here has every
|
|
104
|
+
* default filled in and every path made absolute, so nothing downstream has
|
|
105
|
+
* to know how the run was configured.
|
|
106
|
+
*/
|
|
107
|
+
export declare class ConfigurationService {
|
|
108
|
+
constructor();
|
|
109
|
+
/** A caught value as text, whether or not it is an `Error`. */
|
|
110
|
+
private describe;
|
|
111
|
+
/**
|
|
112
|
+
* Wraps the configured fold so that its faults name the file.
|
|
113
|
+
*
|
|
114
|
+
* The function is the configuration's own code, and it runs once per word
|
|
115
|
+
* long after the file was read; wrapping it here keeps every check of what
|
|
116
|
+
* it did in the one place that knows the file's path.
|
|
117
|
+
*/
|
|
118
|
+
private guardFold;
|
|
119
|
+
/**
|
|
120
|
+
* The configuration file a run reads, or `undefined` when it uses defaults.
|
|
121
|
+
*
|
|
122
|
+
* A named file must exist. An unnamed one is searched for only in the
|
|
123
|
+
* working directory, never above it, so a run never picks up a
|
|
124
|
+
* configuration written for some enclosing folder.
|
|
125
|
+
*/
|
|
126
|
+
private locate;
|
|
127
|
+
/**
|
|
128
|
+
* The configuration with the command line's flags laid over it.
|
|
129
|
+
*
|
|
130
|
+
* A flag that is given replaces the field it names, so the file never has
|
|
131
|
+
* to be edited to try a variation.
|
|
132
|
+
*/
|
|
133
|
+
private override;
|
|
134
|
+
/**
|
|
135
|
+
* Imports a configuration file, validates its default export, and calls
|
|
136
|
+
* its `exclude.words` function when it has one.
|
|
137
|
+
*
|
|
138
|
+
* Any failure โ the file throwing, a syntax error, an export of the wrong
|
|
139
|
+
* shape, a function that throws or returns something else โ is reported
|
|
140
|
+
* with the file's path, which is the one thing a reader needs to find the
|
|
141
|
+
* fault.
|
|
142
|
+
*/
|
|
143
|
+
private read;
|
|
144
|
+
/** Fills in every default and makes every path absolute. */
|
|
145
|
+
private resolve;
|
|
146
|
+
/**
|
|
147
|
+
* The entries a configuration excludes, calling its function when it has
|
|
148
|
+
* one, split into exact words and patterns.
|
|
149
|
+
*
|
|
150
|
+
* Throws a plain error for the caller to name the file in, so that no frame
|
|
151
|
+
* is spent on building the report here.
|
|
152
|
+
*/
|
|
153
|
+
private resolveWords;
|
|
154
|
+
/**
|
|
155
|
+
* Loads the run's configuration, or the defaults when there is none.
|
|
156
|
+
*
|
|
157
|
+
* The scan root is the configuration file's folder, so a run behaves the
|
|
158
|
+
* same wherever it is invoked from.
|
|
159
|
+
*/
|
|
160
|
+
loadConfiguration(args: LoadConfigurationArguments): Promise<ResolvedCoinagerieConfiguration>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Globs that together name every file, dot-files included.
|
|
165
|
+
*
|
|
166
|
+
* Three rather than one because `path.matchesGlob` never lets `*` or `**`
|
|
167
|
+
* match a name that starts with a dot: `**` alone would skip `.gitignore` and
|
|
168
|
+
* everything under `.github/`.
|
|
169
|
+
*/
|
|
170
|
+
export declare const DEFAULT_INCLUDE: readonly ["**", "**/.*", "**/.*/**"];
|
|
171
|
+
|
|
172
|
+
/** One entry of `exclude.words`: an exact word, or a pattern matching many. */
|
|
173
|
+
declare type ExcludedWord = RegExp | string;
|
|
174
|
+
|
|
175
|
+
/** A list of excluded words or patterns, or a function that returns one. */
|
|
176
|
+
export declare type ExcludedWords = (() => ExcludedWord[] | Promise<ExcludedWord[]>) | ExcludedWord[];
|
|
177
|
+
|
|
178
|
+
/** A function from a word to the headword it is folded into. */
|
|
179
|
+
export declare type FoldWord = (word: string) => string;
|
|
180
|
+
|
|
181
|
+
/** What `loadConfiguration` is asked for. */
|
|
182
|
+
export declare interface LoadConfigurationArguments {
|
|
183
|
+
/**
|
|
184
|
+
* A configuration file named on the command line, relative to the working
|
|
185
|
+
* directory. Without one, the working directory is searched for a file
|
|
186
|
+
* named in `CONFIGURATION_FILE_NAMES`, and defaults apply when none exists.
|
|
187
|
+
*/
|
|
188
|
+
configurationPath?: string | undefined;
|
|
189
|
+
/** What the command line overrides; nothing when absent. */
|
|
190
|
+
overrides?: ConfigurationOverrides | undefined;
|
|
191
|
+
/** Absolute path the command was run from. */
|
|
192
|
+
workingDirectory: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* A configuration with every default filled in and every path absolute.
|
|
197
|
+
*
|
|
198
|
+
* What the rest of the toolchain reads: nothing past this point has to know
|
|
199
|
+
* whether a value was written or defaulted.
|
|
200
|
+
*/
|
|
201
|
+
export declare interface ResolvedCoinagerieConfiguration {
|
|
202
|
+
/** The file read, or `undefined` when the run uses only defaults. */
|
|
203
|
+
configurationPath: string | undefined;
|
|
204
|
+
/** The root the run scans: the configuration file's folder, or the
|
|
205
|
+
* working directory when there is no file. */
|
|
206
|
+
directory: string;
|
|
207
|
+
/**
|
|
208
|
+
* `words` and `patterns` are resolved: a function in the file has been
|
|
209
|
+
* called, and every entry is either an exact word or a pattern.
|
|
210
|
+
*/
|
|
211
|
+
exclude: {
|
|
212
|
+
paths: string[];
|
|
213
|
+
patterns: RegExp[];
|
|
214
|
+
words: string[];
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* The configured fold, wrapped so that a throw or an empty or non-string
|
|
218
|
+
* result raises an `InvalidConfigurationError` naming the file; `undefined`
|
|
219
|
+
* when none is configured.
|
|
220
|
+
*/
|
|
221
|
+
fold: FoldWord | undefined;
|
|
222
|
+
include: string[];
|
|
223
|
+
outputs: ResolvedCoinagerieOutput[];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** A JSON destination whose path has been made absolute. */
|
|
227
|
+
export declare interface ResolvedCoinagerieJsonOutput {
|
|
228
|
+
path: string;
|
|
229
|
+
type: "json";
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** A markdown destination whose path has been made absolute. */
|
|
233
|
+
export declare interface ResolvedCoinagerieMarkdownOutput {
|
|
234
|
+
description: string | undefined;
|
|
235
|
+
path: string;
|
|
236
|
+
type: "markdown";
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** One destination, resolved. */
|
|
240
|
+
export declare type ResolvedCoinagerieOutput = ResolvedCoinagerieJsonOutput | ResolvedCoinagerieMarkdownOutput;
|
|
241
|
+
|
|
242
|
+
export { }
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { z as e } from "zod";
|
|
2
|
+
import { Injectable as t, Module as n } from "@nestjs/common";
|
|
3
|
+
import { existsSync as r } from "node:fs";
|
|
4
|
+
import i from "node:path";
|
|
5
|
+
import { fileURLToPath as a } from "node:url";
|
|
6
|
+
import { ConfigurationFileNotFoundError as o, InvalidConfigurationError as s } from "@coinagerie/core";
|
|
7
|
+
import { createJiti as c } from "jiti";
|
|
8
|
+
// \0rolldown/runtime.js
|
|
9
|
+
var l = [
|
|
10
|
+
"coinagerie.config.ts",
|
|
11
|
+
"coinagerie.config.mts",
|
|
12
|
+
"coinagerie.config.cts",
|
|
13
|
+
"coinagerie.config.js",
|
|
14
|
+
"coinagerie.config.mjs",
|
|
15
|
+
"coinagerie.config.cjs"
|
|
16
|
+
], u = [
|
|
17
|
+
"**",
|
|
18
|
+
"**/.*",
|
|
19
|
+
"**/.*/**"
|
|
20
|
+
], d = /^\s*(?:[-*+]\s|<!--)/mu, f = e.strictObject({
|
|
21
|
+
path: e.string().min(1),
|
|
22
|
+
type: e.literal("json")
|
|
23
|
+
}), p = e.string().refine((e) => !d.test(e), { message: "A description may not hold a list item or an HTML comment, which would read back as part of the glossary" }), isFunction = (e) => typeof e == "function", m = e.union([e.string(), e.instanceof(RegExp)]), h = e.array(m), g = e.string().regex(/^[^\s*]+$/u), _ = e.strictObject({
|
|
24
|
+
description: p.optional(),
|
|
25
|
+
path: e.string().min(1),
|
|
26
|
+
type: e.literal("markdown")
|
|
27
|
+
}), v = e.strictObject({
|
|
28
|
+
description: p.optional(),
|
|
29
|
+
excludePaths: e.array(e.string()).optional(),
|
|
30
|
+
include: e.array(e.string()).optional(),
|
|
31
|
+
outputJson: e.string().min(1).optional(),
|
|
32
|
+
outputMarkdown: e.string().min(1).optional()
|
|
33
|
+
}), y = e.strictObject({
|
|
34
|
+
exclude: e.strictObject({
|
|
35
|
+
paths: e.array(e.string()).optional(),
|
|
36
|
+
words: e.union([e.array(m), e.custom(isFunction, { message: "Expected a list of words or regular expressions, or a function returning one" })]).optional()
|
|
37
|
+
}).optional(),
|
|
38
|
+
fold: e.custom(isFunction, { message: "Expected a function" }).optional(),
|
|
39
|
+
include: e.array(e.string()).optional(),
|
|
40
|
+
outputs: e.array(e.discriminatedUnion("type", [f, _])).optional()
|
|
41
|
+
});
|
|
42
|
+
// \0@oxc-project+runtime@0.155.0/helpers/esm/decorateMetadata.js
|
|
43
|
+
function __decorateMetadata(e, t) {
|
|
44
|
+
if (typeof Reflect == "object" && typeof Reflect.metadata == "function") return Reflect.metadata(e, t);
|
|
45
|
+
}
|
|
46
|
+
// \0@oxc-project+runtime@0.155.0/helpers/esm/decorate.js
|
|
47
|
+
function __decorate(e, t, n, r) {
|
|
48
|
+
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
49
|
+
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
50
|
+
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);
|
|
51
|
+
return i > 3 && a && Object.defineProperty(t, n, a), a;
|
|
52
|
+
}
|
|
53
|
+
// src/modules/configuration/configuration.service.ts
|
|
54
|
+
var b = class ConfigurationService {
|
|
55
|
+
constructor() {}
|
|
56
|
+
describe(e) {
|
|
57
|
+
return e instanceof Error ? e.message : String(e);
|
|
58
|
+
}
|
|
59
|
+
guardFold(e, t) {
|
|
60
|
+
return (n) => {
|
|
61
|
+
let r;
|
|
62
|
+
try {
|
|
63
|
+
r = e(n);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
throw new s(t, `fold threw on "${n}": ${this.describe(e)}`);
|
|
66
|
+
}
|
|
67
|
+
let i = g.safeParse(r);
|
|
68
|
+
if (!i.success) throw new s(t, `fold must return a non-empty string without whitespace or "*", but returned ${typeof r == "string" ? JSON.stringify(r) : `a value of type ${typeof r}`} for "${n}"; it must be synchronous`);
|
|
69
|
+
return i.data;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
locate(e) {
|
|
73
|
+
if (e.configurationPath !== void 0) {
|
|
74
|
+
let t = i.resolve(e.workingDirectory, e.configurationPath);
|
|
75
|
+
if (!r(t)) throw new o(t);
|
|
76
|
+
return t;
|
|
77
|
+
}
|
|
78
|
+
return l.map((t) => i.join(e.workingDirectory, t)).find((e) => r(e));
|
|
79
|
+
}
|
|
80
|
+
override(e) {
|
|
81
|
+
let { configuration: t, flags: n, workingDirectory: r } = e, a = [...n.outputJson === void 0 ? [] : [{
|
|
82
|
+
path: i.resolve(r, n.outputJson),
|
|
83
|
+
type: "json"
|
|
84
|
+
}], ...n.outputMarkdown === void 0 ? [] : [{
|
|
85
|
+
path: i.resolve(r, n.outputMarkdown),
|
|
86
|
+
type: "markdown"
|
|
87
|
+
}]], o = a.length > 0 ? a : t.outputs ?? [];
|
|
88
|
+
return {
|
|
89
|
+
exclude: n.excludePaths ? {
|
|
90
|
+
...t.exclude,
|
|
91
|
+
paths: n.excludePaths
|
|
92
|
+
} : t.exclude,
|
|
93
|
+
fold: t.fold,
|
|
94
|
+
include: n.include ?? t.include,
|
|
95
|
+
outputs: o
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async read(t) {
|
|
99
|
+
let n;
|
|
100
|
+
try {
|
|
101
|
+
n = await c(a(import.meta.url)).import(t, { default: !0 });
|
|
102
|
+
} catch (e) {
|
|
103
|
+
throw new s(t, this.describe(e));
|
|
104
|
+
}
|
|
105
|
+
let r = y.safeParse(n);
|
|
106
|
+
if (!r.success) throw new s(t, e.prettifyError(r.error));
|
|
107
|
+
try {
|
|
108
|
+
return {
|
|
109
|
+
configuration: r.data,
|
|
110
|
+
excluded: await this.resolveWords(r.data.exclude?.words)
|
|
111
|
+
};
|
|
112
|
+
} catch (e) {
|
|
113
|
+
throw new s(t, `exclude.words ${this.describe(e)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
resolve(t) {
|
|
117
|
+
let { directory: n, location: r } = t, a = v.safeParse(t.overrides ?? {});
|
|
118
|
+
if (!a.success) throw new s("the command line", e.prettifyError(a.error));
|
|
119
|
+
let o = this.override({
|
|
120
|
+
configuration: t.loaded.configuration,
|
|
121
|
+
flags: a.data,
|
|
122
|
+
workingDirectory: t.workingDirectory
|
|
123
|
+
}), c = [], l = /* @__PURE__ */ new Set();
|
|
124
|
+
for (let e of o.outputs ?? []) {
|
|
125
|
+
let r = i.resolve(n, e.path);
|
|
126
|
+
if (l.has(r)) throw new s(t.configurationPath ?? "the command line", `Two outputs name ${r}, and each write would overwrite the other`);
|
|
127
|
+
l.add(r), c.push(e.type === "json" ? {
|
|
128
|
+
path: r,
|
|
129
|
+
type: "json"
|
|
130
|
+
} : {
|
|
131
|
+
description: a.data.description ?? e.description,
|
|
132
|
+
path: r,
|
|
133
|
+
type: "markdown"
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
configurationPath: t.configurationPath,
|
|
138
|
+
directory: n,
|
|
139
|
+
exclude: {
|
|
140
|
+
paths: o.exclude?.paths ?? [],
|
|
141
|
+
patterns: t.loaded.excluded.patterns,
|
|
142
|
+
words: t.loaded.excluded.words
|
|
143
|
+
},
|
|
144
|
+
fold: o.fold === void 0 ? void 0 : this.guardFold(o.fold, r),
|
|
145
|
+
include: o.include ?? [...u],
|
|
146
|
+
outputs: c
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async resolveWords(e) {
|
|
150
|
+
let t = typeof e == "function" ? await e() : e ?? [], n = h.safeParse(t);
|
|
151
|
+
if (!n.success) throw Error("must be a list of strings or RegExp objects, or a function returning one");
|
|
152
|
+
let r = [], i = [];
|
|
153
|
+
for (let e of n.data) e instanceof RegExp ? r.push(new RegExp(e.source, e.flags.replaceAll(/[gy]/gu, ""))) : i.push(e);
|
|
154
|
+
return {
|
|
155
|
+
patterns: r,
|
|
156
|
+
words: i
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
async loadConfiguration(e) {
|
|
160
|
+
let t = this.locate(e);
|
|
161
|
+
return t === void 0 ? this.resolve({
|
|
162
|
+
configurationPath: void 0,
|
|
163
|
+
directory: e.workingDirectory,
|
|
164
|
+
loaded: {
|
|
165
|
+
configuration: {},
|
|
166
|
+
excluded: {
|
|
167
|
+
patterns: [],
|
|
168
|
+
words: []
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
location: e.workingDirectory,
|
|
172
|
+
overrides: e.overrides,
|
|
173
|
+
workingDirectory: e.workingDirectory
|
|
174
|
+
}) : this.resolve({
|
|
175
|
+
configurationPath: t,
|
|
176
|
+
directory: i.dirname(t),
|
|
177
|
+
loaded: await this.read(t),
|
|
178
|
+
location: t,
|
|
179
|
+
overrides: e.overrides,
|
|
180
|
+
workingDirectory: e.workingDirectory
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
b = __decorate([t(), __decorateMetadata("design:paramtypes", [])], b);
|
|
185
|
+
// src/modules/configuration/configuration.module.ts
|
|
186
|
+
var x = class ConfigurationModule {};
|
|
187
|
+
x = __decorate([n({
|
|
188
|
+
controllers: [],
|
|
189
|
+
exports: [b],
|
|
190
|
+
imports: [],
|
|
191
|
+
providers: [b]
|
|
192
|
+
})], x);
|
|
193
|
+
export { l as CONFIGURATION_FILE_NAMES, x as ConfigurationModule, b as ConfigurationService, u as DEFAULT_INCLUDE };
|
package/package.json
CHANGED
|
@@ -1,6 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
+
"author": "Jimmy Paolini",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/organizzolini/codebase/issues"
|
|
5
|
+
},
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@coinagerie/core": "0.0.2",
|
|
8
|
+
"@nestjs/common": "^11.1.21 || ^12.0.1",
|
|
9
|
+
"jiti": "^2.7.0",
|
|
10
|
+
"reflect-metadata": "^0.2.2",
|
|
11
|
+
"zod": "^4.4.3"
|
|
12
|
+
},
|
|
13
|
+
"description": "Configuration schema, loader, and command-line flag resolution for the coinagerie vocabulary toolchain",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@golevelup/ts-vitest": "^4.0.0",
|
|
16
|
+
"@nestjs/testing": "^12.0.1",
|
|
17
|
+
"@nx/eslint-plugin": "^24.0.0",
|
|
18
|
+
"@swc/helpers": "^0.5.21",
|
|
19
|
+
"@types/node": "^26.5.1",
|
|
20
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
21
|
+
"typescript": "^6.0.3",
|
|
22
|
+
"vitest": "^5.0.0"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/src/index.d.ts",
|
|
27
|
+
"default": "./dist/src/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"CHANGELOG.md",
|
|
33
|
+
"dist",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"homepage": "https://github.com/organizzolini/codebase/tree/main/projects/ic-suite/coinagerie/coinagerie-configuration#readme",
|
|
38
|
+
"keywords": [
|
|
39
|
+
"coinagerie",
|
|
40
|
+
"configuration",
|
|
41
|
+
"glossary",
|
|
42
|
+
"vocabulary"
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"main": "./dist/src/index.js",
|
|
2
46
|
"name": "@coinagerie/configuration",
|
|
3
|
-
"
|
|
4
|
-
|
|
5
|
-
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"registry": "https://registry.npmjs.org"
|
|
50
|
+
},
|
|
51
|
+
"repository": {
|
|
52
|
+
"directory": "projects/ic-suite/coinagerie/coinagerie-configuration",
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/organizzolini/codebase.git"
|
|
55
|
+
},
|
|
56
|
+
"type": "module",
|
|
57
|
+
"typeCoverage": {
|
|
58
|
+
"atLeast": 100,
|
|
59
|
+
"strict": true
|
|
60
|
+
},
|
|
61
|
+
"types": "./dist/src/index.d.ts",
|
|
62
|
+
"version": "0.0.2"
|
|
6
63
|
}
|