@conformetry/configuration 0.0.79 → 0.0.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## 0.0.81 (2026-11-10)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **codometer:** ✨ gate JSDoc on every declaration kind and shorten long comments ([#2227](https://github.com/organizzolini/codebase/pull/2227), [#2226](https://github.com/organizzolini/codebase/issues/2226))
6
+
7
+ ### 🧱 Updated Dependencies
8
+
9
+ - Updated conformetry-core to 0.0.79
10
+
11
+ ## 0.0.80 (2026-11-10)
12
+
13
+ ### 🩹 Fixes
14
+
15
+ - **codependix,conformetry,infrastructure,installation,persistence,testing,configuration,caelundas,dependencies:** 🐛 gap ([#2223](https://github.com/organizzolini/codebase/pull/2223), [#2221](https://github.com/organizzolini/codebase/issues/2221))
16
+
17
+ ### 🧱 Updated Dependencies
18
+
19
+ - Updated conformetry-core to 0.0.78
20
+
1
21
  ## 0.0.79 (2026-11-10)
2
22
 
3
23
  ### 🧱 Updated Dependencies
@@ -7,25 +7,15 @@ import { InventoriedTemplate } from '@conformetry/core';
7
7
  import { PreparedValidationDocument } from '@conformetry/core';
8
8
 
9
9
  /**
10
- * How a caller says "every template" to `validate --templates`.
11
- *
12
- * A sentinel rather than a second flag, because supplying a value is how this
13
- * command line opts out of being prompted: omitting `--templates` in a
14
- * terminal asks, and passing `all` decides without narrowing. It lives beside
15
- * the other command-line vocabulary because that is what it is — the word a
16
- * caller types — and `assertNoCollisions` reads it from here so a template can
17
- * never be named the same thing.
10
+ * The `validate --templates` value meaning every template. Supplying it skips
11
+ * the prompt omitting it would show; no template may use this name.
18
12
  */
19
13
  export declare const ALL_TEMPLATES_SELECTION = "all";
20
14
 
21
15
  /**
22
- * Reads what each placeholder value in `templateText` stands for in
23
- * `instanceText`.
16
+ * Reads what each placeholder value in `templateText` stands for in `instanceText`.
24
17
  *
25
- * The template text is a pattern: its literal parts must match exactly and
26
- * each placeholder value captures a non-empty run of text. Returns `undefined`
27
- * when the template text holds no placeholder value or the instance text does
28
- * not fit the pattern, so a caller keeps its own equality check as it was.
18
+ * Returns `undefined` when the instance text does not fit the template pattern.
29
19
  */
30
20
  export declare function capturePlaceholderValues(args: {
31
21
  instanceText: string;
@@ -35,12 +25,7 @@ export declare function capturePlaceholderValues(args: {
35
25
  /**
36
26
  * Provides the configuration layer's one public service.
37
27
  *
38
- * The five modules above supply the collaborators `ConfigurationService` is
39
- * assembled from, and none of them is re-exported: a consumer outside this
40
- * package injects `ConfigurationService` and nothing else, which is what makes
41
- * this layer one entry point rather than a bag of services a caller has to
42
- * know the names of. The three sibling ic-suite toolchains publish exactly
43
- * this pair, and conformetry now reads as the same shape.
28
+ * Only `ConfigurationService` is exported; a consumer injects it and nothing else from this package.
44
29
  */
45
30
  export declare class ConfigurationModule {
46
31
  }
@@ -48,10 +33,7 @@ export declare class ConfigurationModule {
48
33
  /**
49
34
  * Raised when a run names no configuration file.
50
35
  *
51
- * There is no default file and no filename search: the path is the one thing a
52
- * run cannot infer, and a guessed file is a silently wrong configuration. The
53
- * surface is how the caller spells the thing the person left unset — a flag, an
54
- * option, a registration — so the message points at the fix where they are.
36
+ * There is no default file and no filename search, since a guessed file would be silently wrong.
55
37
  */
56
38
  export declare class ConfigurationPathRequiredError extends Error {
57
39
  constructor(surface: string);
@@ -59,22 +41,9 @@ export declare class ConfigurationPathRequiredError extends Error {
59
41
  }
60
42
 
61
43
  /**
62
- * The one answer to "what is this run actually configured to do".
63
- *
64
- * Every question a caller outside this package can ask about configuration is
65
- * asked here: what a config file declares, which templates it points at, which
66
- * instances exist and what explains them, what a placeholder renders to, and
67
- * what to ask a person for when an input was left off. A consumer therefore
68
- * injects this and nothing else from this package, which is what makes the
69
- * configuration layer one layer rather than a bag of collaborators a caller
70
- * has to know the names of — the shape callidescope, codependix and codometer
71
- * already publish.
44
+ * The single entry point for configuration questions: load a config file, find templates and instances, and prompt for inputs.
72
45
  *
73
- * Loading a config file is the one job held here rather than delegated;
74
- * everything below it is a one-line hand-off. Prompting, option parsing,
75
- * rendering, template discovery, instance discovery and instance-group reading
76
- * stay six classes in their own files, because they are six different jobs.
77
- * What they stop being is six public entry points.
46
+ * Callers inject this service and nothing else from this package. The collaborators are kept as separate classes so each one stays a single job.
78
47
  */
79
48
  export declare class ConfigurationService {
80
49
  private readonly inputPromptingService;
@@ -87,8 +56,7 @@ export declare class ConfigurationService {
87
56
  /**
88
57
  * Fills in the optional halves of one parsed generator entry.
89
58
  *
90
- * A generator with no inputs and no instances is legal — it renders a fixed
91
- * template nobody validates — so both default to empty rather than failing.
59
+ * A generator with no inputs or instances is legal.
92
60
  */
93
61
  private applyGeneratorDefaults;
94
62
  /**
@@ -97,10 +65,9 @@ export declare class ConfigurationService {
97
65
  */
98
66
  private applyHookDefaults;
99
67
  /**
100
- * Walks upward from the process cwd looking for the workspace manifest.
68
+ * Walks upward from the cwd to find the workspace manifest.
101
69
  *
102
- * Used to resolve a config path given relative to the workspace root even
103
- * when the command was invoked from a nested directory.
70
+ * Lets a config path resolve from a nested directory.
104
71
  */
105
72
  private findWorkspaceRoot;
106
73
  /** Loads a config module, choosing the reader by extension. */
@@ -125,9 +92,7 @@ export declare class ConfigurationService {
125
92
  /**
126
93
  * Loads, validates, and normalizes a conformetry configuration file.
127
94
  *
128
- * Throws `UnknownConfigurationFileTypeError` for an unreadable extension, and
129
- * propagates the Zod error for a malformed registry — a bad config should
130
- * fail loudly rather than silently validate nothing.
95
+ * Throws for an unsupported extension or a malformed registry, so a bad config fails loudly.
131
96
  */
132
97
  loadConformetryConfiguration(configurationPath: string): Promise<ConformetryConfiguration>;
133
98
  /** Resolves every instance to the template, or templates, that explain it. */
@@ -157,22 +122,15 @@ export declare class ConfigurationService {
157
122
  /** Renders a template path with mustache. */
158
123
  renderPath(args: Parameters<RenderingService["renderPath"]>[0]): string;
159
124
  /**
160
- * Returns the configuration path a run was given, or refuses.
125
+ * Returns the configuration path, or throws when it is absent or blank.
161
126
  *
162
- * Every host asks here, so "a path is required" and what the refusal says
163
- * have one home. `surface` names where the caller expected the path to be
164
- * set, for example the `--config` flag.
165
- *
166
- * Throws `ConfigurationPathRequiredError` for an absent or blank value.
127
+ * `surface` names where the path was expected.
167
128
  */
168
129
  requireConfigurationPath(value: string | undefined, surface: string): string;
169
130
  /**
170
- * Resolves a config path to the absolute file `loadConformetryConfiguration`
171
- * reads: against the cwd first, then the workspace root.
131
+ * Resolves a config path to the file `loadConformetryConfiguration` reads.
172
132
  *
173
- * Public because the directory a hook builds its paths from is that file's
174
- * parent, and only this resolution knows which file was read. A host that
175
- * worked it out from the flag alone would miss the workspace-root fallback.
133
+ * Public so hosts resolve the same file, including the workspace-root fallback.
176
134
  */
177
135
  resolveConfigurationPath(configurationPath: string): Promise<string>;
178
136
  /** Resolves generator inputs from raw command-line arguments. */
@@ -186,10 +144,8 @@ export declare class ConfigurationService {
186
144
  }
187
145
 
188
146
  /**
189
- * The loaded configuration: one entry per generator.
190
- *
191
- * An array rather than a keyed record because a generator's name is already a
192
- * field, and a record made the name true in two places at once.
147
+ * The loaded configuration: one entry per generator. An array, since a
148
+ * generator's name is already a field and a record would state it twice.
193
149
  */
194
150
  export declare type ConformetryConfiguration = ConformetryGeneratorDefinition[];
195
151
 
@@ -197,34 +153,23 @@ export declare type ConformetryConfiguration = ConformetryGeneratorDefinition[];
197
153
  export declare interface ConformetryGeneratorDefinition {
198
154
  description?: string;
199
155
  /**
200
- * Functions run around generation: `preGenerate` before anything is written,
201
- * `postGenerate` after the template is rendered. Optional, and left off the
202
- * loaded definition when a generator declares none, so a host forwards
203
- * exactly what the configuration said.
156
+ * Functions run around generation: `preGenerate` before writing, `postGenerate`
157
+ * after rendering. Left off when a generator declares none.
204
158
  */
205
159
  hooks?: GeneratorHooks;
206
- /**
207
- * The values this generator substitutes, as JSON Schema fragments. Named for
208
- * what the implementation calls them everywhere else — a generator takes
209
- * inputs and renders a template with them.
210
- */
160
+ /** Values substituted into the template, each a JSON Schema fragment. */
211
161
  inputs: Record<string, ConformetryGeneratorInputDefinition>;
212
162
  /**
213
- * Where this generator's output already lives in the workspace. Validation
214
- * expands these to find what to check; generation reads them to learn where
215
- * a new instance belongs.
163
+ * Where this generator's output already lives. Validation expands these to
164
+ * find what to check; generation reads them to place new instances.
216
165
  */
217
166
  instances: ConformetryInstanceGroup[];
218
167
  name: string;
219
168
  /** The template folder, relative to the workspace root. */
220
169
  templatePath: string;
221
170
  /**
222
- * Lowest conformance score, from 0 to 1, an instance of this template may
223
- * have and still pass.
224
- *
225
- * Left undefined when unset rather than defaulted to 1, so a run-level
226
- * `--threshold` still has somewhere to apply. The default is reached only
227
- * when no level supplies a value.
171
+ * Lowest passing conformance score, 0 to 1. Unset rather than defaulted, so a
172
+ * run-level `--threshold` can still apply.
228
173
  */
229
174
  threshold?: number;
230
175
  }
@@ -240,69 +185,47 @@ export declare type ConformetryGeneratorInputDefinition = Record<string, unknown
240
185
  */
241
186
  export declare interface ConformetryInstanceGroup {
242
187
  /**
243
- * Workspace-relative globs naming paths that are never instances, applied
244
- * whether or not the group has tags. A directory or file the patterns found
245
- * is dropped when one of these matches it — how vendored or generated code,
246
- * such as shadcn components, is left out of validation.
188
+ * Workspace-relative globs naming paths that are never instances, such as
189
+ * vendored shadcn components. Applies whether or not the group has tags.
247
190
  */
248
191
  exclude?: string[] | undefined;
249
192
  /**
250
- * Globs locating this group's instances.
251
- *
252
- * Workspace-relative on their own. A host that resolves `tags` may instead
253
- * read them relative to each labelled host it selects — see
254
- * `ConformetryNxInstanceGroup` in `@conformetry/nx` — which is why a group
255
- * naming only tags is legal: it selects without locating.
193
+ * Globs locating this group's instances, workspace-relative unless a host
194
+ * resolves `tags` against each selected host. A group with only `tags` selects
195
+ * without locating.
256
196
  */
257
197
  patterns?: string[] | undefined;
258
198
  /**
259
- * Values every placeholder this generator's template uses must be given.
260
- * Mustache renders an unknown placeholder as empty, so a missing entry shows
261
- * up as a silent hole rather than an error.
199
+ * Values for every placeholder the template uses. A missing one renders as
200
+ * empty rather than failing, so it is a silent hole.
262
201
  */
263
202
  substitutions?: Record<string, string> | undefined;
264
203
  /**
265
- * Labels selecting the hosts this group applies to.
266
- *
267
- * The base configuration carries them uninterpreted, because it has no
268
- * notion of a host to match them against; `conformetry-nx` reads them as Nx
269
- * project tags, and another host is free to read them as something else. A
270
- * group with no tags applies everywhere.
204
+ * Labels selecting the hosts this group applies to, carried uninterpreted
205
+ * here; `conformetry-nx` reads them as Nx project tags. No tags means everywhere.
271
206
  */
272
207
  tags?: string[] | undefined;
273
208
  /**
274
- * Lowest conformance score the instances in this group may have, overriding
275
- * the generator's own threshold.
276
- *
277
- * This is what makes a migration bearable: one directory being brought onto
278
- * a new template can be held to a lower bar while every other instance of
279
- * the same template stays strict.
209
+ * Lowest passing score for this group's instances, overriding the generator's
210
+ * threshold. It lets one directory migrate at a lower bar.
280
211
  */
281
212
  threshold?: number | undefined;
282
213
  }
283
214
 
284
215
  /**
285
- * Creates a random stand-in for a placeholder nothing supplied.
286
- *
287
- * Validation renders it in place of the missing value, so the comparison can
288
- * find where the instance holds the real one and capture it.
216
+ * Creates a random stand-in for a placeholder nothing supplied, so validation can find the real value.
289
217
  */
290
218
  export declare function createPlaceholderValue(): string;
291
219
 
292
220
  /** Arguments for expanding instance globs into instances. */
293
221
  export declare interface FindInstancesArguments {
294
- /**
295
- * Globs, relative to the working directory, naming paths that are never
296
- * instances: a directory or file a pattern found is dropped when one of
297
- * these matches it.
298
- */
222
+ /** Globs naming paths that are never instances. A matching directory or file is dropped. */
299
223
  readonly exclude?: string[] | undefined;
300
224
  /** Glob patterns, resolved against the working directory. */
301
225
  readonly patterns: string[];
302
226
  /**
303
- * Applied to every instance these patterns produce. Callers that need
304
- * per-project values, such as an Nx plugin supplying `type`, call once per
305
- * project rather than passing a lookup table.
227
+ * Applied to every instance these patterns produce. Callers needing per-project
228
+ * values call once per project rather than passing a lookup table.
306
229
  */
307
230
  readonly substitutions?: Substitutions;
308
231
  /** Applied to every instance these patterns produce, when the group sets one. */
@@ -344,10 +267,9 @@ declare class InputOptionsService {
344
267
  /** Reads the option name from `--flag` or `--flag=value`. */
345
268
  private readOptionName;
346
269
  /**
347
- * Reads an option's value from either `--flag=value` or `--flag value`.
270
+ * Reads an option's value from `--flag=value` or `--flag value`.
348
271
  *
349
- * Returns `undefined` when the next token is another flag, so a valueless
350
- * flag does not swallow the option that follows it.
272
+ * A valueless flag does not swallow the option after it.
351
273
  */
352
274
  private readOptionValue;
353
275
  /** Matches an option name to a schema property, in camel or kebab form. */
@@ -355,8 +277,7 @@ declare class InputOptionsService {
355
277
  /**
356
278
  * Scans raw arguments for flags matching the generator's schema.
357
279
  *
358
- * Unknown flags are ignored rather than rejected: the argument list also
359
- * carries the command's own options, which are handled elsewhere.
280
+ * Unknown flags are ignored, since the command's own options share the argument list.
360
281
  */
361
282
  collectGeneratorInputs(args: {
362
283
  rawArguments: string[];
@@ -367,23 +288,9 @@ declare class InputOptionsService {
367
288
  }
368
289
 
369
290
  /**
370
- * Asks the user for input values interactively.
371
- *
372
- * Whether anybody *can* be asked is decided here rather than by the caller,
373
- * and `promptForInput` refuses rather than draws itself when nobody can. That
374
- * used to be the caller's job, behind a `--no-interactive` flag; a flag is a
375
- * poor place for it, because forgetting to consult it is what hung this CLI
376
- * in non-interactive environments.
377
- *
378
- * `isAtTerminal` stays public because some callers genuinely need the question
379
- * rather than the refusal: an **optional** input nobody can be asked about is
380
- * left out where a required one is refused, and the two template pickers below
381
- * are only ever reached once a command has already asked it.
291
+ * Asks the user for input values interactively, and for the template to run.
382
292
  *
383
- * Those pickers widen this service's remit from "values a schema declares" to
384
- * "also, which template to run". That is a deliberate trade: one prompting
385
- * seam is easier to keep honest than two, and a second one would have to read
386
- * the terminal for itself.
293
+ * Refuses rather than prompting when nobody can answer, so a non-terminal run cannot hang.
387
294
  */
388
295
  declare class InputPromptingService {
389
296
  private readonly inputSchemaService;
@@ -393,9 +300,7 @@ declare class InputPromptingService {
393
300
  /**
394
301
  * Refuses to draw a prompt nobody can answer.
395
302
  *
396
- * `prompts` does not fail on a non-terminal stdin — it renders the menu,
397
- * never resolves, and lets the process exit 0, so a run that generated
398
- * nothing reads as one that succeeded.
303
+ * `prompts` would otherwise exit 0 with nothing generated.
399
304
  */
400
305
  private assertCanPrompt;
401
306
  /** Renders one template as a choice, omitting an absent description. */
@@ -403,11 +308,7 @@ declare class InputPromptingService {
403
308
  /**
404
309
  * Whether anybody is there to answer a question.
405
310
  *
406
- * The one place the terminal is read, so the refusal in front of a prompt
407
- * and the caller's decision to skip an optional input cannot disagree about
408
- * what counts as interactive. `isTTY` is read as falsy rather than coerced:
409
- * `@types/node` calls it a `boolean` while it is `undefined` off a terminal,
410
- * so lint rejects the coercion that would say so.
311
+ * `isTTY` is tested as falsy: it is `undefined` off a terminal, despite its `boolean` type.
411
312
  */
412
313
  isAtTerminal(): boolean;
413
314
  /**
@@ -416,21 +317,13 @@ declare class InputPromptingService {
416
317
  */
417
318
  promptForInput(input: SchemaInput): Promise<string | undefined>;
418
319
  /**
419
- * Asks which single template to run, filtering as the caller types.
420
- *
421
- * Autocomplete rather than a plain select because a template name is long
422
- * by design — `nestjs-service-module` — and typing a fragment is what makes
423
- * that cheap. Whether anybody can be asked at all is the caller's decision,
424
- * already taken by the time this is reached.
320
+ * Asks which single template to run, with autocomplete since template names are long.
425
321
  */
426
322
  promptForTemplate(templates: readonly TemplateChoice[]): Promise<string | undefined>;
427
323
  /**
428
- * Asks which templates to narrow a run to, offering the `all` sentinel
429
- * alongside them so the picker can express everything the flag can.
324
+ * Asks which templates to narrow a run to, offering the `all` sentinel alongside them.
430
325
  *
431
- * Ticking nothing resolves to no selection rather than an empty one: an
432
- * empty narrowing would validate nothing at all, where the caller plainly
433
- * declined to narrow.
326
+ * Ticking nothing means no narrowing, not an empty one.
434
327
  */
435
328
  promptForTemplates(templates: readonly TemplateChoice[]): Promise<string[] | undefined>;
436
329
  }
@@ -466,8 +359,7 @@ declare class InputSchemaService {
466
359
  /**
467
360
  * Validates a value, returning `true` or the reason it failed.
468
361
  *
469
- * An empty value is only an error when the input is required, so optional
470
- * inputs can be skipped by pressing enter at a prompt.
362
+ * An empty value fails only when the input is required.
471
363
  */
472
364
  validateValue(args: {
473
365
  input: SchemaInput;
@@ -495,10 +387,7 @@ declare class InputService {
495
387
  /**
496
388
  * Obtains one missing value by prompting.
497
389
  *
498
- * With nobody at a terminal the two kinds of input part ways: an optional
499
- * one is left out, and a required one is refused. Prompting anyway is what
500
- * used to hang the process, and refusing an optional input would fail runs
501
- * that never needed the value at all.
390
+ * Without a terminal, a required input is refused and an optional one is skipped.
502
391
  */
503
392
  private resolveMissingValue;
504
393
  /** Splits a comma-delimited filter option into its values. */
@@ -513,9 +402,7 @@ declare class InputService {
513
402
  /**
514
403
  * Parses a threshold option as a ratio from 0 to 1.
515
404
  *
516
- * Rejected loudly rather than clamped: `--threshold 90` is someone meaning
517
- * 90%, and silently reading it as "always passes" would turn a typo into a
518
- * validation run that can never fail.
405
+ * Rejected rather than clamped: `--threshold 90` would otherwise read as always passing.
519
406
  */
520
407
  parseThresholdOption(value: string | undefined): number | undefined;
521
408
  /** Resolves generator inputs from raw command-line arguments. */
@@ -525,39 +412,27 @@ declare class InputService {
525
412
  }
526
413
 
527
414
  /**
528
- * A place a template's tree is rendered into, plus the name it renders with.
415
+ * A place a template's tree is rendered into, with the name it renders with.
529
416
  *
530
- * Instances come from the caller's glob expansion. Nothing here knows how they
531
- * were found — that is the host's job, because globbing a workspace and
532
- * reading project labels is workspace knowledge, not template knowledge.
417
+ * The host's glob expansion supplies it.
533
418
  */
534
419
  export declare interface Instance {
535
420
  /**
536
- * Absolute paths the match is restricted to, or `undefined` for the whole
537
- * directory tree.
538
- *
539
- * This is what lets a two-file template like `nestjs-service-file` win. A
540
- * directory glob leaves the scope open and the largest fitting template
541
- * wins; a file glob narrows the scope to the matched files, so a template
542
- * describing exactly those files fits better than one describing the whole
543
- * directory.
421
+ * Absolute paths narrowing the match, or `undefined` for the whole tree. A file
422
+ * glob narrows this, so a template describing those files fits better.
544
423
  */
545
424
  readonly fileScope?: string[];
546
425
  /** Drives the name substitutions — a directory basename or a filename stem. */
547
426
  readonly nameStem: string;
548
427
  /**
549
- * Absolute path to the directory the template's tree is laid over.
550
- *
551
- * A template that produces a folder contains that folder, so this is the
552
- * folder's *parent*: `nestjs-service-module` holds `{{nameKebabCase}}/…`,
553
- * and its path is `…/src/modules`. A template that produces loose files
554
- * holds them at its root, and its path is the directory those files sit in.
428
+ * Directory the template's tree is laid over: for a folder-producing template,
429
+ * the folder's parent; for loose files, their directory.
555
430
  */
556
431
  readonly path: string;
557
432
  /**
558
- * Substitutions the caller supplies on top of the derived name variants,
559
- * such as `type` from the project graph. Mustache renders an unknown
560
- * placeholder as empty, so anything a template references must arrive here.
433
+ * Caller-supplied substitutions beyond the derived name variants, such as
434
+ * `type`. Mustache renders a missing placeholder as empty, so each one must
435
+ * arrive here.
561
436
  */
562
437
  readonly substitutions?: Substitutions;
563
438
  /**
@@ -577,15 +452,9 @@ export declare interface Instance {
577
452
  declare class InstanceDiscoveryLocatingService {
578
453
  constructor();
579
454
  /**
580
- * Derives the substitutions an instance's own location answers.
455
+ * Derives location substitutions, such as `type`.
581
456
  *
582
- * `type` is the top-level directory the instance sits in — `packages` for
583
- * `packages/widgets` — because that is what a project template's own
584
- * `project.json` renders into its paths. Derived rather than configured for
585
- * the same reason the name variants are: it is a fact about where the
586
- * instance is, and restating it per glob is how the two drift apart. A
587
- * configured value still wins, which is what a workspace nesting its
588
- * projects deeper needs.
457
+ * `type` is the top-level directory; a configured value still wins.
589
458
  */
590
459
  private deriveLocationSubstitutions;
591
460
  /** Expands one pattern, leaving out every path an exclude glob matches. */
@@ -593,33 +462,21 @@ declare class InstanceDiscoveryLocatingService {
593
462
  /** Whether an exclude glob matches a found path, workspace-relative. */
594
463
  private isExcluded;
595
464
  /**
596
- * Returns the literal filename suffix a pattern ends with, such as
597
- * `.service.ts` for `**\/*.service.ts`, or `""` when the pattern's last
598
- * segment holds no wildcard.
465
+ * Returns the literal suffix a pattern ends with, or `""` if none.
599
466
  *
600
- * This is what a file instance's name is derived from: the part of the
601
- * filename the glob did not spell out is the name.
467
+ * A file's name is what the glob did not spell out.
602
468
  */
603
469
  private resolveGlobSuffix;
604
470
  /**
605
- * Derives the name an instance's substitutions are built from.
471
+ * Derives an instance's name.
606
472
  *
607
- * A directory is named by itself. A file is named by what remains once the
608
- * glob's literal suffix is removed, so `differences.service.ts` matched by
609
- * `*.service.ts` and `differences.service.unit.test.ts` matched by
610
- * `*.service.unit.test.ts` both yield `differences` — which is what collapses the
611
- * two into a single two-file instance.
473
+ * Minus the glob's suffix, `differences.service.ts` and `differences.service.unit.test.ts` both give `differences`.
612
474
  */
613
475
  private resolveNameStem;
614
476
  /**
615
- * Expands every pattern and returns one instance per distinct path, name,
616
- * and scope kind.
477
+ * Expands every pattern into one instance per distinct path, name, and scope kind.
617
478
  *
618
- * A directory match leaves the file scope open, so the largest fitting
619
- * template wins. File matches for the same name are unioned into one scoped
620
- * instance, so a template describing exactly those files wins instead. A
621
- * directory and a file instance for the same name stay separate on purpose:
622
- * both run, and deduplication reports the finding from the smaller template.
479
+ * Same-name file matches merge into one scoped instance.
623
480
  */
624
481
  findInstances(args: FindInstancesArguments): Instance[];
625
482
  }
@@ -636,57 +493,37 @@ declare class InstanceDiscoveryMatchingService {
636
493
  private readonly renderingService;
637
494
  constructor(templateDiscoveryService: TemplateDiscoveryService, renderingService: RenderingService);
638
495
  /**
639
- * Orders template matches best-first.
496
+ * Orders matches best-first.
640
497
  *
641
- * Coverage ratio leads, because absolute count alone lets a large template
642
- * win on a weak partial match — a module directory matching three of a
643
- * seven-file GraphQL template would beat nothing, and used to. Absolute
644
- * count breaks ratio ties, so a five-file module template beats a two-file
645
- * service-file template when both match completely. Name makes it
646
- * deterministic.
498
+ * Coverage ratio leads, so a large template cannot win a weak partial match.
499
+ * Ties break on count, then name.
647
500
  */
648
501
  private compareMatches;
649
502
  /**
650
- * Gives every placeholder the substitutions leave out a random stand-in.
503
+ * Gives each placeholder the substitutions leave out a random stand-in.
651
504
  *
652
- * Only validation matches instances, and there a missing value is something
653
- * to infer from the instance rather than an error: generation renders
654
- * without this and still refuses a placeholder nobody supplied. `name` and its
655
- * variants are always supplied, so they are never stood in for.
505
+ * Validation infers the stand-in's value from the instance; generation refuses to render one.
656
506
  */
657
507
  private fillPlaceholders;
658
508
  /**
659
509
  * Builds the substitutions an instance's template is rendered with.
660
510
  *
661
- * Name variants come from the instance's stem; caller-supplied values are
662
- * spread last so an explicit `type` or `description` always wins.
511
+ * Caller-supplied values are spread last, so an explicit `type` wins.
663
512
  */
664
513
  buildSubstitutions(instance: Instance): Substitutions;
665
514
  /**
666
- * Resolves every instance to the template — or templates — that explain it.
667
- *
668
- * An instance matching nothing, or matching two templates equally well but
669
- * only partially, is returned as unmatched rather than dropped: the caller
670
- * asserted these are instances, so silence would hide both a drifted
671
- * instance and a pair of indistinguishable templates.
515
+ * Resolves every instance to the template, or templates, that explain it.
672
516
  *
673
- * A complete tie is different, and is matched against every tied template. A
674
- * module holding both a command and a service really is an instance of both
675
- * `nestjs-command-module` and `nestjs-service-module`; calling that ambiguous
676
- * would demand the author narrow a glob that is not wrong.
517
+ * Unexplained or partially tied instances are reported as unmatched, not dropped.
677
518
  */
678
519
  matchInstances(args: {
679
520
  instances: Instance[];
680
521
  templates: TemplateDefinition[];
681
522
  }): ResolvedInstances;
682
523
  /**
683
- * Weighs every template that shares at least one file with the instance,
684
- * best-first.
524
+ * Weighs every template sharing a file with the instance, best-first.
685
525
  *
686
- * Public because a caller may need the ranking itself and not just the
687
- * verdict: nothing records which template an instance came from, so an
688
- * ambiguous or unmatched outcome is only explainable by showing what was
689
- * weighed and how well each template fitted.
526
+ * Public so callers can explain an ambiguous or unmatched outcome.
690
527
  */
691
528
  matchTemplates(args: {
692
529
  instance: Instance;
@@ -711,11 +548,9 @@ declare class InstanceDiscoveryService {
711
548
  private readonly templateDiscoveryService;
712
549
  constructor(instanceDiscoveryLocatingService: InstanceDiscoveryLocatingService, instanceDiscoveryMatchingService: InstanceDiscoveryMatchingService, instanceGroupService: InstanceGroupService, templateDiscoveryService: TemplateDiscoveryService);
713
550
  /**
714
- * The globs an inventory expands: the configured groups' patterns and
715
- * exclusions, or an explicit pattern list replacing both.
551
+ * The globs an inventory expands.
716
552
  *
717
- * One expansion rather than one per group, so an instance two groups locate
718
- * is listed once; every group's exclusions therefore apply to all of them.
553
+ * One expansion covers all groups, so an instance two groups locate is listed once.
719
554
  */
720
555
  private readInventoryGlobs;
721
556
  /** Weighs one instance against every template, best fit first. */
@@ -737,24 +572,9 @@ declare class InstanceDiscoveryService {
737
572
  */
738
573
  prepareDocuments(args: PrepareDocumentsArguments): PreparedInstanceDocuments[];
739
574
  /**
740
- * Keeps the groups a host with no project graph can actually locate.
575
+ * Keeps the groups this host can locate: those without `tags`.
741
576
  *
742
- * A group carrying `tags` reads its globs *inside each project the tags
743
- * select*, so `src/modules/*` has no meaning until a project root is joined
744
- * to it. This package has no notion of a project, so such a group is not
745
- * addressed to it and is left out rather than expanded from the working
746
- * directory — which would match whatever happened to sit at the same
747
- * relative path and measure it against a template scoped to other projects.
748
- * `@conformetry/nx` resolves those groups first, so what reaches discovery
749
- * from there is already workspace-relative and untagged groups are all that
750
- * is left to read.
751
- *
752
- * Dropping them is deliberately silent here and reported by the caller: this
753
- * is a question about one group, and only a command knows whether the run it
754
- * was asked for has been left with nothing.
755
- *
756
- * Which groups those are is `InstanceGroupService`'s to say, so that this and
757
- * the set `@conformetry/nx` claims stay exact complements.
577
+ * Tagged groups need a project graph, which this host lacks.
758
578
  */
759
579
  readWorkspaceGroups(groups: readonly ConformetryInstanceGroup[]): ConformetryInstanceGroup[];
760
580
  /** Lists every file a matched instance's template requires it to have. */
@@ -762,16 +582,13 @@ declare class InstanceDiscoveryService {
762
582
  /**
763
583
  * Lists every instance found, paired with the templates that explain it.
764
584
  *
765
- * `templateNames` narrows the pairing rather than the search, so an instance
766
- * that no named template explains drops out entirely.
585
+ * `templateNames` narrows the pairing, dropping unexplained instances.
767
586
  */
768
587
  resolveInventoriedInstances(args: ResolveInventoryArguments): InventoriedInstance[];
769
588
  /**
770
589
  * Lists every template declared, paired with the instances it explains.
771
590
  *
772
- * `instancePatterns` narrows which instances are considered, which is what
773
- * turns this into "which templates explain this path". A path can legitimately
774
- * belong to several templates, so every one that fits is reported.
591
+ * `instancePatterns` narrows which instances count.
775
592
  */
776
593
  resolveInventoriedTemplates(args: ResolveInventoryArguments): InventoriedTemplate[];
777
594
  /** Weighs every instance the globs find against every declared template. */
@@ -794,36 +611,22 @@ export declare interface InstanceFile {
794
611
  /**
795
612
  * Reads an instance group's own fields, for every host that resolves one.
796
613
  *
797
- * `ConformetryInstanceGroup` is declared beside this, and how its `tags` are
798
- * read decides which host owns a group — so the reading lives here rather than
799
- * in either host. `@conformetry/nx` resolves project-scoped groups against the
800
- * project graph; a host without one leaves them alone. The two answers must be
801
- * complements, and nothing would fail if they stopped being: each host would
802
- * simply take a different set of groups to be its own, and validation would
803
- * quietly measure the wrong tree.
804
- *
805
- * Dependency-free on purpose. Every host reaches it through
806
- * `ConfigurationService`, so nothing has to be wired up to ask this question —
807
- * including the install-time bootstrap, which has no project graph to hand
808
- * anybody.
614
+ * Both hosts must agree on which groups are project-scoped, so the reading lives here.
809
615
  */
810
616
  declare class InstanceGroupService {
811
617
  constructor();
812
618
  /**
813
619
  * Whether a group locates its instances inside the hosts its tags select.
814
620
  *
815
- * Non-empty `tags` is the whole rule. An empty array is not a selector — it
816
- * selects nothing and would silence the group entirely — so it reads as the
817
- * workspace form, the same as omitting the field.
621
+ * Empty `tags` selects nothing, so it reads as the workspace form.
818
622
  */
819
623
  isProjectScoped(group: ConformetryInstanceGroup): boolean;
820
624
  }
821
625
 
822
626
  /**
823
- * Minimal JSON Schema fragment used to discover a generator's inputs.
627
+ * Minimal JSON Schema fragment for a generator's inputs.
824
628
  *
825
- * Only the parts conformetry actually reads are modelled — `properties` for
826
- * the input names, and `required` for which ones must be supplied.
629
+ * Only `properties` and `required` are modelled, since those are what conformetry reads.
827
630
  */
828
631
  export declare interface JsonSchemaDefinition {
829
632
  [key: string]: unknown;
@@ -836,9 +639,8 @@ export declare interface MatchedInstance {
836
639
  /** How many of the template's files the instance already has. */
837
640
  readonly matchedFileCount: number;
838
641
  /**
839
- * The random stand-in rendered for each placeholder nothing supplied, keyed
840
- * by placeholder. Validation replaces each with the text the instance holds
841
- * there. Absent or empty when every placeholder was supplied.
642
+ * Random stand-ins for placeholders nothing supplied, keyed by placeholder.
643
+ * Validation swaps each for the instance's own text there.
842
644
  */
843
645
  readonly placeholderValues?: Substitutions;
844
646
  /** Every value the template renders with, stand-ins included. */
@@ -847,14 +649,8 @@ export declare interface MatchedInstance {
847
649
  }
848
650
 
849
651
  /**
850
- * A run that names no directory, and has nothing else to place its output by.
851
- *
852
- * Both hosts refuse this with the same words, which is why it lives here: the
853
- * command-line host always needs `--directory`, and the Nx plugin needs it
854
- * only when no `project` or `type` locates the output, so each decides when to
855
- * raise it and neither words it. A silent fallback is what this replaces —
856
- * output written somewhere the caller never chose, reported as success. The
857
- * optional `hint` carries a remedy only one host has.
652
+ * Refuses a run that gives no output directory. Both hosts share these words;
653
+ * `hint` carries a remedy only one host has.
858
654
  */
859
655
  export declare const missingDirectoryError: (args: {
860
656
  generatorName: string | undefined;
@@ -862,24 +658,15 @@ export declare const missingDirectoryError: (args: {
862
658
  }) => InputError;
863
659
 
864
660
  /**
865
- * A required input that cannot be asked for, because stdin is not a terminal.
866
- *
867
- * `prompts` does not fail there — it draws its menu, never resolves, and the
868
- * process exits 0 having done nothing, which is exactly how this CLI used to
869
- * hang in non-interactive environments. Naming the flag to pass is the whole
870
- * remedy, so the message carries it.
661
+ * Input that cannot be asked for: stdin is not a terminal. `prompts` would hang
662
+ * and exit 0, so the message names the flag.
871
663
  */
872
664
  export declare const missingInputError: (inputName: string) => InputError;
873
665
 
874
666
  /**
875
- * Raised when a template interpolates a placeholder nobody supplied a value
876
- * for.
667
+ * Raised when a template interpolates a placeholder nobody supplied a value for.
877
668
  *
878
- * Refusing is the only outcome that cannot be mistaken for success: mustache
879
- * would render the placeholder as an empty string, and because generation and
880
- * validation render identically, both halves of the loop would lose the same
881
- * value and agree that nothing was wrong. Section tags are exempt, and why is
882
- * in this package's README.
669
+ * Refusing is the only outcome that cannot pass for success: generation and validation would otherwise lose the same value and agree.
883
670
  */
884
671
  export declare class MissingSubstitutionError extends Error {
885
672
  constructor(args: {
@@ -916,29 +703,18 @@ declare class RenderingService {
916
703
  /**
917
704
  * Derives the case variants every template can reference from one name.
918
705
  *
919
- * Callers merge their own inputs over this result, so an explicit input of
920
- * the same key always wins over the derived variant.
706
+ * Explicit inputs with the same key override these.
921
707
  */
922
708
  buildNameSubstitutions(name: string): Substitutions;
923
709
  /**
924
710
  * Every placeholder a template interpolates, deduplicated.
925
711
  *
926
- * Mustache's own parser reads them, so an interpolation is told from a
927
- * comment, a partial, and a delimiter change the way mustache tells them.
928
- * Section names are skipped and their bodies still walked — `{{#field}}` and
929
- * `{{^field}}` are conditionals, so absence is an answer there — as is the
930
- * implicit iterator `{{.}}`, which names no field.
712
+ * Mustache's own parser decides what counts, so comments and partials are not placeholders.
931
713
  */
932
714
  collectInterpolatedNames(template: string): string[];
933
715
  /**
934
- * Renders template contents with mustache.
935
- *
936
- * Full mustache is available — sections, inverted sections, partials — with
937
- * HTML escaping disabled so substituted values cannot corrupt source code.
938
- *
939
- * An interpolated placeholder nobody supplied raises
940
- * `MissingSubstitutionError`. `subject` is what that error names, so pass
941
- * the template's path when there is one.
716
+ * Renders template contents with mustache, HTML escaping disabled. Throws
717
+ * `MissingSubstitutionError` for a placeholder with no value; `subject` names the template.
942
718
  */
943
719
  renderContent(args: {
944
720
  subject?: string;
@@ -946,12 +722,9 @@ declare class RenderingService {
946
722
  templateContent: string;
947
723
  }): string;
948
724
  /**
949
- * Renders a template path with mustache, the same way contents are rendered.
725
+ * Renders a template path with mustache.
950
726
  *
951
- * Paths once used a `__field__` syntax of their own, on the assumption that
952
- * braces were not portable across filesystems. They are — and the separate
953
- * syntax could not tell a placeholder from a Python dunder, so a template
954
- * shipping `__init__.py` depended on `init` never being a substitution.
727
+ * Uses the same placeholders as contents, so a dunder such as `__init__` is never read as one.
955
728
  */
956
729
  renderPath(args: {
957
730
  subject?: string;
@@ -981,8 +754,7 @@ declare interface ResolveInputsFromValuesArguments {
981
754
  /**
982
755
  * Arguments for taking an inventory of templates and instances.
983
756
  *
984
- * Both filters narrow the pairing rather than the search, so an entry that
985
- * survives neither drops out entirely.
757
+ * Both filters narrow the pairing, so an entry that survives neither drops out.
986
758
  */
987
759
  export declare interface ResolveInventoryArguments {
988
760
  readonly configuration: ConformetryConfiguration;
@@ -1001,20 +773,15 @@ declare interface SchemaInput {
1001
773
  }
1002
774
 
1003
775
  /**
1004
- * Placeholder values applied when rendering a template.
1005
- *
1006
- * Built from the generator name by `RenderingService.buildNameSubstitutions`
1007
- * and then merged with the caller's own inputs, so an explicit input always
1008
- * wins over a derived name variant.
776
+ * Placeholder values for rendering a template. Derived name variants are merged
777
+ * under the caller's inputs, which always win.
1009
778
  */
1010
779
  export declare type Substitutions = Record<string, string>;
1011
780
 
1012
781
  /**
1013
782
  * One template a picker can offer.
1014
783
  *
1015
- * Deliberately not `ConformetryGeneratorDefinition`: the picker needs only the
1016
- * name it returns and the description it shows, and asking for the whole
1017
- * definition would tie prompting to the configuration's shape.
784
+ * Only the name and description are passed, so prompting does not depend on the configuration's shape.
1018
785
  */
1019
786
  export declare interface TemplateChoice {
1020
787
  readonly description?: string | undefined;
@@ -1030,9 +797,8 @@ export declare interface TemplateDefinition {
1030
797
  /** The template's directory name, used to identify it. */
1031
798
  readonly name: string;
1032
799
  /**
1033
- * Every placeholder the template's files and file paths interpolate. Read
1034
- * once here so validation knows which ones nothing supplied without
1035
- * reading the template again per instance. Absent means none.
800
+ * Every placeholder the template's files and paths interpolate. Read once
801
+ * here, so validation knows which nothing supplied. Absent means none.
1036
802
  */
1037
803
  readonly placeholderNames?: string[];
1038
804
  /**
@@ -1045,15 +811,8 @@ export declare interface TemplateDefinition {
1045
811
  /**
1046
812
  * Reads template folders and maps their files onto instance files.
1047
813
  *
1048
- * A template's tree is laid over the instance path verbatim, so a template
1049
- * that should produce a folder contains that folder — `{{nameKebabCase}}/…` —
1050
- * rather than the runtime inventing one. That keeps the shape of the output
1051
- * visible in the template itself, and lets one template produce a folder while
1052
- * another produces loose files, with nothing but their contents to say so.
1053
- *
1054
- * Rendering goes through `RenderingService` so a template is substituted here
1055
- * exactly as it was when the generator wrote the file — otherwise validation
1056
- * would report differences the generator itself introduced.
814
+ * A template's tree is laid over the instance path verbatim, so a template creates a folder by containing it.
815
+ * Rendering goes through `RenderingService` so validation substitutes exactly as generation did.
1057
816
  */
1058
817
  declare class TemplateDiscoveryService {
1059
818
  private readonly renderingService;
@@ -1074,11 +833,7 @@ declare class TemplateDiscoveryService {
1074
833
  threshold?: number | undefined;
1075
834
  }): TemplateDefinition;
1076
835
  /**
1077
- * Reads every configured generator's template folder.
1078
- *
1079
- * Every host needs this before it can match anything, and each was resolving
1080
- * the configured paths itself. Resolving them once here keeps one answer to
1081
- * where a generator's template lives.
836
+ * Reads every configured generator's template folder, resolving each path once.
1082
837
  */
1083
838
  collectTemplates(args: {
1084
839
  configuration: ConformetryConfiguration;
@@ -1087,9 +842,7 @@ declare class TemplateDiscoveryService {
1087
842
  /**
1088
843
  * Counts how many of a template's files the instance path already has.
1089
844
  *
1090
- * When a file scope is given, only files inside it count — that is what lets
1091
- * a file glob select a template describing exactly those files rather than
1092
- * the larger template describing the whole directory.
845
+ * A file scope limits the count to the files it lists.
1093
846
  */
1094
847
  countMatchingFiles(args: {
1095
848
  fileScope?: string[] | undefined;
@@ -1100,9 +853,7 @@ declare class TemplateDiscoveryService {
1100
853
  /**
1101
854
  * Pairs one template file with its instance, rendering the template.
1102
855
  *
1103
- * Returns `undefined` when the instance does not exist — that is a missing
1104
- * file, which the file-existence pass reports; a language validator has nothing
1105
- * to compare and should not see the pair at all.
856
+ * Returns `undefined` when the instance is missing, which the file-existence pass reports instead.
1106
857
  */
1107
858
  prepareDocument(args: {
1108
859
  instancePath: string;
@@ -1122,10 +873,7 @@ declare class TemplateDiscoveryService {
1122
873
  /**
1123
874
  * One template weighed against an instance during matching.
1124
875
  *
1125
- * `matchRatio` measures which template *fits*, by file presence alone. It is
1126
- * deliberately not called a score: an instance's conformance score measures
1127
- * how well the matched template's contents are honoured, which is a different
1128
- * number arrived at a different way.
876
+ * `matchRatio` measures fit by file presence alone, not conformance score.
1129
877
  */
1130
878
  export declare interface TemplateMatch {
1131
879
  readonly matchedFileCount: number;
@@ -1152,11 +900,8 @@ export declare interface UnmatchedInstance {
1152
900
  }
1153
901
 
1154
902
  /**
1155
- * Why an instance could not be matched.
1156
- *
1157
- * Both are reported rather than skipped: a glob is the caller asserting these
1158
- * directories are instances, so an instance matching nothing is a real finding,
1159
- * and a tie means two templates are indistinguishable.
903
+ * Why an instance went unmatched. Reported, not skipped: a glob asserts the
904
+ * directory is an instance, so no match is a finding.
1160
905
  */
1161
906
  export declare type UnmatchedReason = "ambiguous" | "no-match";
1162
907
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "url": "https://github.com/organizzolini/codebase/issues"
5
5
  },
6
6
  "dependencies": {
7
- "@conformetry/core": "0.0.77",
7
+ "@conformetry/core": "0.0.79",
8
8
  "@nestjs/common": "^11.1.21 || ^12.0.1",
9
9
  "jiti": "^2.7.0",
10
10
  "jsonc-parser": "^3.3.1",
@@ -24,9 +24,9 @@
24
24
  "@types/mustache": "^4.2.6",
25
25
  "@types/node": "^26.5.1",
26
26
  "@types/prompts": "^2.4.9",
27
- "@vitest/coverage-v8": "^5.0.0",
27
+ "@vitest/coverage-v8": "^5.1.0",
28
28
  "typescript": "^6.0.3",
29
- "vitest": "^5.0.0"
29
+ "vitest": "^5.1.0"
30
30
  },
31
31
  "exports": {
32
32
  ".": {
@@ -68,5 +68,5 @@
68
68
  "strict": true
69
69
  },
70
70
  "types": "./dist/src/index.d.ts",
71
- "version": "0.0.79"
71
+ "version": "0.0.81"
72
72
  }