@venizia/dev-configs 0.4.1 → 0.4.3

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.
Files changed (47) hide show
  1. package/README.md +5 -3
  2. package/dist/cli/clean.d.ts +2 -1
  3. package/dist/cli/clean.d.ts.map +1 -1
  4. package/dist/cli/clean.js +28 -1
  5. package/dist/cli/clean.js.map +1 -1
  6. package/dist/cli/codemod/files.d.ts +22 -0
  7. package/dist/cli/codemod/files.d.ts.map +1 -0
  8. package/dist/cli/codemod/files.js +68 -0
  9. package/dist/cli/codemod/files.js.map +1 -0
  10. package/dist/cli/codemod/index.d.ts +13 -0
  11. package/dist/cli/codemod/index.d.ts.map +1 -0
  12. package/dist/cli/codemod/index.js +106 -0
  13. package/dist/cli/codemod/index.js.map +1 -0
  14. package/dist/cli/codemod/model-settings.d.ts +34 -0
  15. package/dist/cli/codemod/model-settings.d.ts.map +1 -0
  16. package/dist/cli/codemod/model-settings.js +307 -0
  17. package/dist/cli/codemod/model-settings.js.map +1 -0
  18. package/dist/cli/index.js +17 -2
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/linters/house/common.d.ts +1 -0
  21. package/dist/linters/house/common.d.ts.map +1 -1
  22. package/dist/linters/house/common.js +1 -0
  23. package/dist/linters/house/common.js.map +1 -1
  24. package/dist/linters/house/configs.d.ts.map +1 -1
  25. package/dist/linters/house/configs.js +20 -1
  26. package/dist/linters/house/configs.js.map +1 -1
  27. package/dist/linters/house/const-class-values.rule.d.ts +7 -4
  28. package/dist/linters/house/const-class-values.rule.d.ts.map +1 -1
  29. package/dist/linters/house/const-class-values.rule.js +73 -21
  30. package/dist/linters/house/const-class-values.rule.js.map +1 -1
  31. package/dist/linters/rules/common.d.ts +48 -1
  32. package/dist/linters/rules/common.d.ts.map +1 -1
  33. package/dist/linters/rules/common.js +53 -0
  34. package/dist/linters/rules/common.js.map +1 -1
  35. package/dist/linters/rules/eqeqeq.rule.d.ts +2 -2
  36. package/dist/linters/rules/eqeqeq.rule.d.ts.map +1 -1
  37. package/dist/linters/rules/eqeqeq.rule.js +2 -1
  38. package/dist/linters/rules/eqeqeq.rule.js.map +1 -1
  39. package/dist/linters/rules/no-unused-vars.rule.d.ts +3 -3
  40. package/dist/linters/rules/no-unused-vars.rule.d.ts.map +1 -1
  41. package/dist/linters/rules/no-unused-vars.rule.js +2 -1
  42. package/dist/linters/rules/no-unused-vars.rule.js.map +1 -1
  43. package/dist/linters/rules/switch-case-braces.rule.d.ts +2 -2
  44. package/dist/linters/rules/switch-case-braces.rule.d.ts.map +1 -1
  45. package/dist/linters/rules/switch-case-braces.rule.js +2 -1
  46. package/dist/linters/rules/switch-case-braces.rule.js.map +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrateModelSettings = void 0;
