@cosyte/script-utils 0.0.2 → 0.1.0

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.
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Types for `@cosyte/script-utils/internal-refs`: the shared internal-reference gate.
3
+ *
4
+ * The engine owns the canonical rule set, the self-test floor, enumeration, the completeness rule,
5
+ * the tarball drift tripwire, every refusal and the hit report. The caller owns the axes below: what
6
+ * its prefixes are, which standards designations must never be flagged, what its public surface is,
7
+ * what its tarball already accounts for, and whether the source doc-comment pass runs.
8
+ */
9
+
10
+ /** One entry of the documented configuration surface. */
11
+ export interface ConfigAxis {
12
+ /** The option name a caller writes. */
13
+ name: string;
14
+ /** `true` when there is deliberately no default, because it is the axis a port gets wrong. */
15
+ required: boolean;
16
+ /** `true` when an empty value is refused as well as an absent one. */
17
+ refusesEmpty: boolean;
18
+ /** What the default is, in words, for a defaulted axis. */
19
+ default?: string;
20
+ /** What the axis decides. */
21
+ summary: string;
22
+ }
23
+
24
+ /**
25
+ * THE DOCUMENTED CONFIGURATION SURFACE, enumerable rather than only readable.
26
+ *
27
+ * A grader walks this table to assert that no value of any axis makes a run which found something
28
+ * exit 0. Prose quantifying over "any flag or setting" cannot be failed by a test; a table can.
29
+ */
30
+ export declare const CONFIG_AXES: readonly ConfigAxis[];
31
+
32
+ /** The three codes this gate returns. */
33
+ export interface InternalRefsExitCodes {
34
+ /** The run completed, read every target it enumerated, passed its self-tests and found nothing. */
35
+ clean: number;
36
+ /** This surface carries internal bookkeeping. */
37
+ hits: number;
38
+ /** The run could not account for something, so its answer is not a verdict on the tree. */
39
+ refuse: number;
40
+ }
41
+
42
+ /** A rule a caller ADDS. It joins the canonical set and the self-test floor on the same terms. */
43
+ export interface ExtraRule {
44
+ /** A stable id of the caller's own. Reusing a canonical id is refused. */
45
+ id: string;
46
+ /** What a hit report calls it. */
47
+ name: string;
48
+ /** One pattern, as a source string or a `RegExp`. */
49
+ pattern?: string | RegExp;
50
+ /** Several patterns, when one rule needs two case policies. */
51
+ patterns?: (string | RegExp)[];
52
+ /** Text this rule MUST match. At least one is required. */
53
+ positives: string[];
54
+ /** Text this rule must NOT match. At least one is required: it is what stops a widening. */
55
+ negatives: string[];
56
+ }
57
+
58
+ /** Additive self-test material, keyed by rule id. Nothing here can remove a canonical sample. */
59
+ export type ExtraSamples = Record<string, { positives?: string[]; negatives?: string[] }>;
60
+
61
+ /** Whether the source doc-comment pass runs, over what, and with which extra rules. */
62
+ export interface SourceDocCommentsAxis {
63
+ /** @default false */
64
+ enabled: boolean;
65
+ /** Tracked pathspecs holding the source whose doc comments compile into shipped declarations. */
66
+ paths?: string[];
67
+ /** Detection that applies to the source surface only. */
68
+ extraRules?: ExtraRule[];
69
+ }
70
+
71
+ export interface InternalRefsConfig {
72
+ /**
73
+ * AXIS 1, REQUIRED. The project and programme prefixes an identifier is keyed on, and an empty
74
+ * set is refused.
75
+ *
76
+ * KEYING ON KNOWN PREFIXES RATHER THAN ON A `WORD-N` SHAPE IS THE WHOLE DESIGN. A shape rule
77
+ * flags `MSH-2`, `PID-3` and `OBX-5`, which are segment-field references a consumer of a parser
78
+ * needs, and so destroys the documentation the gate was added to protect. The cost is that a new
79
+ * programme means adding its prefix here by hand; that is the cheaper of the two mistakes.
80
+ */
81
+ projectPrefixes: string[];
82
+
83
+ /**
84
+ * AXIS 2, REQUIRED. Regular-expression sources for standards designations that must NEVER be
85
+ * flagged, even where they collide with a prefix.
86
+ *
87
+ * An explicitly empty list is accepted and declares that this repository's docs carry no
88
+ * designation that collides. Omitting the axis is refused, because "there are none" and "nobody
89
+ * thought about it" must not look the same.
90
+ */
91
+ standardsDesignations: string[];
92
+
93
+ /**
94
+ * AXIS 3, REQUIRED. The public surface, as repo-relative paths, and an empty list is refused.
95
+ * Every entry must be tracked: a renamed page otherwise shrinks the scan in silence.
96
+ */
97
+ surfacePaths: string[];
98
+
99
+ /**
100
+ * AXIS 4, REQUIRED. The `package.json` `files` entries this repository has already accounted for,
101
+ * by scanning them or by excluding them deliberately.
102
+ *
103
+ * `surfacePaths` counts as accounted, so this axis carries the DELIBERATE EXCLUSIONS. Anything in
104
+ * `files` that appears in neither list trips the tarball drift tripwire, because it is public
105
+ * surface a consumer receives that this gate does not read.
106
+ */
107
+ accountedTarballFiles: string[];
108
+
109
+ /**
110
+ * AXIS 5, DEFAULTED OFF. The source doc-comment pass.
111
+ *
112
+ * @default { enabled: false }
113
+ */
114
+ sourceDocComments?: SourceDocCommentsAxis;
115
+
116
+ /**
117
+ * AXIS 6, DEFAULTED. `clean` must be 0 and the other two must not be, which is checked: a mapping
118
+ * that put `hits` on 0 would turn every finding into a green run.
119
+ *
120
+ * @default { clean: 0, hits: 1, refuse: 1 }
121
+ */
122
+ exitCodes?: InternalRefsExitCodes;
123
+
124
+ /**
125
+ * Detection this repository ADDS. A caller may add and may not subtract.
126
+ *
127
+ * @default []
128
+ */
129
+ extraRules?: ExtraRule[];
130
+
131
+ /**
132
+ * Extra self-test samples for the canonical rules, keyed by rule id. This is where a repository's
133
+ * own measured reference material lives: the concrete designations, field names and phrasings its
134
+ * documentation legitimately carries.
135
+ *
136
+ * @default {}
137
+ */
138
+ extraSamples?: ExtraSamples;
139
+
140
+ /**
141
+ * Where the repository under test is. The scan anchors at its git top level either way.
142
+ *
143
+ * @default process.cwd()
144
+ */
145
+ repoRoot?: string;
146
+
147
+ /**
148
+ * Where the report goes. It changes where text lands and nothing about what the run concludes.
149
+ *
150
+ * @default process.stdout.write / process.stderr.write
151
+ */
152
+ write?: { out?: (text: string) => void; err?: (text: string) => void };
153
+ }
154
+
155
+ /** A compiled rule, as the self-test floor and a conformance corpus see it. */
156
+ export interface CompiledRule {
157
+ id: string;
158
+ name: string;
159
+ patterns: RegExp[];
160
+ positives: string[];
161
+ negatives: string[];
162
+ }
163
+
164
+ /**
165
+ * Run the gate and return an exit code drawn from `config.exitCodes`. Nothing here calls
166
+ * `process.exit`, so a test can drive it in process.
167
+ *
168
+ * @example
169
+ * process.exit(
170
+ * runInternalRefsScan({
171
+ * projectPrefixes: ["HL7", "CCDA"],
172
+ * standardsDesignations: ["HL7-(?:V2|V3|CDA)"],
173
+ * surfacePaths: ["README.md", "docs-content"],
174
+ * accountedTarballFiles: ["CHANGELOG.md", "dist"],
175
+ * }),
176
+ * );
177
+ */
178
+ export declare function runInternalRefsScan(config: InternalRefsConfig): number;
179
+
180
+ /** The canonical rule set's identity: a stable id and the name a hit report prints, in run order. */
181
+ export declare const CANONICAL_RULE_INDEX: readonly { id: string; name: string }[];
182
+
183
+ /**
184
+ * What the scan may do with one tracked entry, from the mode `git ls-files -s` recorded for it.
185
+ *
186
+ * `skip` is a gitlink and is the only entry the scan may pass over; `read` is a regular blob or a
187
+ * symbolic link; `refuse` is everything else, including a mode this version has never seen.
188
+ */
189
+ export declare function classifyTrackedMode(mode: string): "skip" | "read" | "refuse";
190
+
191
+ /** The reader-facing names of the canonical rules, in the order they run. */
192
+ export declare function canonicalRuleNames(): string[];
193
+
194
+ /** Compile the canonical rule set against one resolved configuration. */
195
+ export declare function compileCanonicalRules(resolved: InternalRefsConfig): CompiledRule[];
196
+
197
+ /** Check a caller's configuration and fill in the defaults, without running anything. */
198
+ export declare function resolveConfig(config: unknown): {
199
+ resolved?: InternalRefsConfig;
200
+ problems?: string[];
201
+ codes: InternalRefsExitCodes;
202
+ };
203
+
204
+ /** Prove every rule still matches its positives and still lets its negatives through. */
205
+ export declare function runSelfTests(rules: CompiledRule[]): string[];
206
+
207
+ /** Join a document the way markdown renders it, so a violation that straddles a wrap is visible. */
208
+ export declare function reflowParagraphs(text: string): string[];
209
+
210
+ /** Extract doc-comment text from one source file, with each line's location beside it. */
211
+ export declare function extractDocComments(
212
+ text: string,
213
+ file: string,
214
+ ): {
215
+ lines: { text: string; where: string }[];
216
+ paragraphs: { text: string; where: string }[];
217
+ };
218
+
219
+ /** The defaulted exit-code mapping. */
220
+ export declare const DEFAULT_EXIT_CODES: InternalRefsExitCodes;
221
+
222
+ /** Option names refused by name, with the reason each one is not something a caller may supply. */
223
+ export declare const REFUSED_OPTIONS: ReadonlyMap<string, string>;