@design.estate/wcctools 6.0.0 → 6.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.
- package/changelog.md +13 -0
- package/dist_shell/bundle.js +3 -3
- package/dist_shell/bundle.js.map +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cli.js +8 -2
- package/dist_ts/plugins.d.ts +7 -2
- package/dist_ts/plugins.js +9 -3
- package/dist_ts/standards/baselines.d.ts +27 -0
- package/dist_ts/standards/baselines.js +83 -0
- package/dist_ts/standards/checker.d.ts +21 -0
- package/dist_ts/standards/checker.js +88 -0
- package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
- package/dist_ts/standards/classes.gitrepo.js +43 -0
- package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
- package/dist_ts/standards/classes.sourceedits.js +54 -0
- package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
- package/dist_ts/standards/classes.standardfixer.js +210 -0
- package/dist_ts/standards/classes.standardproject.d.ts +80 -0
- package/dist_ts/standards/classes.standardproject.js +195 -0
- package/dist_ts/standards/classes.standardtree.d.ts +56 -0
- package/dist_ts/standards/classes.standardtree.js +207 -0
- package/dist_ts/standards/cli.d.ts +7 -0
- package/dist_ts/standards/cli.js +89 -0
- package/dist_ts/standards/config.d.ts +33 -0
- package/dist_ts/standards/config.js +139 -0
- package/dist_ts/standards/errors.d.ts +9 -0
- package/dist_ts/standards/errors.js +17 -0
- package/dist_ts/standards/helpers.ast.d.ts +56 -0
- package/dist_ts/standards/helpers.ast.js +172 -0
- package/dist_ts/standards/helpers.paths.d.ts +36 -0
- package/dist_ts/standards/helpers.paths.js +86 -0
- package/dist_ts/standards/index.d.ts +14 -0
- package/dist_ts/standards/index.js +15 -0
- package/dist_ts/standards/output.d.ts +7 -0
- package/dist_ts/standards/output.js +57 -0
- package/dist_ts/standards/ratchet.d.ts +15 -0
- package/dist_ts/standards/ratchet.js +45 -0
- package/dist_ts/standards/rule.d.ts +50 -0
- package/dist_ts/standards/rule.js +9 -0
- package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
- package/dist_ts/standards/rules/barrel.element-index.js +108 -0
- package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
- package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
- package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
- package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
- package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
- package/dist_ts/standards/rules/demo.groups.js +72 -0
- package/dist_ts/standards/rules/demo.required.d.ts +3 -0
- package/dist_ts/standards/rules/demo.required.js +48 -0
- package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
- package/dist_ts/standards/rules/demo.separate-file.js +38 -0
- package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
- package/dist_ts/standards/rules/demo.shape.js +38 -0
- package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
- package/dist_ts/standards/rules/docs.component-index.js +84 -0
- package/dist_ts/standards/rules/element.exported.d.ts +3 -0
- package/dist_ts/standards/rules/element.exported.js +33 -0
- package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
- package/dist_ts/standards/rules/element.literal-tag.js +30 -0
- package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
- package/dist_ts/standards/rules/element.reachable.js +48 -0
- package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
- package/dist_ts/standards/rules/element.tag-map.js +83 -0
- package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
- package/dist_ts/standards/rules/i18n.literals.js +52 -0
- package/dist_ts/standards/rules/index.d.ts +12 -0
- package/dist_ts/standards/rules/index.js +83 -0
- package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
- package/dist_ts/standards/rules/layout.element-folder.js +47 -0
- package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
- package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
- package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
- package/dist_ts/standards/rules/layout.entry.js +38 -0
- package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
- package/dist_ts/standards/rules/layout.group-folder.js +22 -0
- package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
- package/dist_ts/standards/rules/layout.shared-00.js +36 -0
- package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
- package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
- package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
- package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
- package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
- package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
- package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
- package/dist_ts/standards/rules/props.accessor.js +35 -0
- package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
- package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
- package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
- package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
- package/dist_ts/standards/rules/props.typed.d.ts +6 -0
- package/dist_ts/standards/rules/props.typed.js +64 -0
- package/dist_ts/standards/rules/shared.d.ts +38 -0
- package/dist_ts/standards/rules/shared.js +103 -0
- package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
- package/dist_ts/standards/rules/style.bdtheme.js +28 -0
- package/dist_ts_interfaces/index.d.ts +1 -0
- package/dist_ts_interfaces/index.js +2 -1
- package/dist_ts_interfaces/standard.d.ts +93 -0
- package/dist_ts_interfaces/standard.js +6 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +4 -2
- package/readme.md +34 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/cli.ts +8 -1
- package/ts/plugins.ts +10 -2
- package/ts/standards/baselines.ts +100 -0
- package/ts/standards/checker.ts +114 -0
- package/ts/standards/classes.gitrepo.ts +48 -0
- package/ts/standards/classes.sourceedits.ts +58 -0
- package/ts/standards/classes.standardfixer.ts +234 -0
- package/ts/standards/classes.standardproject.ts +250 -0
- package/ts/standards/classes.standardtree.ts +220 -0
- package/ts/standards/cli.ts +86 -0
- package/ts/standards/config.ts +160 -0
- package/ts/standards/errors.ts +18 -0
- package/ts/standards/helpers.ast.ts +208 -0
- package/ts/standards/helpers.paths.ts +119 -0
- package/ts/standards/index.ts +22 -0
- package/ts/standards/output.ts +65 -0
- package/ts/standards/ratchet.ts +63 -0
- package/ts/standards/rule.ts +58 -0
- package/ts/standards/rules/barrel.element-index.ts +112 -0
- package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
- package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
- package/ts/standards/rules/demo.groups.ts +74 -0
- package/ts/standards/rules/demo.required.ts +49 -0
- package/ts/standards/rules/demo.separate-file.ts +40 -0
- package/ts/standards/rules/demo.shape.ts +42 -0
- package/ts/standards/rules/docs.component-index.ts +88 -0
- package/ts/standards/rules/element.exported.ts +35 -0
- package/ts/standards/rules/element.literal-tag.ts +30 -0
- package/ts/standards/rules/element.reachable.ts +49 -0
- package/ts/standards/rules/element.tag-map.ts +87 -0
- package/ts/standards/rules/i18n.literals.ts +58 -0
- package/ts/standards/rules/index.ts +87 -0
- package/ts/standards/rules/layout.element-folder.ts +49 -0
- package/ts/standards/rules/layout.entry-file-name.ts +73 -0
- package/ts/standards/rules/layout.entry.ts +40 -0
- package/ts/standards/rules/layout.group-folder.ts +23 -0
- package/ts/standards/rules/layout.shared-00.ts +37 -0
- package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
- package/ts/standards/rules/naming.lowercase-files.ts +27 -0
- package/ts/standards/rules/naming.tag-prefix.ts +24 -0
- package/ts/standards/rules/props.accessor.ts +37 -0
- package/ts/standards/rules/props.object-no-attribute.ts +45 -0
- package/ts/standards/rules/props.reflect-primitive.ts +44 -0
- package/ts/standards/rules/props.typed.ts +70 -0
- package/ts/standards/rules/shared.ts +127 -0
- package/ts/standards/rules/style.bdtheme.ts +31 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as ast from './helpers.ast.js';
|
|
3
|
+
import { baseOf, isRepoPath, isTypeScriptSource, resolveSpecifier, specifierFor } from './helpers.paths.js';
|
|
4
|
+
import { SourceEdits } from './classes.sourceedits.js';
|
|
5
|
+
import { StandardProject } from './classes.standardproject.js';
|
|
6
|
+
const ts = plugins.typescript;
|
|
7
|
+
/** The changes one rule run collected. */
|
|
8
|
+
export class FixBatch {
|
|
9
|
+
edits = new Map();
|
|
10
|
+
creates = new Map();
|
|
11
|
+
moves = new Map();
|
|
12
|
+
redirects = new Map();
|
|
13
|
+
edit(fileArg, startArg, endArg, textArg) {
|
|
14
|
+
this.edits.set(fileArg, [...(this.edits.get(fileArg) ?? []), { start: startArg, end: endArg, text: textArg }]);
|
|
15
|
+
}
|
|
16
|
+
create(fileArg, textArg) {
|
|
17
|
+
if (!this.creates.has(fileArg)) {
|
|
18
|
+
this.creates.set(fileArg, textArg);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
move(fromArg, toArg) {
|
|
22
|
+
if (!this.moves.has(fromArg)) {
|
|
23
|
+
this.moves.set(fromArg, toArg);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
redirectBarrelExports(targetArg, barrelTargetArg) {
|
|
27
|
+
this.redirects.set(targetArg, barrelTargetArg);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The fixer's in-memory copy of a repository: the tracked TypeScript sources and the side files the
|
|
32
|
+
* standard reads, with the moves and edits applied so far. Nothing touches the disk until the
|
|
33
|
+
* fixer commits the tree. Every path a batch names must be a repository path (see isRepoPath);
|
|
34
|
+
* a batch with any other path is rejected before it changes the tree.
|
|
35
|
+
*/
|
|
36
|
+
export class StandardTree {
|
|
37
|
+
files;
|
|
38
|
+
originalTexts = new Map();
|
|
39
|
+
/** Current path → original path, for moved files. */
|
|
40
|
+
originOf = new Map();
|
|
41
|
+
/** Original paths that were moved away. */
|
|
42
|
+
vacated = new Set();
|
|
43
|
+
created = new Set();
|
|
44
|
+
/** Current path → ids of the rules that changed the file. */
|
|
45
|
+
changedBy = new Map();
|
|
46
|
+
parseCache = new Map();
|
|
47
|
+
/** Every tracked file of the repository, including those the tree holds no text for (`.json`, `.css`, `.d.ts`, …). */
|
|
48
|
+
trackedFiles;
|
|
49
|
+
existsOnDisk;
|
|
50
|
+
constructor(filesArg, trackedFilesArg, existsOnDiskArg) {
|
|
51
|
+
this.files = new Map(filesArg);
|
|
52
|
+
for (const [file, text] of filesArg) {
|
|
53
|
+
this.originalTexts.set(file, text);
|
|
54
|
+
}
|
|
55
|
+
this.trackedFiles = new Set(trackedFilesArg);
|
|
56
|
+
this.existsOnDisk = existsOnDiskArg;
|
|
57
|
+
}
|
|
58
|
+
exists(fileArg) {
|
|
59
|
+
return this.files.has(fileArg) || (!this.vacated.has(fileArg) && this.existsOnDisk(fileArg));
|
|
60
|
+
}
|
|
61
|
+
/** The model of the tree's current state. */
|
|
62
|
+
project() {
|
|
63
|
+
return new StandardProject(this.files, (fileArg) => this.exists(fileArg), this.parseCache);
|
|
64
|
+
}
|
|
65
|
+
markChanged(fileArg, ruleIdArg) {
|
|
66
|
+
this.changedBy.set(fileArg, new Set([...(this.changedBy.get(fileArg) ?? []), ruleIdArg]));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Applies a batch: edits, then new files, then moves with import rewriting. Returns the number of
|
|
70
|
+
* applied changes. Throws without changing the tree when the batch names a path that is not a
|
|
71
|
+
* repository path.
|
|
72
|
+
*/
|
|
73
|
+
apply(ruleIdArg, batchArg) {
|
|
74
|
+
const outside = [
|
|
75
|
+
...batchArg.edits.keys(),
|
|
76
|
+
...batchArg.creates.keys(),
|
|
77
|
+
...[...batchArg.moves].flat(),
|
|
78
|
+
...[...batchArg.redirects].flat(),
|
|
79
|
+
].filter((pathArg) => !isRepoPath(pathArg));
|
|
80
|
+
if (outside.length > 0) {
|
|
81
|
+
throw new Error(`The fix of ${ruleIdArg} names paths outside the repository root: ${[...new Set(outside)].join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
let applied = 0;
|
|
84
|
+
for (const [file, edits] of batchArg.edits) {
|
|
85
|
+
const text = this.files.get(file);
|
|
86
|
+
if (text === undefined) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const sourceEdits = new SourceEdits();
|
|
90
|
+
edits.forEach((editArg) => sourceEdits.add(editArg));
|
|
91
|
+
const next = sourceEdits.apply(text);
|
|
92
|
+
if (next !== text) {
|
|
93
|
+
this.files.set(file, next);
|
|
94
|
+
this.markChanged(file, ruleIdArg);
|
|
95
|
+
applied += sourceEdits.size;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const [file, text] of batchArg.creates) {
|
|
99
|
+
if (this.exists(file)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
this.files.set(file, text);
|
|
103
|
+
this.created.add(file);
|
|
104
|
+
this.markChanged(file, ruleIdArg);
|
|
105
|
+
applied++;
|
|
106
|
+
}
|
|
107
|
+
const moves = new Map();
|
|
108
|
+
const targets = new Set();
|
|
109
|
+
for (const [from, to] of batchArg.moves) {
|
|
110
|
+
if (from === to || !this.files.has(from) || targets.has(to) || (this.exists(to) && !batchArg.moves.has(to))) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
moves.set(from, to);
|
|
114
|
+
targets.add(to);
|
|
115
|
+
}
|
|
116
|
+
if (moves.size > 0) {
|
|
117
|
+
this.rewriteSpecifiers(ruleIdArg, moves, batchArg.redirects);
|
|
118
|
+
const texts = new Map([...moves.keys()].map((fromArg) => [fromArg, this.files.get(fromArg)]));
|
|
119
|
+
for (const [from, to] of moves) {
|
|
120
|
+
this.files.delete(from);
|
|
121
|
+
if (this.created.delete(from)) {
|
|
122
|
+
this.created.add(to);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
const origin = this.originOf.get(from) ?? from;
|
|
126
|
+
this.originOf.delete(from);
|
|
127
|
+
if (origin !== to) {
|
|
128
|
+
this.originOf.set(to, origin);
|
|
129
|
+
}
|
|
130
|
+
if (origin === from) {
|
|
131
|
+
this.vacated.add(from);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const changed = this.changedBy.get(from);
|
|
135
|
+
this.changedBy.delete(from);
|
|
136
|
+
if (changed) {
|
|
137
|
+
this.changedBy.set(to, changed);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
for (const [from, to] of moves) {
|
|
141
|
+
this.files.set(to, texts.get(from));
|
|
142
|
+
this.vacated.delete(to);
|
|
143
|
+
}
|
|
144
|
+
applied += moves.size;
|
|
145
|
+
}
|
|
146
|
+
return applied;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Rewrites every relative module specifier whose importing file or target moves, keeping its
|
|
150
|
+
* extension style. A specifier resolves to any tracked file (sources, `.d.ts`, `.json`, `.css`, …),
|
|
151
|
+
* so a moved file's imports of files that stay keep pointing at them. Barrel re-exports of a
|
|
152
|
+
* redirected target point at the redirect instead.
|
|
153
|
+
*/
|
|
154
|
+
rewriteSpecifiers(ruleIdArg, movesArg, redirectsArg) {
|
|
155
|
+
const known = (fileArg) => this.files.has(fileArg) || (this.trackedFiles.has(fileArg) && !this.vacated.has(fileArg));
|
|
156
|
+
const project = this.project();
|
|
157
|
+
for (const [file, text] of [...this.files]) {
|
|
158
|
+
if (!isTypeScriptSource(file)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const newFile = movesArg.get(file) ?? file;
|
|
162
|
+
const sourceFile = project.sourceFile(file);
|
|
163
|
+
const edits = new SourceEdits();
|
|
164
|
+
for (const literal of ast.moduleSpecifierLiterals(sourceFile)) {
|
|
165
|
+
const resolved = resolveSpecifier(file, literal.text, known);
|
|
166
|
+
if (!resolved) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
let target = movesArg.get(resolved.target) ?? resolved.target;
|
|
170
|
+
let viaFolder = resolved.viaFolder;
|
|
171
|
+
const redirect = redirectsArg.get(resolved.target);
|
|
172
|
+
if (redirect && redirect !== newFile && ts.isExportDeclaration(literal.parent) && baseOf(newFile) === 'index.ts') {
|
|
173
|
+
target = redirect;
|
|
174
|
+
viaFolder = true;
|
|
175
|
+
}
|
|
176
|
+
if (newFile === file && target === resolved.target) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const specifier = specifierFor(newFile, target, resolved.style, viaFolder);
|
|
180
|
+
if (specifier !== literal.text) {
|
|
181
|
+
edits.add({ start: literal.getStart() + 1, end: literal.end - 1, text: specifier });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (edits.size > 0) {
|
|
185
|
+
this.files.set(file, edits.apply(text));
|
|
186
|
+
this.markChanged(file, ruleIdArg);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** The tree's changes against the repository it was read from. */
|
|
191
|
+
plan() {
|
|
192
|
+
const moves = [...this.originOf].map(([to, from]) => ({ from, to })).sort((a, b) => a.from.localeCompare(b.from));
|
|
193
|
+
const created = [...this.created].sort();
|
|
194
|
+
const edited = [];
|
|
195
|
+
for (const [file, ruleIds] of [...this.changedBy].sort(([a], [b]) => a.localeCompare(b))) {
|
|
196
|
+
if (this.created.has(file)) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const origin = this.originOf.get(file) ?? file;
|
|
200
|
+
if (this.files.get(file) !== this.originalTexts.get(origin)) {
|
|
201
|
+
edited.push({ file, ruleIds: [...ruleIds].sort() });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return { moves, created, edited };
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdGFuZGFyZHRyZWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9zdGFuZGFyZHMvY2xhc3Nlcy5zdGFuZGFyZHRyZWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxLQUFLLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQztBQUN4QyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxrQkFBa0IsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1RyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBb0IsTUFBTSw4QkFBOEIsQ0FBQztBQUdqRixNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO0FBRTlCLDBDQUEwQztBQUMxQyxNQUFNLE9BQU8sUUFBUTtJQUNILEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztJQUNoRCxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDcEMsS0FBSyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQ2xDLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUUvQyxJQUFJLENBQUMsT0FBZSxFQUFFLFFBQWdCLEVBQUUsTUFBYyxFQUFFLE9BQWU7UUFDNUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakgsQ0FBQztJQUVNLE1BQU0sQ0FBQyxPQUFlLEVB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
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* Registers `wcctools check` and `wcctools fix`. Both work on the current directory, the
|
|
4
|
+
* repository root that holds `.smartconfig.json`. Exit codes: 0 ok, 1 failing findings or a
|
|
5
|
+
* refused baseline update, 2 configuration or usage error (StandardConfigError/StandardUsageError).
|
|
6
|
+
*/
|
|
7
|
+
export declare const registerStandardCommands: (out: plugins.smartconsole.SmartConsole) => void;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { checkStandard } from './checker.js';
|
|
3
|
+
import { loadStandardProject } from './classes.standardproject.js';
|
|
4
|
+
import { StandardFixer } from './classes.standardfixer.js';
|
|
5
|
+
import { openStandardConfig } from './config.js';
|
|
6
|
+
import { StandardUsageError } from './errors.js';
|
|
7
|
+
import { renderFixResult, renderStandardReport } from './output.js';
|
|
8
|
+
import { initBaselines, updateBaselines } from './ratchet.js';
|
|
9
|
+
/**
|
|
10
|
+
* Registers `wcctools check` and `wcctools fix`. Both work on the current directory, the
|
|
11
|
+
* repository root that holds `.smartconfig.json`. Exit codes: 0 ok, 1 failing findings or a
|
|
12
|
+
* refused baseline update, 2 configuration or usage error (StandardConfigError/StandardUsageError).
|
|
13
|
+
*/
|
|
14
|
+
export const registerStandardCommands = (out) => {
|
|
15
|
+
out.cli.command({
|
|
16
|
+
name: 'check',
|
|
17
|
+
description: 'Check the catalog against the wcctools component standard (https://code.foss.global/design.estate/wcctools/src/branch/main/docs/standard.md)',
|
|
18
|
+
options: {
|
|
19
|
+
json: { type: 'boolean', description: 'Print the report as one JSON document (IStandardReport) and nothing else' },
|
|
20
|
+
verbose: { type: 'boolean', description: 'Also list info findings, findings covered by the allowlist or baselines, and baseline slack' },
|
|
21
|
+
initBaseline: { type: 'boolean', description: 'Record the current error counts as standard.baselines (only while none exist)' },
|
|
22
|
+
updateBaseline: { type: 'boolean', description: 'Lower standard.baselines to the current counts; refuses to raise any count' },
|
|
23
|
+
},
|
|
24
|
+
}, async ({ options }) => {
|
|
25
|
+
if (options.initBaseline && options.updateBaseline) {
|
|
26
|
+
throw new StandardUsageError('--init-baseline and --update-baseline exclude each other');
|
|
27
|
+
}
|
|
28
|
+
const rootDir = process.cwd();
|
|
29
|
+
const opened = openStandardConfig(rootDir);
|
|
30
|
+
const notes = [];
|
|
31
|
+
let report;
|
|
32
|
+
let refused = false;
|
|
33
|
+
if (options.initBaseline || options.updateBaseline) {
|
|
34
|
+
const result = options.initBaseline ? await initBaselines(rootDir, opened) : await updateBaselines(rootDir, opened);
|
|
35
|
+
report = result.report;
|
|
36
|
+
if (result.raised.length > 0) {
|
|
37
|
+
refused = true;
|
|
38
|
+
for (const raise of result.raised) {
|
|
39
|
+
await out.error(`refusing to raise the ${raise.ruleId} baseline of ${raise.file}: ${raise.baseline} → ${raise.current}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
notes.push(`standard.baselines written: ${result.writtenFiles} file(s)`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
report = checkStandard(await loadStandardProject(rootDir), opened.loaded);
|
|
48
|
+
}
|
|
49
|
+
if (options.json) {
|
|
50
|
+
await out.log(JSON.stringify(report));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
for (const line of [...renderStandardReport(report, !!options.verbose), ...notes]) {
|
|
54
|
+
await out.log(line);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
process.exitCode = report.ok && !refused ? 0 : 1;
|
|
58
|
+
});
|
|
59
|
+
out.cli.command({
|
|
60
|
+
name: 'fix',
|
|
61
|
+
description: 'Fix findings of the wcctools component standard with span edits and git mv; needs a clean work tree, never commits',
|
|
62
|
+
options: {
|
|
63
|
+
rule: { type: 'strings', description: 'Fix only this rule (repeatable); opt-in rules run only when named' },
|
|
64
|
+
dryRun: { type: 'boolean', description: 'Show the changes without writing anything' },
|
|
65
|
+
json: { type: 'boolean', description: 'Print the result as one JSON document (IStandardFixResult) and nothing else' },
|
|
66
|
+
verbose: { type: 'boolean', description: 'Also list info and covered findings of the remaining check' },
|
|
67
|
+
},
|
|
68
|
+
}, async ({ options }) => {
|
|
69
|
+
const rootDir = process.cwd();
|
|
70
|
+
const opened = openStandardConfig(rootDir);
|
|
71
|
+
const result = await new StandardFixer({
|
|
72
|
+
rootDir,
|
|
73
|
+
loaded: opened.loaded,
|
|
74
|
+
rules: options.rule,
|
|
75
|
+
dryRun: !!options.dryRun,
|
|
76
|
+
configWriter: opened.writer,
|
|
77
|
+
}).run();
|
|
78
|
+
if (options.json) {
|
|
79
|
+
await out.log(JSON.stringify(result));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
for (const line of renderFixResult(result, !!options.verbose)) {
|
|
83
|
+
await out.log(line);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
process.exitCode = result.remaining.ok ? 0 : 1;
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RhbmRhcmRzL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2pELE9BQU8sRUFBRSxlQUFlLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFOUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLENBQUMsR0FBc0MsRUFBUSxFQUFFO0lBQ3ZGLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDO1FBQ2QsSUFBSSxFQUFFLE9BQU87UUFDYixXQUFXLEVBQUUsOElBQThJO1FBQzNKLE9BQU8sRUFBRTtZQUNQLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLDBFQUEwRSxFQUFFO1lBQ2xILE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLDZGQUE2RixFQUFFO1lBQ3hJLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLCtFQUErRSxFQUFFO1lBQy9ILGNBQWMsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLDRFQUE0RSxFQUFFO1NBQy9IO0tBQ0YsRUFBRSxLQUFLLEVB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
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
type IStandardConfig = plugins.interfaces.IStandardConfig;
|
|
3
|
+
type TStandardProfile = plugins.interfaces.TStandardProfile;
|
|
4
|
+
/** The key of wcctools' configuration in `.smartconfig.json`. */
|
|
5
|
+
export declare const wcctoolsConfigKey = "@design.estate/wcctools";
|
|
6
|
+
/** Persists the `standard` configuration of the repository it was read from. */
|
|
7
|
+
export interface IStandardConfigWriter {
|
|
8
|
+
writeStandardConfig(configArg: IStandardConfig): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export interface ILoadedStandardConfig {
|
|
11
|
+
config: IStandardConfig;
|
|
12
|
+
profile: TStandardProfile;
|
|
13
|
+
}
|
|
14
|
+
/** A validated configuration together with the writer bound to the `.smartconfig.json` it was read from. */
|
|
15
|
+
export interface IOpenedStandardConfig {
|
|
16
|
+
loaded: ILoadedStandardConfig;
|
|
17
|
+
writer: IStandardConfigWriter;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Writes through the Smartconfig instance that read the configuration, so a write is refused
|
|
21
|
+
* (SmartconfigChangedError) when `.smartconfig.json` changed in between. Other keys of the
|
|
22
|
+
* `@design.estate/wcctools` block keep their values.
|
|
23
|
+
*/
|
|
24
|
+
export declare class SmartconfigStandardConfigWriter implements IStandardConfigWriter {
|
|
25
|
+
private readonly smartconfig;
|
|
26
|
+
constructor(smartconfigArg: plugins.smartconfig.Smartconfig);
|
|
27
|
+
writeStandardConfig(configArg: IStandardConfig): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/** Validates the `standard` object; collects every problem into one StandardConfigError. */
|
|
30
|
+
export declare const validateStandardConfig: (valueArg: unknown) => ILoadedStandardConfig;
|
|
31
|
+
/** Reads and validates `.smartconfig.json` → `@design.estate/wcctools` → `standard` of a repository. */
|
|
32
|
+
export declare const openStandardConfig: (rootDirArg: string) => IOpenedStandardConfig;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { StandardConfigError } from './errors.js';
|
|
3
|
+
import { severityIn } from './rule.js';
|
|
4
|
+
import { standardRules } from './rules/index.js';
|
|
5
|
+
/** The key of wcctools' configuration in `.smartconfig.json`. */
|
|
6
|
+
export const wcctoolsConfigKey = '@design.estate/wcctools';
|
|
7
|
+
/**
|
|
8
|
+
* Writes through the Smartconfig instance that read the configuration, so a write is refused
|
|
9
|
+
* (SmartconfigChangedError) when `.smartconfig.json` changed in between. Other keys of the
|
|
10
|
+
* `@design.estate/wcctools` block keep their values.
|
|
11
|
+
*/
|
|
12
|
+
export class SmartconfigStandardConfigWriter {
|
|
13
|
+
smartconfig;
|
|
14
|
+
constructor(smartconfigArg) {
|
|
15
|
+
this.smartconfig = smartconfigArg;
|
|
16
|
+
}
|
|
17
|
+
async writeStandardConfig(configArg) {
|
|
18
|
+
const block = this.smartconfig.dataFor(wcctoolsConfigKey, {});
|
|
19
|
+
await this.smartconfig.writeDataFor(wcctoolsConfigKey, { ...block, standard: configArg });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const isPlainObject = (valueArg) => typeof valueArg === 'object' && valueArg !== null && !Array.isArray(valueArg);
|
|
23
|
+
const knownKeys = ['profile', 'tagPrefix', 'groupNames', 'allowlist', 'baselines'];
|
|
24
|
+
/** Validates the `standard` object; collects every problem into one StandardConfigError. */
|
|
25
|
+
export const validateStandardConfig = (valueArg) => {
|
|
26
|
+
const problems = [];
|
|
27
|
+
if (valueArg === undefined) {
|
|
28
|
+
throw new StandardConfigError([`"${wcctoolsConfigKey}".standard is missing`]);
|
|
29
|
+
}
|
|
30
|
+
if (!isPlainObject(valueArg)) {
|
|
31
|
+
throw new StandardConfigError([`"${wcctoolsConfigKey}".standard must be an object`]);
|
|
32
|
+
}
|
|
33
|
+
for (const key of Object.keys(valueArg)) {
|
|
34
|
+
if (!knownKeys.includes(key)) {
|
|
35
|
+
problems.push(`standard.${key} is not a known key (${knownKeys.join(', ')})`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const profile = valueArg.profile ?? 'base';
|
|
39
|
+
if (profile !== 'base' && profile !== 'dees') {
|
|
40
|
+
problems.push(`standard.profile must be 'base' or 'dees'`);
|
|
41
|
+
}
|
|
42
|
+
if (valueArg.tagPrefix === undefined) {
|
|
43
|
+
problems.push('standard.tagPrefix is missing');
|
|
44
|
+
}
|
|
45
|
+
else if (typeof valueArg.tagPrefix !== 'string' || !/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(valueArg.tagPrefix)) {
|
|
46
|
+
problems.push('standard.tagPrefix must be a lowercase tag prefix without the trailing hyphen, e.g. "dees"');
|
|
47
|
+
}
|
|
48
|
+
if (valueArg.groupNames !== undefined) {
|
|
49
|
+
if (!isPlainObject(valueArg.groupNames)) {
|
|
50
|
+
problems.push('standard.groupNames must be an object of area → display name');
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
for (const [area, name] of Object.entries(valueArg.groupNames)) {
|
|
54
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
55
|
+
problems.push(`standard.groupNames.${area} must be a non-empty string`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const rulesById = new Map(standardRules.map((ruleArg) => [ruleArg.id, ruleArg]));
|
|
61
|
+
if (valueArg.allowlist !== undefined) {
|
|
62
|
+
if (!isPlainObject(valueArg.allowlist)) {
|
|
63
|
+
problems.push('standard.allowlist must be an object of rule id → entries');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
for (const [ruleId, entries] of Object.entries(valueArg.allowlist)) {
|
|
67
|
+
const rule = rulesById.get(ruleId);
|
|
68
|
+
if (!rule) {
|
|
69
|
+
problems.push(`standard.allowlist: unknown rule '${ruleId}'`);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!rule.allowlistCategories) {
|
|
73
|
+
problems.push(`standard.allowlist: rule '${ruleId}' takes no allowlist entries`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (!isPlainObject(entries)) {
|
|
77
|
+
problems.push(`standard.allowlist['${ruleId}'] must be an object of '<file>#<member>' → '<category>: <reason>'`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
81
|
+
const match = typeof value === 'string' ? /^([a-z-]+):\s*(\S.*)$/.exec(value) : null;
|
|
82
|
+
if (!match) {
|
|
83
|
+
problems.push(`standard.allowlist['${ruleId}']['${key}'] must be '<category>: <reason>'`);
|
|
84
|
+
}
|
|
85
|
+
else if (!rule.allowlistCategories.includes(match[1])) {
|
|
86
|
+
problems.push(`standard.allowlist['${ruleId}']['${key}']: unknown category '${match[1]}' (${rule.allowlistCategories.join(', ')})`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (valueArg.baselines !== undefined) {
|
|
93
|
+
if (!isPlainObject(valueArg.baselines)) {
|
|
94
|
+
problems.push('standard.baselines must be an object of rule id → file → count');
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
for (const [ruleId, counts] of Object.entries(valueArg.baselines)) {
|
|
98
|
+
const rule = rulesById.get(ruleId);
|
|
99
|
+
if (!rule) {
|
|
100
|
+
problems.push(`standard.baselines: unknown rule '${ruleId}'`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if ((profile === 'base' || profile === 'dees') && severityIn(rule, profile) !== 'error') {
|
|
104
|
+
problems.push(`standard.baselines: '${ruleId}' is not an error rule of the '${profile}' profile; baselines hold error rules only`);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (!isPlainObject(counts)) {
|
|
108
|
+
problems.push(`standard.baselines['${ruleId}'] must be an object of file → count`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
for (const [file, count] of Object.entries(counts)) {
|
|
112
|
+
if (typeof count !== 'number' || !Number.isInteger(count) || count < 1) {
|
|
113
|
+
problems.push(`standard.baselines['${ruleId}']['${file}'] must be an integer of at least 1`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (problems.length > 0) {
|
|
120
|
+
throw new StandardConfigError(problems);
|
|
121
|
+
}
|
|
122
|
+
return { config: valueArg, profile: profile };
|
|
123
|
+
};
|
|
124
|
+
/** Reads and validates `.smartconfig.json` → `@design.estate/wcctools` → `standard` of a repository. */
|
|
125
|
+
export const openStandardConfig = (rootDirArg) => {
|
|
126
|
+
let smartconfig;
|
|
127
|
+
try {
|
|
128
|
+
smartconfig = new plugins.smartconfig.Smartconfig(rootDirArg);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw new StandardConfigError([`.smartconfig.json cannot be read: ${error instanceof Error ? error.message : String(error)}`]);
|
|
132
|
+
}
|
|
133
|
+
if (!smartconfig.smartconfigJsonExists) {
|
|
134
|
+
throw new StandardConfigError([`${rootDirArg} has no .smartconfig.json`]);
|
|
135
|
+
}
|
|
136
|
+
const wcctoolsConfig = smartconfig.dataFor(wcctoolsConfigKey, {});
|
|
137
|
+
return { loaded: validateStandardConfig(wcctoolsConfig.standard), writer: new SmartconfigStandardConfigWriter(smartconfig) };
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RhbmRhcmRzL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN2QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFLakQsaUVBQWlFO0FBQ2pFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLHlCQUF5QixDQUFDO0FBa0IzRDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLCtCQUErQjtJQUN6QixXQUFXLENBQWtDO0lBRTlELFlBQVksY0FBK0M7UUFDekQsSUFBSSxDQUFDLFdBQVcsR0FBRyxjQUFjLENBQUM7SUFDcEMsQ0FBQztJQUVNLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxTQUEwQjtRQUN6RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBMEIsaUJBQWlCLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkYsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLEdBQUcsS0FBSyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQzVGLENBQUM7Q0FDRjtBQUVELE1BQU0sYUFBYSxHQUFHLENBQUMsUUFBaUIsRUFBdUMsRUFBRSxDQUMvRSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFaEYsTUFBTSxTQUFTLEdBQUcsQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7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
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** The `standard` configuration is missing or invalid; the CLI exits with code 2. */
|
|
2
|
+
export declare class StandardConfigError extends Error {
|
|
3
|
+
readonly problems: string[];
|
|
4
|
+
constructor(problemsArg: string[]);
|
|
5
|
+
}
|
|
6
|
+
/** A precondition or argument of `check`/`fix` is not met; the CLI exits with code 2. */
|
|
7
|
+
export declare class StandardUsageError extends Error {
|
|
8
|
+
constructor(messageArg: string);
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The `standard` configuration is missing or invalid; the CLI exits with code 2. */
|
|
2
|
+
export class StandardConfigError extends Error {
|
|
3
|
+
problems;
|
|
4
|
+
constructor(problemsArg) {
|
|
5
|
+
super(`Invalid wcctools standard configuration in .smartconfig.json:\n${problemsArg.map((problemArg) => ` - ${problemArg}`).join('\n')}`);
|
|
6
|
+
this.name = 'StandardConfigError';
|
|
7
|
+
this.problems = problemsArg;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** A precondition or argument of `check`/`fix` is not met; the CLI exits with code 2. */
|
|
11
|
+
export class StandardUsageError extends Error {
|
|
12
|
+
constructor(messageArg) {
|
|
13
|
+
super(messageArg);
|
|
14
|
+
this.name = 'StandardUsageError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RhbmRhcmRzL2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxRkFBcUY7QUFDckYsTUFBTSxPQUFPLG1CQUFvQixTQUFRLEtBQUs7SUFDNUIsUUFBUSxDQUFXO0lBRW5DLFlBQVksV0FBcUI7UUFDL0IsS0FBSyxDQUFDLGtFQUFrRSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxPQUFPLFVBQVUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzSSxJQUFJLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDO1FBQ2xDLElBQUksQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO0lBQzlCLENBQUM7Q0FDRjtBQUVELHlGQUF5RjtBQUN6RixNQUFNLE9BQU8sa0JBQW1CLFNBQVEsS0FBSztJQUMzQyxZQUFZLFVBQWtCO1FBQzVCLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsSUFBSSxHQUFHLG9CQUFvQixDQUFDO0lBQ25DLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
export type TNode = plugins.typescript.Node;
|
|
3
|
+
export type TSourceFile = plugins.typescript.SourceFile;
|
|
4
|
+
export type TClassDeclaration = plugins.typescript.ClassDeclaration;
|
|
5
|
+
export type TClassElement = plugins.typescript.ClassElement;
|
|
6
|
+
export type TPropertyDeclaration = plugins.typescript.PropertyDeclaration;
|
|
7
|
+
export type TObjectLiteralExpression = plugins.typescript.ObjectLiteralExpression;
|
|
8
|
+
export type TCallExpression = plugins.typescript.CallExpression;
|
|
9
|
+
export type TExpression = plugins.typescript.Expression;
|
|
10
|
+
export type TTypeNode = plugins.typescript.TypeNode;
|
|
11
|
+
export type TStringLiteralLike = plugins.typescript.StringLiteralLike;
|
|
12
|
+
export declare const parseSource: (fileArg: string, textArg: string) => TSourceFile;
|
|
13
|
+
/** 1-based line and column of a position. */
|
|
14
|
+
export declare const lineAndColumn: (sourceFileArg: TSourceFile, positionArg: number) => {
|
|
15
|
+
line: number;
|
|
16
|
+
column: number;
|
|
17
|
+
};
|
|
18
|
+
/** The called name of `name(...)` or `a.b.name(...)`. */
|
|
19
|
+
export declare const calleeName: (expressionArg: TExpression) => string | null;
|
|
20
|
+
/** The decorator call named `nameArg` on a node, e.g. `@customElement('x')`. */
|
|
21
|
+
export declare const findDecoratorCall: (nodeArg: TNode, namesArg: readonly string[]) => {
|
|
22
|
+
name: string;
|
|
23
|
+
call: TCallExpression;
|
|
24
|
+
} | null;
|
|
25
|
+
export declare const hasModifier: (nodeArg: TNode, kindArg: plugins.typescript.SyntaxKind) => boolean;
|
|
26
|
+
/** The text of a member name: identifier, private identifier (with '#'), string or numeric literal. */
|
|
27
|
+
export declare const memberNameText: (memberArg: TClassElement) => string | null;
|
|
28
|
+
export declare const isStatic: (memberArg: TNode) => boolean;
|
|
29
|
+
/** The static property declaration `static <name> = …` of a class. */
|
|
30
|
+
export declare const findStaticProperty: (classArg: TClassDeclaration, nameArg: string) => TPropertyDeclaration | null;
|
|
31
|
+
export declare const isStringLiteralLike: (nodeArg: TNode | undefined) => nodeArg is TStringLiteralLike;
|
|
32
|
+
/** A property assignment `key: value` of an object literal, by key. */
|
|
33
|
+
export declare const objectProperty: (objectArg: TObjectLiteralExpression, keyArg: string) => plugins.typescript.PropertyAssignment | null;
|
|
34
|
+
/** The source text of an object literal property's value, or null. */
|
|
35
|
+
export declare const objectPropertyText: (objectArg: TObjectLiteralExpression, keyArg: string) => string | null;
|
|
36
|
+
/** The indentation (leading whitespace) of the line a position is on. */
|
|
37
|
+
export declare const indentationAt: (textArg: string, positionArg: number) => string;
|
|
38
|
+
export interface ITextEdit {
|
|
39
|
+
start: number;
|
|
40
|
+
end: number;
|
|
41
|
+
text: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The edit that adds `propertyTextArg` (e.g. `reflect: true`) as the last property of an object
|
|
45
|
+
* literal, following the literal's own layout: inline literals stay on one line, multi-line
|
|
46
|
+
* literals get a new line with the indentation of their last property.
|
|
47
|
+
*/
|
|
48
|
+
export declare const appendObjectPropertyEdit: (objectArg: TObjectLiteralExpression, propertyTextArg: string) => ITextEdit;
|
|
49
|
+
/** The edit that adds `propertyTextArg` (e.g. `type: String`) as the first property of an object literal. */
|
|
50
|
+
export declare const prependObjectPropertyEdit: (objectArg: TObjectLiteralExpression, propertyTextArg: string) => ITextEdit;
|
|
51
|
+
/** The position after the last import declaration, at the start of the following line; 0 without imports. */
|
|
52
|
+
export declare const afterLastImport: (sourceFileArg: TSourceFile) => number;
|
|
53
|
+
/** The module an identifier is imported from in a file, e.g. `html` → `lit`. */
|
|
54
|
+
export declare const importSourceOf: (sourceFileArg: TSourceFile, identifierArg: string) => string | null;
|
|
55
|
+
/** Every relative-capable module specifier literal of a file: imports, re-exports, dynamic `import()` and `import('…')` types. */
|
|
56
|
+
export declare const moduleSpecifierLiterals: (sourceFileArg: TSourceFile) => TStringLiteralLike[];
|