4
+ const QUERY_KEYS = { defaultFilter: 'filter', defaultLimit: 'default', maxLimit: 'max' };
5
+ const OLD_KEYS = new Set([...Object.keys(QUERY_KEYS), 'scopeFilter']);
6
+ /**
7
+ * Rewrites `@model({ ... })` from the old keys to the grouped ones. `skipMigrate` becomes
8
+ * `migration: { use: false }`. In the `settings` object literal:
9
+ * `defaultFilter` to `query.filter`, `defaultLimit` and `maxLimit` to `query.limit.default` and
10
+ * `query.limit.max`, `scopeFilter` to `access` (`writeGuard` to `write.mode`, `sharedRows` to
11
+ * `write.sharedRows`).
12
+ *
13
+ * It edits by source range, so comments and formatting outside the rewritten properties stay. It
14
+ * never guesses: a `settings` value that is not an object literal, a spread, a computed key, or a
15
+ * `scopeFilter` that is not an object literal is reported and the model is left untouched.
16
+ */
17
+ const migrateModelSettings = (opts) => {
18
+ const { typescript, fileName, source } = opts;
19
+ const sourceFile = typescript.createSourceFile(fileName, source, typescript.ScriptTarget.Latest, true);
20
+ const edits = [];
21
+ const reports = [];
22
+ let rewritten = 0;
23
+ const report = (node, reason) => {
24
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
25
+ reports.push({ line: line + 1, column: character + 1, reason });
26
+ };
27
+ const nameOf = (property) => {
28
+ if (!typescript.isPropertyAssignment(property) &&
29
+ !typescript.isShorthandPropertyAssignment(property)) {
30
+ return undefined;
31
+ }
32
+ const { name } = property;
33
+ if (typescript.isIdentifier(name) || typescript.isStringLiteral(name)) {
34
+ return name.text;
35
+ }
36
+ return undefined;
37
+ };
38
+ const text = (node) => source.slice(node.getStart(sourceFile), node.end);
39
+ /**
40
+ * The leading trivia of `first` (its own comments and indentation) followed by the comments that
41
+ * were above the properties being merged into it, so no comment is dropped.
42
+ */
43
+ const composeLeading = (first, merged) => {
44
+ const trivia = source.slice(first.getFullStart(), first.getStart(sourceFile));
45
+ const indent = /[ \t]*$/.exec(trivia)?.[0] ?? '';
46
+ const extra = merged
47
+ .flatMap((node) => typescript.getLeadingCommentRanges(source, node.getFullStart()) ?? [])
48
+ .map((range) => `${source.slice(range.pos, range.end)}\n${indent}`)
49
+ .join('');
50
+ return trivia + extra;
51
+ };
52
+ /**
53
+ * Removes a property with the comma after it; the last property has none, so the comma before it
54
+ * goes instead, leaving no dangling `, }`.
55
+ */
56
+ const removal = (node) => {
57
+ const after = /^\s*,/.exec(source.slice(node.end));
58
+ if (after) {
59
+ return { start: node.getFullStart(), end: node.end + after[0].length, text: '' };
60
+ }
61
+ const before = /,\s*$/.exec(source.slice(0, node.getFullStart()));
62
+ const start = before ? node.getFullStart() - before[0].length : node.getFullStart();
63
+ return { start, end: node.end, text: '' };
64
+ };
65
+ /** Appends members to an object literal: after its last member, or inside empty braces. */
66
+ const append = (object, members) => {
67
+ const last = object.properties[object.properties.length - 1];
68
+ if (last) {
69
+ return { start: last.end, end: last.end, text: `, ${members.join(', ')}` };
70
+ }
71
+ const at = object.getStart(sourceFile) + 1;
72
+ return { start: at, end: at, text: ` ${members.join(', ')} ` };
73
+ };
74
+ const migrateSettings = (settings) => {
75
+ const properties = [...settings.properties];
76
+ const old = new Map();
77
+ let existingQuery;
78
+ for (const property of properties) {
79
+ if (typescript.isSpreadAssignment(property)) {
80
+ // A spread can carry old keys we cannot see.
81
+ report(property, 'settings contains a spread, so its keys are unknown; left untouched');
82
+ return;
83
+ }
84
+ if (typescript.isMethodDeclaration(property)) {
85
+ continue;
86
+ }
87
+ const name = nameOf(property);
88
+ if (name === undefined) {
89
+ report(property, 'settings contains a computed key; left untouched');
90
+ return;
91
+ }
92
+ if (OLD_KEYS.has(name)) {
93
+ if (!typescript.isPropertyAssignment(property)) {
94
+ report(property, `settings.${name} is a shorthand property; left untouched`);
95
+ return;
96
+ }
97
+ old.set(name, property);
98
+ }
99
+ if (name === 'query' && typescript.isPropertyAssignment(property)) {
100
+ existingQuery = property;
101
+ }
102
+ }
103
+ if (old.size === 0) {
104
+ return;
105
+ }
106
+ const queryOld = [...old.keys()].filter((key) => key in QUERY_KEYS);
107
+ const localEdits = [];
108
+ // ---- scopeFilter -> access (rename the key, rewrite writeGuard / sharedRows inside)
109
+ const scopeFilter = old.get('scopeFilter');
110
+ if (scopeFilter) {
111
+ if (!typescript.isObjectLiteralExpression(scopeFilter.initializer)) {
112
+ report(scopeFilter, 'settings.scopeFilter is not an object literal; left untouched');
113
+ return;
114
+ }
115
+ const inner = scopeFilter.initializer;
116
+ const guard = inner.properties.find((property) => nameOf(property) === 'writeGuard' && typescript.isPropertyAssignment(property));
117
+ const shared = inner.properties.find((property) => nameOf(property) === 'sharedRows' && typescript.isPropertyAssignment(property));
118
+ const hasSpread = inner.properties.some((property) => typescript.isSpreadAssignment(property));
119
+ if (hasSpread) {
120
+ report(scopeFilter, 'settings.scopeFilter contains a spread; left untouched');
121
+ return;
122
+ }
123
+ if (inner.properties.some((property) => nameOf(property) === 'write')) {
124
+ report(scopeFilter, 'settings.scopeFilter already has a write key; left untouched');
125
+ return;
126
+ }
127
+ localEdits.push({
128
+ start: scopeFilter.name.getStart(sourceFile),
129
+ end: scopeFilter.name.end,
130
+ text: 'access',
131
+ });
132
+ if (guard || shared) {
133
+ const members = [
134
+ guard ? `mode: ${text(guard.initializer)}` : undefined,
135
+ shared ? `sharedRows: ${text(shared.initializer)}` : undefined,
136
+ ].filter((member) => member !== undefined);
137
+ const ordered = [guard, shared]
138
+ .filter((property) => property !== undefined)
139
+ .sort((a, b) => a.getStart(sourceFile) - b.getStart(sourceFile));
140
+ const [first, ...merged] = ordered;
141
+ localEdits.push({
142
+ start: first.getFullStart(),
143
+ end: first.end,
144
+ text: `${composeLeading(first, merged)}write: { ${members.join(', ')} }`,
145
+ });
146
+ for (const second of merged) {
147
+ localEdits.push(removal(second));
148
+ }
149
+ }
150
+ }
151
+ // ---- defaultFilter / defaultLimit / maxLimit -> query
152
+ if (queryOld.length > 0) {
153
+ const filter = old.get('defaultFilter');
154
+ const defaultLimit = old.get('defaultLimit');
155
+ const maxLimit = old.get('maxLimit');
156
+ if (existingQuery) {
157
+ if (!typescript.isObjectLiteralExpression(existingQuery.initializer)) {
158
+ report(existingQuery, 'settings.query is not an object literal; left untouched');
159
+ return;
160
+ }
161
+ const queryObject = existingQuery.initializer;
162
+ const queryKeys = new Set(queryObject.properties.map((property) => nameOf(property)));
163
+ const existingLimit = queryObject.properties.find((property) => nameOf(property) === 'limit');
164
+ if (filter && queryKeys.has('filter')) {
165
+ report(filter, 'settings.defaultFilter and settings.query.filter are both set; left untouched');
166
+ return;
167
+ }
168
+ if ((defaultLimit || maxLimit) && existingLimit) {
169
+ if (!typescript.isObjectLiteralExpression(existingLimit.initializer)) {
170
+ report(existingLimit, 'settings.query.limit is not an object literal; left untouched');
171
+ return;
172
+ }
173
+ const limitKeys = new Set(existingLimit.initializer.properties.map((property) => nameOf(property)));
174
+ if ((defaultLimit && limitKeys.has('default')) || (maxLimit && limitKeys.has('max'))) {
175
+ report(existingLimit, 'an old limit key and its new key are both set; left untouched');
176
+ return;
177
+ }
178
+ }
179
+ const additions = [];
180
+ if (filter) {
181
+ additions.push(`filter: ${text(filter.initializer)}`);
182
+ }
183
+ const limitMembers = [
184
+ defaultLimit ? `default: ${text(defaultLimit.initializer)}` : undefined,
185
+ maxLimit ? `max: ${text(maxLimit.initializer)}` : undefined,
186
+ ].filter((member) => member !== undefined);
187
+ if (limitMembers.length > 0 && existingLimit) {
188
+ localEdits.push(append(existingLimit.initializer, limitMembers));
189
+ }
190
+ else if (limitMembers.length > 0) {
191
+ additions.push(`limit: { ${limitMembers.join(', ')} }`);
192
+ }
193
+ if (additions.length > 0) {
194
+ localEdits.push(append(queryObject, additions));
195
+ }
196
+ for (const key of queryOld) {
197
+ const property = old.get(key);
198
+ localEdits.push(removal(property));
199
+ }
200
+ }
201
+ else {
202
+ const members = [];
203
+ if (filter) {
204
+ members.push(`filter: ${text(filter.initializer)}`);
205
+ }
206
+ const limitMembers = [
207
+ defaultLimit ? `default: ${text(defaultLimit.initializer)}` : undefined,
208
+ maxLimit ? `max: ${text(maxLimit.initializer)}` : undefined,
209
+ ].filter((member) => member !== undefined);
210
+ if (limitMembers.length > 0) {
211
+ members.push(`limit: { ${limitMembers.join(', ')} }`);
212
+ }
213
+ const ordered = queryOld
214
+ .map((key) => old.get(key))
215
+ .sort((a, b) => a.getStart(sourceFile) - b.getStart(sourceFile));
216
+ const [first, ...others] = ordered;
217
+ localEdits.push({
218
+ start: first.getFullStart(),
219
+ end: first.end,
220
+ text: `${composeLeading(first, others)}query: { ${members.join(', ')} }`,
221
+ });
222
+ for (const other of others) {
223
+ localEdits.push(removal(other));
224
+ }
225
+ }
226
+ }
227
+ edits.push(...localEdits);
228
+ rewritten += 1;
229
+ };
230
+ /**
231
+ * `skipMigrate: true` becomes `migration: { use: false }`; `skipMigrate: false` is the default and
232
+ * is removed. Anything that is not a boolean literal, or a model that already has `migration`, is
233
+ * reported and left alone.
234
+ */
235
+ const migrateSkipMigrate = (argument) => {
236
+ const property = argument.properties.find((candidate) => nameOf(candidate) === 'skipMigrate');
237
+ if (!property) {
238
+ return;
239
+ }
240
+ if (!typescript.isPropertyAssignment(property)) {
241
+ report(property, 'skipMigrate is a shorthand property; left untouched');
242
+ return;
243
+ }
244
+ if (argument.properties.some((candidate) => nameOf(candidate) === 'migration')) {
245
+ report(property, 'skipMigrate and migration are both set; left untouched');
246
+ return;
247
+ }
248
+ const { initializer } = property;
249
+ if (initializer.kind === typescript.SyntaxKind.TrueKeyword) {
250
+ edits.push({
251
+ start: property.getStart(sourceFile),
252
+ end: property.end,
253
+ text: 'migration: { use: false }',
254
+ });
255
+ }
256
+ else if (initializer.kind === typescript.SyntaxKind.FalseKeyword) {
257
+ edits.push(removal(property));
258
+ }
259
+ else {
260
+ report(property, 'skipMigrate is not a boolean literal; left untouched');
261
+ return;
262
+ }
263
+ rewritten += 1;
264
+ };
265
+ const visit = (node) => {
266
+ if (typescript.isDecorator(node) &&
267
+ typescript.isCallExpression(node.expression) &&
268
+ typescript.isIdentifier(node.expression.expression) &&
269
+ node.expression.expression.text === 'model') {
270
+ const argument = node.expression.arguments[0];
271
+ if (argument && typescript.isObjectLiteralExpression(argument)) {
272
+ const settingsProperty = argument.properties.find((property) => nameOf(property) === 'settings');
273
+ if (settingsProperty) {
274
+ if (typescript.isPropertyAssignment(settingsProperty) &&
275
+ typescript.isObjectLiteralExpression(settingsProperty.initializer)) {
276
+ migrateSettings(settingsProperty.initializer);
277
+ }
278
+ else {
279
+ report(settingsProperty, 'settings is not an object literal (a variable, a call or a shorthand); left untouched');
280
+ }
281
+ }
282
+ migrateSkipMigrate(argument);
283
+ }
284
+ }
285
+ typescript.forEachChild(node, visit);
286
+ };
287
+ visit(sourceFile);
288
+ // Neighbouring removals can touch the same comma: merge those, then apply from the end so
289
+ // earlier offsets stay valid.
290
+ const ascending = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);
291
+ const merged = [];
292
+ for (const edit of ascending) {
293
+ const previous = merged[merged.length - 1];
294
+ if (previous && edit.start < previous.end && previous.text === '' && edit.text === '') {
295
+ previous.end = Math.max(previous.end, edit.end);
296
+ continue;
297
+ }
298
+ merged.push({ ...edit });
299
+ }
300
+ let output = source;
301
+ for (const edit of merged.reverse()) {
302
+ output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);
303
+ }
304
+ return { output, changed: output !== source, rewritten, reports };
305
+ };
306
+ exports.migrateModelSettings = migrateModelSettings;
307
+ //# sourceMappingURL=model-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-settings.js","sourceRoot":"","sources":["../../../src/cli/codemod/model-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import type ts from 'typescript';\n\ntype TTypeScript = typeof ts;\n\n/** One thing the codemod could not decide and left alone. */\nexport interface IModelSettingsReport {\n line: number;\n column: number;\n reason: string;\n}\n\nexport interface IModelSettingsResult {\n /** The source after the migration; equal to the input when nothing changed. */\n output: string;\n changed: boolean;\n /** How many `@model` settings objects were rewritten. */\n rewritten: number;\n reports: IModelSettingsReport[];\n}\n\ninterface IEdit {\n start: number;\n end: number;\n text: string;\n}\n\nconst QUERY_KEYS = { defaultFilter: 'filter', defaultLimit: 'default', maxLimit: 'max' } as const;\nconst OLD_KEYS = new Set<string>([...Object.keys(QUERY_KEYS), 'scopeFilter']);\n\n/**\n * Rewrites `@model({ ... })` from the old keys to the grouped ones. `skipMigrate` becomes\n * `migration: { use: false }`. In the `settings` object literal:\n * `defaultFilter` to `query.filter`, `defaultLimit` and `maxLimit` to `query.limit.default` and\n * `query.limit.max`, `scopeFilter` to `access` (`writeGuard` to `write.mode`, `sharedRows` to\n * `write.sharedRows`).\n *\n * It edits by source range, so comments and formatting outside the rewritten properties stay. It\n * never guesses: a `settings` value that is not an object literal, a spread, a computed key, or a\n * `scopeFilter` that is not an object literal is reported and the model is left untouched.\n */\nexport const migrateModelSettings = (opts: {\n typescript: TTypeScript;\n fileName: string;\n source: string;\n}): IModelSettingsResult => {\n const { typescript, fileName, source } = opts;\n const sourceFile = typescript.createSourceFile(\n fileName,\n source,\n typescript.ScriptTarget.Latest,\n true,\n );\n const edits: IEdit[] = [];\n const reports: IModelSettingsReport[] = [];\n let rewritten = 0;\n\n const report = (node: ts.Node, reason: string) => {\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));\n reports.push({ line: line + 1, column: character + 1, reason });\n };\n\n const nameOf = (property: ts.ObjectLiteralElementLike): string | undefined => {\n if (\n !typescript.isPropertyAssignment(property) &&\n !typescript.isShorthandPropertyAssignment(property)\n ) {\n return undefined;\n }\n\n const { name } = property;\n if (typescript.isIdentifier(name) || typescript.isStringLiteral(name)) {\n return name.text;\n }\n\n return undefined;\n };\n\n const text = (node: ts.Node) => source.slice(node.getStart(sourceFile), node.end);\n\n /**\n * The leading trivia of `first` (its own comments and indentation) followed by the comments that\n * were above the properties being merged into it, so no comment is dropped.\n */\n const composeLeading = (first: ts.Node, merged: ts.Node[]): string => {\n const trivia = source.slice(first.getFullStart(), first.getStart(sourceFile));\n const indent = /[ \\t]*$/.exec(trivia)?.[0] ?? '';\n const extra = merged\n .flatMap((node) => typescript.getLeadingCommentRanges(source, node.getFullStart()) ?? [])\n .map((range) => `${source.slice(range.pos, range.end)}\\n${indent}`)\n .join('');\n\n return trivia + extra;\n };\n\n /**\n * Removes a property with the comma after it; the last property has none, so the comma before it\n * goes instead, leaving no dangling `, }`.\n */\n const removal = (node: ts.Node): IEdit => {\n const after = /^\\s*,/.exec(source.slice(node.end));\n if (after) {\n return { start: node.getFullStart(), end: node.end + after[0].length, text: '' };\n }\n\n const before = /,\\s*$/.exec(source.slice(0, node.getFullStart()));\n const start = before ? node.getFullStart() - before[0].length : node.getFullStart();\n\n return { start, end: node.end, text: '' };\n };\n\n /** Appends members to an object literal: after its last member, or inside empty braces. */\n const append = (object: ts.ObjectLiteralExpression, members: string[]): IEdit => {\n const last = object.properties[object.properties.length - 1];\n if (last) {\n return { start: last.end, end: last.end, text: `, ${members.join(', ')}` };\n }\n\n const at = object.getStart(sourceFile) + 1;\n return { start: at, end: at, text: ` ${members.join(', ')} ` };\n };\n\n const migrateSettings = (settings: ts.ObjectLiteralExpression) => {\n const properties = [...settings.properties];\n const old = new Map<string, ts.PropertyAssignment>();\n let existingQuery: ts.PropertyAssignment | undefined;\n\n for (const property of properties) {\n if (typescript.isSpreadAssignment(property)) {\n // A spread can carry old keys we cannot see.\n report(property, 'settings contains a spread, so its keys are unknown; left untouched');\n return;\n }\n\n if (typescript.isMethodDeclaration(property)) {\n continue;\n }\n\n const name = nameOf(property);\n if (name === undefined) {\n report(property, 'settings contains a computed key; left untouched');\n return;\n }\n\n if (OLD_KEYS.has(name)) {\n if (!typescript.isPropertyAssignment(property)) {\n report(property, `settings.${name} is a shorthand property; left untouched`);\n return;\n }\n old.set(name, property);\n }\n\n if (name === 'query' && typescript.isPropertyAssignment(property)) {\n existingQuery = property;\n }\n }\n\n if (old.size === 0) {\n return;\n }\n\n const queryOld = [...old.keys()].filter((key) => key in QUERY_KEYS);\n const localEdits: IEdit[] = [];\n\n // ---- scopeFilter -> access (rename the key, rewrite writeGuard / sharedRows inside)\n const scopeFilter = old.get('scopeFilter');\n if (scopeFilter) {\n if (!typescript.isObjectLiteralExpression(scopeFilter.initializer)) {\n report(scopeFilter, 'settings.scopeFilter is not an object literal; left untouched');\n return;\n }\n\n const inner = scopeFilter.initializer;\n const guard = inner.properties.find(\n (property) =>\n nameOf(property) === 'writeGuard' && typescript.isPropertyAssignment(property),\n ) as ts.PropertyAssignment | undefined;\n const shared = inner.properties.find(\n (property) =>\n nameOf(property) === 'sharedRows' && typescript.isPropertyAssignment(property),\n ) as ts.PropertyAssignment | undefined;\n const hasSpread = inner.properties.some((property) =>\n typescript.isSpreadAssignment(property),\n );\n\n if (hasSpread) {\n report(scopeFilter, 'settings.scopeFilter contains a spread; left untouched');\n return;\n }\n\n if (inner.properties.some((property) => nameOf(property) === 'write')) {\n report(scopeFilter, 'settings.scopeFilter already has a write key; left untouched');\n return;\n }\n\n localEdits.push({\n start: scopeFilter.name.getStart(sourceFile),\n end: scopeFilter.name.end,\n text: 'access',\n });\n\n if (guard || shared) {\n const members = [\n guard ? `mode: ${text(guard.initializer)}` : undefined,\n shared ? `sharedRows: ${text(shared.initializer)}` : undefined,\n ].filter((member): member is string => member !== undefined);\n const ordered = [guard, shared]\n .filter((property): property is ts.PropertyAssignment => property !== undefined)\n .sort((a, b) => a.getStart(sourceFile) - b.getStart(sourceFile));\n const [first, ...merged] = ordered;\n\n localEdits.push({\n start: first.getFullStart(),\n end: first.end,\n text: `${composeLeading(first, merged)}write: { ${members.join(', ')} }`,\n });\n\n for (const second of merged) {\n localEdits.push(removal(second));\n }\n }\n }\n\n // ---- defaultFilter / defaultLimit / maxLimit -> query\n if (queryOld.length > 0) {\n const filter = old.get('defaultFilter');\n const defaultLimit = old.get('defaultLimit');\n const maxLimit = old.get('maxLimit');\n\n if (existingQuery) {\n if (!typescript.isObjectLiteralExpression(existingQuery.initializer)) {\n report(existingQuery, 'settings.query is not an object literal; left untouched');\n return;\n }\n\n const queryObject = existingQuery.initializer;\n const queryKeys = new Set(queryObject.properties.map((property) => nameOf(property)));\n const existingLimit = queryObject.properties.find(\n (property) => nameOf(property) === 'limit',\n ) as ts.PropertyAssignment | undefined;\n\n if (filter && queryKeys.has('filter')) {\n report(\n filter,\n 'settings.defaultFilter and settings.query.filter are both set; left untouched',\n );\n return;\n }\n\n if ((defaultLimit || maxLimit) && existingLimit) {\n if (!typescript.isObjectLiteralExpression(existingLimit.initializer)) {\n report(existingLimit, 'settings.query.limit is not an object literal; left untouched');\n return;\n }\n\n const limitKeys = new Set(\n existingLimit.initializer.properties.map((property) => nameOf(property)),\n );\n if ((defaultLimit && limitKeys.has('default')) || (maxLimit && limitKeys.has('max'))) {\n report(existingLimit, 'an old limit key and its new key are both set; left untouched');\n return;\n }\n }\n\n const additions: string[] = [];\n if (filter) {\n additions.push(`filter: ${text(filter.initializer)}`);\n }\n\n const limitMembers = [\n defaultLimit ? `default: ${text(defaultLimit.initializer)}` : undefined,\n maxLimit ? `max: ${text(maxLimit.initializer)}` : undefined,\n ].filter((member): member is string => member !== undefined);\n\n if (limitMembers.length > 0 && existingLimit) {\n localEdits.push(\n append(existingLimit.initializer as ts.ObjectLiteralExpression, limitMembers),\n );\n } else if (limitMembers.length > 0) {\n additions.push(`limit: { ${limitMembers.join(', ')} }`);\n }\n\n if (additions.length > 0) {\n localEdits.push(append(queryObject, additions));\n }\n\n for (const key of queryOld) {\n const property = old.get(key) as ts.PropertyAssignment;\n localEdits.push(removal(property));\n }\n } else {\n const members: string[] = [];\n if (filter) {\n members.push(`filter: ${text(filter.initializer)}`);\n }\n\n const limitMembers = [\n defaultLimit ? `default: ${text(defaultLimit.initializer)}` : undefined,\n maxLimit ? `max: ${text(maxLimit.initializer)}` : undefined,\n ].filter((member): member is string => member !== undefined);\n if (limitMembers.length > 0) {\n members.push(`limit: { ${limitMembers.join(', ')} }`);\n }\n\n const ordered = queryOld\n .map((key) => old.get(key) as ts.PropertyAssignment)\n .sort((a, b) => a.getStart(sourceFile) - b.getStart(sourceFile));\n const [first, ...others] = ordered;\n\n localEdits.push({\n start: first.getFullStart(),\n end: first.end,\n text: `${composeLeading(first, others)}query: { ${members.join(', ')} }`,\n });\n\n for (const other of others) {\n localEdits.push(removal(other));\n }\n }\n }\n\n edits.push(...localEdits);\n rewritten += 1;\n };\n\n /**\n * `skipMigrate: true` becomes `migration: { use: false }`; `skipMigrate: false` is the default and\n * is removed. Anything that is not a boolean literal, or a model that already has `migration`, is\n * reported and left alone.\n */\n const migrateSkipMigrate = (argument: ts.ObjectLiteralExpression) => {\n const property = argument.properties.find((candidate) => nameOf(candidate) === 'skipMigrate');\n if (!property) {\n return;\n }\n\n if (!typescript.isPropertyAssignment(property)) {\n report(property, 'skipMigrate is a shorthand property; left untouched');\n return;\n }\n\n if (argument.properties.some((candidate) => nameOf(candidate) === 'migration')) {\n report(property, 'skipMigrate and migration are both set; left untouched');\n return;\n }\n\n const { initializer } = property;\n if (initializer.kind === typescript.SyntaxKind.TrueKeyword) {\n edits.push({\n start: property.getStart(sourceFile),\n end: property.end,\n text: 'migration: { use: false }',\n });\n } else if (initializer.kind === typescript.SyntaxKind.FalseKeyword) {\n edits.push(removal(property));\n } else {\n report(property, 'skipMigrate is not a boolean literal; left untouched');\n return;\n }\n\n rewritten += 1;\n };\n\n const visit = (node: ts.Node) => {\n if (\n typescript.isDecorator(node) &&\n typescript.isCallExpression(node.expression) &&\n typescript.isIdentifier(node.expression.expression) &&\n node.expression.expression.text === 'model'\n ) {\n const argument = node.expression.arguments[0];\n\n if (argument && typescript.isObjectLiteralExpression(argument)) {\n const settingsProperty = argument.properties.find(\n (property) => nameOf(property) === 'settings',\n );\n\n if (settingsProperty) {\n if (\n typescript.isPropertyAssignment(settingsProperty) &&\n typescript.isObjectLiteralExpression(settingsProperty.initializer)\n ) {\n migrateSettings(settingsProperty.initializer);\n } else {\n report(\n settingsProperty,\n 'settings is not an object literal (a variable, a call or a shorthand); left untouched',\n );\n }\n }\n\n migrateSkipMigrate(argument);\n }\n }\n\n typescript.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n\n // Neighbouring removals can touch the same comma: merge those, then apply from the end so\n // earlier offsets stay valid.\n const ascending = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);\n const merged: IEdit[] = [];\n for (const edit of ascending) {\n const previous = merged[merged.length - 1];\n if (previous && edit.start < previous.end && previous.text === '' && edit.text === '') {\n previous.end = Math.max(previous.end, edit.end);\n continue;\n }\n\n merged.push({ ...edit });\n }\n\n let output = source;\n for (const edit of merged.reverse()) {\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n }\n\n return { output, changed: output !== source, rewritten, reports };\n};\n"]}
package/dist/cli/index.js CHANGED
@@ -2,15 +2,30 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const clean_1 = require("./clean");
5
+ const codemod_1 = require("./codemod");
5
6
  const lint_1 = require("./lint");
6
- const USAGE = 'Usage: devz lint [--fix] [files] | devz clean';
7
+ const USAGE = `Usage: devz <command> [options]
8
+
9
+ Commands:
10
+ lint [--fix] [files] oxlint, ESLint and the formatter; --fix writes
11
+ clean remove dist, node_modules/.cache and *.tsbuildinfo
12
+ codemod model-settings [paths...] [--write] move @model settings to the grouped shape (dry run unless --write)
13
+
14
+ Run \`devz clean --help\` or \`devz codemod model-settings --help\` for a command's options.`;
7
15
  const main = async (opts) => {
8
16
  const [command, ...args] = opts.argv;
17
+ if (command === undefined || command === '--help' || command === '-h') {
18
+ console.log(USAGE);
19
+ return 0;
20
+ }
9
21
  if (command === 'lint') {
10
22
  return lint_1.LintCommand.run({ root: process.cwd(), args });
11
23
  }
12
24
  if (command === 'clean') {
13
- return clean_1.CleanCommand.run({ root: process.cwd() });
25
+ return clean_1.CleanCommand.run({ root: process.cwd(), args });
26
+ }
27
+ if (command === 'codemod') {
28
+ return codemod_1.CodemodCommand.run({ root: process.cwd(), args });
14
29
  }
15
30
  console.error(`devz: unknown command "${command ?? ''}"\n${USAGE}`);
16
31
  return 1;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,mCAAuC;AACvC,iCAAqC;AAErC,MAAM,KAAK,GAAG,+CAA+C,CAAC;AAE9D,MAAM,IAAI,GAAG,KAAK,EAAE,IAAwB,EAAmB,EAAE;IAC/D,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;IAErC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,kBAAW,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,oBAAY,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,IAAI,EAAE,MAAM,KAAK,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CACxC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EACpC,CAAC,KAAc,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CACF,CAAC","sourcesContent":["#!/usr/bin/env bun\nimport { CleanCommand } from './clean';\nimport { LintCommand } from './lint';\n\nconst USAGE = 'Usage: devz lint [--fix] [files] | devz clean';\n\nconst main = async (opts: { argv: string[] }): Promise<number> => {\n const [command, ...args] = opts.argv;\n\n if (command === 'lint') {\n return LintCommand.run({ root: process.cwd(), args });\n }\n\n if (command === 'clean') {\n return CleanCommand.run({ root: process.cwd() });\n }\n\n console.error(`devz: unknown command \"${command ?? ''}\"\\n${USAGE}`);\n return 1;\n};\n\nmain({ argv: process.argv.slice(2) }).then(\n (exitCode) => process.exit(exitCode),\n (error: unknown) => {\n console.error(error);\n process.exit(1);\n },\n);\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,mCAAuC;AACvC,uCAA2C;AAC3C,iCAAqC;AAErC,MAAM,KAAK,GAAG;;;;;;;6FAO+E,CAAC;AAE9F,MAAM,IAAI,GAAG,KAAK,EAAE,IAAwB,EAAmB,EAAE;IAC/D,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;IAErC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,kBAAW,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,oBAAY,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,wBAAc,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,IAAI,EAAE,MAAM,KAAK,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CACxC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EACpC,CAAC,KAAc,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CACF,CAAC","sourcesContent":["#!/usr/bin/env bun\nimport { CleanCommand } from './clean';\nimport { CodemodCommand } from './codemod';\nimport { LintCommand } from './lint';\n\nconst USAGE = `Usage: devz <command> [options]\n\nCommands:\n lint [--fix] [files] oxlint, ESLint and the formatter; --fix writes\n clean remove dist, node_modules/.cache and *.tsbuildinfo\n codemod model-settings [paths...] [--write] move @model settings to the grouped shape (dry run unless --write)\n\nRun \\`devz clean --help\\` or \\`devz codemod model-settings --help\\` for a command's options.`;\n\nconst main = async (opts: { argv: string[] }): Promise<number> => {\n const [command, ...args] = opts.argv;\n\n if (command === undefined || command === '--help' || command === '-h') {\n console.log(USAGE);\n return 0;\n }\n\n if (command === 'lint') {\n return LintCommand.run({ root: process.cwd(), args });\n }\n\n if (command === 'clean') {\n return CleanCommand.run({ root: process.cwd(), args });\n }\n\n if (command === 'codemod') {\n return CodemodCommand.run({ root: process.cwd(), args });\n }\n\n console.error(`devz: unknown command \"${command ?? ''}\"\\n${USAGE}`);\n return 1;\n};\n\nmain({ argv: process.argv.slice(2) }).then(\n (exitCode) => process.exit(exitCode),\n (error: unknown) => {\n console.error(error);\n process.exit(1);\n },\n);\n"]}
@@ -6,6 +6,7 @@ export declare class AstNodeTypes {
6
6
  static readonly FUNCTION_EXPRESSION = "FunctionExpression";
7
7
  static readonly ARROW_FUNCTION_EXPRESSION = "ArrowFunctionExpression";
8
8
  static readonly EXPORT_NAMED_DECLARATION = "ExportNamedDeclaration";
9
+ static readonly UNION_TYPE = "TSUnionType";
9
10
  }
10
11
  /** The ESLint namespace the house rules live under: `venizia/<rule>`. */
11
12
  export declare const HOUSE_PLUGIN_NAMESPACE = "venizia";
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":"AAAA,8HAA8H;AAC9H,qBAAa,YAAY;IACvB,MAAM,CAAC,QAAQ,CAAC,cAAc,mBAAmB;IACjD,MAAM,CAAC,QAAQ,CAAC,eAAe,oBAAoB;IACnD,MAAM,CAAC,QAAQ,CAAC,oBAAoB,yBAAyB;IAC7D,MAAM,CAAC,QAAQ,CAAC,mBAAmB,wBAAwB;IAC3D,MAAM,CAAC,QAAQ,CAAC,yBAAyB,6BAA6B;IACtE,MAAM,CAAC,QAAQ,CAAC,wBAAwB,4BAA4B;CACrE;AAED,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,qHAAqH;AACrH,eAAO,MAAM,SAAS,GAAI,MAAM;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,OAKhE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,QAAQ,GAAI,MAAM;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,KAAG,MAAM,GAAG,SAG3D,CAAC"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":"AAAA,8HAA8H;AAC9H,qBAAa,YAAY;IACvB,MAAM,CAAC,QAAQ,CAAC,cAAc,mBAAmB;IACjD,MAAM,CAAC,QAAQ,CAAC,eAAe,oBAAoB;IACnD,MAAM,CAAC,QAAQ,CAAC,oBAAoB,yBAAyB;IAC7D,MAAM,CAAC,QAAQ,CAAC,mBAAmB,wBAAwB;IAC3D,MAAM,CAAC,QAAQ,CAAC,yBAAyB,6BAA6B;IACtE,MAAM,CAAC,QAAQ,CAAC,wBAAwB,4BAA4B;IACpE,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAiB;CAC5C;AAED,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,qHAAqH;AACrH,eAAO,MAAM,SAAS,GAAI,MAAM;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,OAKhE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,QAAQ,GAAI,MAAM;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,KAAG,MAAM,GAAG,SAG3D,CAAC"}
@@ -9,6 +9,7 @@ class AstNodeTypes {
9
9
  static { this.FUNCTION_EXPRESSION = 'FunctionExpression'; }
10
10
  static { this.ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression'; }
11
11
  static { this.EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration'; }
12
+ static { this.UNION_TYPE = 'TSUnionType'; }
12
13
  }
13
14
  exports.AstNodeTypes = AstNodeTypes;
14
15
  /** The ESLint namespace the house rules live under: `venizia/<rule>`. */
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;;AANtE,oCAOC;AAED,yEAAyE;AAC5D,QAAA,sBAAsB,GAAG,SAAS,CAAC;AAEhD,qHAAqH;AAC9G,MAAM,SAAS,GAAG,CAAC,IAAoC,EAAW,EAAE;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3B,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI;QAC7D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;QACxB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC;AALW,QAAA,SAAS,aAKpB;AAEF,8EAA8E;AACvE,MAAM,QAAQ,GAAG,CAAC,IAAuB,EAAsB,EAAE;IACtE,MAAM,IAAI,GAAG,IAAA,iBAAS,EAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC,CAAC;AAHW,QAAA,QAAQ,YAGnB","sourcesContent":["/** The estree node types the house rules visit - computed visitor keys, so the names stay PascalCase as ESLint needs them. */\nexport class AstNodeTypes {\n static readonly NEW_EXPRESSION = 'NewExpression';\n static readonly CALL_EXPRESSION = 'CallExpression';\n static readonly FUNCTION_DECLARATION = 'FunctionDeclaration';\n static readonly FUNCTION_EXPRESSION = 'FunctionExpression';\n static readonly ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression';\n static readonly EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';\n}\n\n/** The ESLint namespace the house rules live under: `venizia/<rule>`. */\nexport const HOUSE_PLUGIN_NAMESPACE = 'venizia';\n\n/** A field of an AST node, read without trusting its type: TypeScript nodes carry fields estree does not declare. */\nexport const readField = (opts: { node: unknown; key: string }): unknown => {\n const { node, key } = opts;\n return typeof node === 'object' && node !== null && key in node\n ? Reflect.get(node, key)\n : undefined;\n};\n\n/** The node's `type`, or `undefined` for anything that is not an AST node. */\nexport const nodeType = (opts: { node: unknown }): string | undefined => {\n const type = readField({ node: opts.node, key: 'type' });\n return typeof type === 'string' ? type : undefined;\n};\n"]}
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;aACpD,eAAU,GAAG,aAAa,CAAC;;AAP7C,oCAQC;AAED,yEAAyE;AAC5D,QAAA,sBAAsB,GAAG,SAAS,CAAC;AAEhD,qHAAqH;AAC9G,MAAM,SAAS,GAAG,CAAC,IAAoC,EAAW,EAAE;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3B,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI;QAC7D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;QACxB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC;AALW,QAAA,SAAS,aAKpB;AAEF,8EAA8E;AACvE,MAAM,QAAQ,GAAG,CAAC,IAAuB,EAAsB,EAAE;IACtE,MAAM,IAAI,GAAG,IAAA,iBAAS,EAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC,CAAC;AAHW,QAAA,QAAQ,YAGnB","sourcesContent":["/** The estree node types the house rules visit - computed visitor keys, so the names stay PascalCase as ESLint needs them. */\nexport class AstNodeTypes {\n static readonly NEW_EXPRESSION = 'NewExpression';\n static readonly CALL_EXPRESSION = 'CallExpression';\n static readonly FUNCTION_DECLARATION = 'FunctionDeclaration';\n static readonly FUNCTION_EXPRESSION = 'FunctionExpression';\n static readonly ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression';\n static readonly EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';\n static readonly UNION_TYPE = 'TSUnionType';\n}\n\n/** The ESLint namespace the house rules live under: `venizia/<rule>`. */\nexport const HOUSE_PLUGIN_NAMESPACE = 'venizia';\n\n/** A field of an AST node, read without trusting its type: TypeScript nodes carry fields estree does not declare. */\nexport const readField = (opts: { node: unknown; key: string }): unknown => {\n const { node, key } = opts;\n return typeof node === 'object' && node !== null && key in node\n ? Reflect.get(node, key)\n : undefined;\n};\n\n/** The node's `type`, or `undefined` for anything that is not an AST node. */\nexport const nodeType = (opts: { node: unknown }): string | undefined => {\n const type = readField({ node: opts.node, key: 'type' });\n return typeof type === 'string' ? type : undefined;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AA8BrC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAsD,CAAC;AAc/F,kHAAkH;AAClH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAI5C,CAAC"}
1
+ {"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAkDrC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAsD,CAAC;AAc/F,kHAAkH;AAClH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAI5C,CAAC"}
@@ -5,16 +5,26 @@ const eslint_1 = require("../eslint");
5
5
  const jsx_files_1 = require("../jsx-files");
6
6
  const react_eslint_1 = require("../react-eslint");
7
7
  const common_1 = require("./common");
8
+ const const_class_values_rule_1 = require("./const-class-values.rule");
8
9
  const max_params_own_rule_1 = require("./max-params-own.rule");
9
10
  const no_leaked_render_rule_1 = require("./no-leaked-render.rule");
10
11
  const no_new_error_rule_1 = require("./no-new-error.rule");
11
12
  const plugin_1 = require("./plugin");
12
13
  const SOURCE_FILES = ['**/*.{ts,tsx,mts,cts}'];
13
14
  const TEST_FILES = ['**/__tests__/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'];
15
+ /**
16
+ * V-C-10: no explicit cast. `as const` is always allowed; `satisfies`, a generic or a narrower type
17
+ * replaces the rest.
18
+ */
19
+ const NO_CAST_RULE = '@typescript-eslint/consistent-type-assertions';
14
20
  /**
15
21
  * The house rules: at most 5 positional parameters on a function we write, and errors thrown through
16
22
  * `getError` only. Tests are exempt from `no-new-error`: a test throws a plain `Error` on purpose, to
17
23
  * stand in for what a driver or a third-party library throws.
24
+ *
25
+ * Two rules only warn, so a project adopts them without failing its lint: `const-class-values` (V-C-08, a
26
+ * string-literal union in an exported declaration) and `consistent-type-assertions` (V-C-10, an `as X`
27
+ * cast). Tests are exempt from both: a test stubs what it does not build.
18
28
  */
19
29
  const houseRuleConfigs = [
20
30
  {
@@ -23,9 +33,18 @@ const houseRuleConfigs = [
23
33
  rules: {
24
34
  [max_params_own_rule_1.MaxParamsOwnRule.NAME]: max_params_own_rule_1.MaxParamsOwnRule.build(),
25
35
  [no_new_error_rule_1.NoNewErrorRule.NAME]: no_new_error_rule_1.NoNewErrorRule.build(),
36
+ [const_class_values_rule_1.ConstClassValuesRule.NAME]: const_class_values_rule_1.ConstClassValuesRule.build({ severity: 'warn' }),
37
+ [NO_CAST_RULE]: ['warn', { assertionStyle: 'never' }],
38
+ },
39
+ },
40
+ {
41
+ files: TEST_FILES,
42
+ rules: {
43
+ [no_new_error_rule_1.NoNewErrorRule.NAME]: 'off',
44
+ [const_class_values_rule_1.ConstClassValuesRule.NAME]: 'off',
45
+ [NO_CAST_RULE]: 'off',
26
46
  },
27
47
  },
28
- { files: TEST_FILES, rules: { [no_new_error_rule_1.NoNewErrorRule.NAME]: 'off' } },
29
48
  ];
30
49
  /**
31
50
  * The ESLint side of a project that lints with oxlint: the naming convention plus the house rules -
@@ -1 +1 @@
1
- {"version":3,"file":"configs.js","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":";;;AACA,sCAAoD;AACpD,4CAAyC;AACzC,kDAA+D;AAC/D,qCAAkD;AAClD,+DAAyD;AACzD,mEAA6D;AAC7D,2DAAqD;AACrD,qCAA6C;AAE7C,MAAM,YAAY,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,gBAAgB,GAAoB;IACxC;QACE,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,EAAE,CAAC,+BAAsB,CAAC,EAAE,0BAAiB,EAAE;QACxD,KAAK,EAAE;YACL,CAAC,sCAAgB,CAAC,IAAI,CAAC,EAAE,sCAAgB,CAAC,KAAK,EAAE;YACjD,CAAC,kCAAc,CAAC,IAAI,CAAC,EAAE,kCAAc,CAAC,KAAK,EAAE;SAC9C;KACF;IACD,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC,kCAAc,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;CAC/D,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAoB,CAAC,GAAG,gCAAuB,EAAE,GAAG,gBAAgB,CAAC,CAAC;AAE/F;;;GAGG;AACH,MAAM,gBAAgB,GAAoB;IACxC;QACE,KAAK,EAAE,qBAAS;QAChB,OAAO,EAAE,EAAE,CAAC,+BAAsB,CAAC,EAAE,0BAAiB,EAAE;QACxD,KAAK,EAAE,EAAE,CAAC,0CAAkB,CAAC,IAAI,CAAC,EAAE,0CAAkB,CAAC,KAAK,EAAE,EAAE;KACjE;CACF,CAAC;AAEF,kHAAkH;AACrG,QAAA,iBAAiB,GAAoB;IAChD,GAAG,2CAA4B;IAC/B,GAAG,gBAAgB;IACnB,GAAG,gBAAgB;CACpB,CAAC","sourcesContent":["import type { Linter } from 'eslint';\nimport { namingConventionConfigs } from '../eslint';\nimport { JSX_FILES } from '../jsx-files';\nimport { reactNamingConventionConfigs } from '../react-eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { houseEslintPlugin } from './plugin';\n\nconst SOURCE_FILES = ['**/*.{ts,tsx,mts,cts}'];\nconst TEST_FILES = ['**/__tests__/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'];\n\n/**\n * The house rules: at most 5 positional parameters on a function we write, and errors thrown through\n * `getError` only. Tests are exempt from `no-new-error`: a test throws a plain `Error` on purpose, to\n * stand in for what a driver or a third-party library throws.\n */\nconst houseRuleConfigs: Linter.Config[] = [\n {\n files: SOURCE_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: {\n [MaxParamsOwnRule.NAME]: MaxParamsOwnRule.build(),\n [NoNewErrorRule.NAME]: NoNewErrorRule.build(),\n },\n },\n { files: TEST_FILES, rules: { [NoNewErrorRule.NAME]: 'off' } },\n];\n\n/**\n * The ESLint side of a project that lints with oxlint: the naming convention plus the house rules -\n * everything oxlint cannot express. Run it next to `oxlintConfigs`.\n *\n * ```js\n * // .configs/lints/eslint.config.mjs\n * import { houseConfigs } from '@venizia/dev-configs/linters';\n *\n * export default houseConfigs;\n * ```\n */\nexport const houseConfigs: Linter.Config[] = [...namingConventionConfigs, ...houseRuleConfigs];\n\n/**\n * The React house rule: a JSX child is drawn with `cond ? <X /> : null`, never `cond && <X />`, which\n * draws `0` when `cond` is `0`.\n */\nconst reactRuleConfigs: Linter.Config[] = [\n {\n files: JSX_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: { [NoLeakedRenderRule.NAME]: NoLeakedRenderRule.build() },\n },\n];\n\n/** `houseConfigs` for a React project: `reactNamingConventionConfigs`, the house rules and `no-leaked-render`. */\nexport const reactHouseConfigs: Linter.Config[] = [\n ...reactNamingConventionConfigs,\n ...houseRuleConfigs,\n ...reactRuleConfigs,\n];\n"]}
1
+ {"version":3,"file":"configs.js","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":";;;AACA,sCAAoD;AACpD,4CAAyC;AACzC,kDAA+D;AAC/D,qCAAkD;AAClD,uEAAiE;AACjE,+DAAyD;AACzD,mEAA6D;AAC7D,2DAAqD;AACrD,qCAA6C;AAE7C,MAAM,YAAY,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;AAEnF;;;GAGG;AACH,MAAM,YAAY,GAAG,+CAA+C,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAoB;IACxC;QACE,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,EAAE,CAAC,+BAAsB,CAAC,EAAE,0BAAiB,EAAE;QACxD,KAAK,EAAE;YACL,CAAC,sCAAgB,CAAC,IAAI,CAAC,EAAE,sCAAgB,CAAC,KAAK,EAAE;YACjD,CAAC,kCAAc,CAAC,IAAI,CAAC,EAAE,kCAAc,CAAC,KAAK,EAAE;YAC7C,CAAC,8CAAoB,CAAC,IAAI,CAAC,EAAE,8CAAoB,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC7E,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;SACtD;KACF;IACD;QACE,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE;YACL,CAAC,kCAAc,CAAC,IAAI,CAAC,EAAE,KAAK;YAC5B,CAAC,8CAAoB,CAAC,IAAI,CAAC,EAAE,KAAK;YAClC,CAAC,YAAY,CAAC,EAAE,KAAK;SACtB;KACF;CACF,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAoB,CAAC,GAAG,gCAAuB,EAAE,GAAG,gBAAgB,CAAC,CAAC;AAE/F;;;GAGG;AACH,MAAM,gBAAgB,GAAoB;IACxC;QACE,KAAK,EAAE,qBAAS;QAChB,OAAO,EAAE,EAAE,CAAC,+BAAsB,CAAC,EAAE,0BAAiB,EAAE;QACxD,KAAK,EAAE,EAAE,CAAC,0CAAkB,CAAC,IAAI,CAAC,EAAE,0CAAkB,CAAC,KAAK,EAAE,EAAE;KACjE;CACF,CAAC;AAEF,kHAAkH;AACrG,QAAA,iBAAiB,GAAoB;IAChD,GAAG,2CAA4B;IAC/B,GAAG,gBAAgB;IACnB,GAAG,gBAAgB;CACpB,CAAC","sourcesContent":["import type { Linter } from 'eslint';\nimport { namingConventionConfigs } from '../eslint';\nimport { JSX_FILES } from '../jsx-files';\nimport { reactNamingConventionConfigs } from '../react-eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { ConstClassValuesRule } from './const-class-values.rule';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { houseEslintPlugin } from './plugin';\n\nconst SOURCE_FILES = ['**/*.{ts,tsx,mts,cts}'];\nconst TEST_FILES = ['**/__tests__/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'];\n\n/**\n * V-C-10: no explicit cast. `as const` is always allowed; `satisfies`, a generic or a narrower type\n * replaces the rest.\n */\nconst NO_CAST_RULE = '@typescript-eslint/consistent-type-assertions';\n\n/**\n * The house rules: at most 5 positional parameters on a function we write, and errors thrown through\n * `getError` only. Tests are exempt from `no-new-error`: a test throws a plain `Error` on purpose, to\n * stand in for what a driver or a third-party library throws.\n *\n * Two rules only warn, so a project adopts them without failing its lint: `const-class-values` (V-C-08, a\n * string-literal union in an exported declaration) and `consistent-type-assertions` (V-C-10, an `as X`\n * cast). Tests are exempt from both: a test stubs what it does not build.\n */\nconst houseRuleConfigs: Linter.Config[] = [\n {\n files: SOURCE_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: {\n [MaxParamsOwnRule.NAME]: MaxParamsOwnRule.build(),\n [NoNewErrorRule.NAME]: NoNewErrorRule.build(),\n [ConstClassValuesRule.NAME]: ConstClassValuesRule.build({ severity: 'warn' }),\n [NO_CAST_RULE]: ['warn', { assertionStyle: 'never' }],\n },\n },\n {\n files: TEST_FILES,\n rules: {\n [NoNewErrorRule.NAME]: 'off',\n [ConstClassValuesRule.NAME]: 'off',\n [NO_CAST_RULE]: 'off',\n },\n },\n];\n\n/**\n * The ESLint side of a project that lints with oxlint: the naming convention plus the house rules -\n * everything oxlint cannot express. Run it next to `oxlintConfigs`.\n *\n * ```js\n * // .configs/lints/eslint.config.mjs\n * import { houseConfigs } from '@venizia/dev-configs/linters';\n *\n * export default houseConfigs;\n * ```\n */\nexport const houseConfigs: Linter.Config[] = [...namingConventionConfigs, ...houseRuleConfigs];\n\n/**\n * The React house rule: a JSX child is drawn with `cond ? <X /> : null`, never `cond && <X />`, which\n * draws `0` when `cond` is `0`.\n */\nconst reactRuleConfigs: Linter.Config[] = [\n {\n files: JSX_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: { [NoLeakedRenderRule.NAME]: NoLeakedRenderRule.build() },\n },\n];\n\n/** `houseConfigs` for a React project: `reactNamingConventionConfigs`, the house rules and `no-leaked-render`. */\nexport const reactHouseConfigs: Linter.Config[] = [\n ...reactNamingConventionConfigs,\n ...houseRuleConfigs,\n ...reactRuleConfigs,\n];\n"]}
@@ -2,13 +2,16 @@ import type { Linter, Rule } from 'eslint';
2
2
  import type { TRuleSeverity } from '../rules/common';
3
3
  /**
4
4
  * `venizia/const-class-values`. An enumerable string is a const class plus `TConstValue<typeof X>`,
5
- * never an exported union of string literals. Only a type whose name ends like a logic value is
6
- * checked (`State`, `Status`, `Stage`, `Mode`, `Kind`, `Type` by default): any other string union may
7
- * be a plain parameter type.
5
+ * never a union of string literals in an exported declaration: a type alias, an interface member, a
6
+ * generic constraint, a parameter or a return type of an exported function or class.
7
+ *
8
+ * Not counted: a union that is not all string literals (a `null` or `undefined` member is ignored),
9
+ * a key set (`Pick`, `Omit`, `Extract`, `Exclude`, `Record` arguments and mapped-type keys), and a
10
+ * declaration that is not exported. `namePattern` narrows the rule to exported type aliases whose name
11
+ * matches it (`(State|Status)$`), for a project that adopts the rule one name at a time.
8
12
  */
9
13
  export declare class ConstClassValuesRule {
10
14
  static readonly NAME = "venizia/const-class-values";
11
- static readonly DEFAULT_NAME_PATTERN = "(State|Status|Stage|Mode|Kind|Type)$";
12
15
  static readonly RULE: Rule.RuleModule;
13
16
  static build(opts?: {
14
17
  severity?: TRuleSeverity;
@@ -1 +1 @@
1
- {"version":3,"file":"const-class-values.rule.d.ts","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,gCAAkD;IAEtE,MAAM,CAAC,QAAQ,CAAC,oBAAoB,0CAA0C;IAE9E,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CA0CnC;IAEF,MAAM,CAAC,KAAK,CAAC,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,aAAa,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,MAAM,CAAC,SAAS;CAI9F"}
1
+ {"version":3,"file":"const-class-values.rule.d.ts","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAoDrD;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,gCAAkD;IAEtE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAsDnC;IAEF,MAAM,CAAC,KAAK,CAAC,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,aAAa,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,MAAM,CAAC,SAAS;CAI9F"}