@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.
- package/README.md +5 -3
- package/dist/cli/clean.d.ts +2 -1
- package/dist/cli/clean.d.ts.map +1 -1
- package/dist/cli/clean.js +28 -1
- package/dist/cli/clean.js.map +1 -1
- package/dist/cli/codemod/files.d.ts +22 -0
- package/dist/cli/codemod/files.d.ts.map +1 -0
- package/dist/cli/codemod/files.js +68 -0
- package/dist/cli/codemod/files.js.map +1 -0
- package/dist/cli/codemod/index.d.ts +13 -0
- package/dist/cli/codemod/index.d.ts.map +1 -0
- package/dist/cli/codemod/index.js +106 -0
- package/dist/cli/codemod/index.js.map +1 -0
- package/dist/cli/codemod/model-settings.d.ts +34 -0
- package/dist/cli/codemod/model-settings.d.ts.map +1 -0
- package/dist/cli/codemod/model-settings.js +307 -0
- package/dist/cli/codemod/model-settings.js.map +1 -0
- package/dist/cli/index.js +17 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/linters/house/common.d.ts +1 -0
- package/dist/linters/house/common.d.ts.map +1 -1
- package/dist/linters/house/common.js +1 -0
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/configs.d.ts.map +1 -1
- package/dist/linters/house/configs.js +20 -1
- package/dist/linters/house/configs.js.map +1 -1
- package/dist/linters/house/const-class-values.rule.d.ts +7 -4
- package/dist/linters/house/const-class-values.rule.d.ts.map +1 -1
- package/dist/linters/house/const-class-values.rule.js +73 -21
- package/dist/linters/house/const-class-values.rule.js.map +1 -1
- package/dist/linters/rules/common.d.ts +48 -1
- package/dist/linters/rules/common.d.ts.map +1 -1
- package/dist/linters/rules/common.js +53 -0
- package/dist/linters/rules/common.js.map +1 -1
- package/dist/linters/rules/eqeqeq.rule.d.ts +2 -2
- package/dist/linters/rules/eqeqeq.rule.d.ts.map +1 -1
- package/dist/linters/rules/eqeqeq.rule.js +2 -1
- package/dist/linters/rules/eqeqeq.rule.js.map +1 -1
- package/dist/linters/rules/no-unused-vars.rule.d.ts +3 -3
- package/dist/linters/rules/no-unused-vars.rule.d.ts.map +1 -1
- package/dist/linters/rules/no-unused-vars.rule.js +2 -1
- package/dist/linters/rules/no-unused-vars.rule.js.map +1 -1
- package/dist/linters/rules/switch-case-braces.rule.d.ts +2 -2
- package/dist/linters/rules/switch-case-braces.rule.d.ts.map +1 -1
- package/dist/linters/rules/switch-case-braces.rule.js +2 -1
- package/dist/linters/rules/switch-case-braces.rule.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -169,10 +169,12 @@ booleans. `BrowserOxlintConfigs.create()` and `ReactOxlintConfigs.create()` take
|
|
|
169
169
|
| `MaxParamsOwnRule` | `venizia/max-params-own` | `build({ max: 5 })` | A function we write takes at most `max` positional parameters. Not counted: an inline callback passed to a call or a JSX prop, a signature a declared type fixes, a constructor whose parameters are all `@inject`. A hook callback counts. |
|
|
170
170
|
| `NoNewErrorRule` | `venizia/no-new-error` | `error` | Throw through `getError` (or an `ApplicationError`), never `new Error(...)` / `Error(...)`. Off in tests. |
|
|
171
171
|
| `NoLeakedRenderRule` | `venizia/no-leaked-render` | `error`, in `reactHouseConfigs` only | A JSX child is drawn with `cond ? <X /> : null`, never `cond && <X />`, which draws `0` when `cond` is `0`. `--fix` rewrites it. `disabled={a && b}` is a value, not a child, and passes. |
|
|
172
|
-
| `ConstClassValuesRule` | `venizia/const-class-values` |
|
|
172
|
+
| `ConstClassValuesRule` | `venizia/const-class-values` | `warn` in both presets; `build({ severity, namePattern })` | V-C-08. A union of string literals in an exported declaration (a type alias, an interface member, a generic constraint, a parameter or return type) is a const class plus `TConstValue<typeof X>`. Not counted: `Pick`, `Omit`, `Extract`, `Exclude`, `Record` arguments and mapped-type keys, and a union with a non-string member. `namePattern` narrows it to exported type aliases whose name matches. Off in tests. |
|
|
173
|
+
| `@typescript-eslint/consistent-type-assertions` | `assertionStyle: never` | `warn` in both presets | V-C-10. `as X`, `as any` and `as unknown as X` warn; `as const` and `satisfies` do not. Off in tests. |
|
|
173
174
|
|
|
174
|
-
`const-class-values`
|
|
175
|
-
|
|
175
|
+
`const-class-values` and the cast rule only warn, so adopting them never fails a lint. Raise one to an error
|
|
176
|
+
with `[ConstClassValuesRule.NAME]: ConstClassValuesRule.build({ severity: 'error' })`. The 5-parameter
|
|
177
|
+
limit (V-C-02) is `venizia/max-params-own`, an error.
|
|
176
178
|
|
|
177
179
|
### namingConventionConfigs
|
|
178
180
|
|
package/dist/cli/clean.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/** `devz clean`: removes what the build and the checks generate, and nothing else. */
|
|
1
|
+
/** `devz clean`: removes what the build and the checks generate, and nothing else. `--help` prints the usage; any other argument is refused, and nothing is deleted. */
|
|
2
2
|
export declare class CleanCommand {
|
|
3
3
|
static run(opts: {
|
|
4
4
|
root: string;
|
|
5
|
+
args?: string[];
|
|
5
6
|
}): number;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=clean.d.ts.map
|
package/dist/cli/clean.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../src/cli/clean.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../src/cli/clean.ts"],"names":[],"mappings":"AAsBA,wKAAwK;AACxK,qBAAa,YAAY;IACvB,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,MAAM;CA2B5D"}
|
package/dist/cli/clean.js
CHANGED
|
@@ -5,12 +5,39 @@ const node_fs_1 = require("node:fs");
|
|
|
5
5
|
const node_path_1 = require("node:path");
|
|
6
6
|
/** What a build and the checks generate, relative to the project root. */
|
|
7
7
|
const GENERATED_PATHS = ['dist', 'node_modules/.cache'];
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* `incremental` is on in the base tsconfig, so a type-check that emits nothing leaves
|
|
10
|
+
* `<tsconfig name>.tsbuildinfo` next to the tsconfig. One inside `dist` is already removed with it.
|
|
11
|
+
*/
|
|
12
|
+
const BUILD_INFO_SUFFIX = '.tsbuildinfo';
|
|
13
|
+
const USAGE = `Usage: devz clean
|
|
14
|
+
|
|
15
|
+
Removes what the build and the checks generate, in the current folder: dist, node_modules/.cache and
|
|
16
|
+
the *.tsbuildinfo files next to the tsconfig. It takes no argument.
|
|
17
|
+
|
|
18
|
+
--help print this text and exit`;
|
|
19
|
+
/** A usage error: nothing was deleted. */
|
|
20
|
+
const USAGE_ERROR_CODE = 2;
|
|
21
|
+
/** `devz clean`: removes what the build and the checks generate, and nothing else. `--help` prints the usage; any other argument is refused, and nothing is deleted. */
|
|
9
22
|
class CleanCommand {
|
|
10
23
|
static run(opts) {
|
|
24
|
+
const { args = [] } = opts;
|
|
25
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
26
|
+
console.log(USAGE);
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
if (args.length > 0) {
|
|
30
|
+
console.error(`devz clean: unexpected argument ${args.map((arg) => `"${arg}"`).join(', ')}\n${USAGE}`);
|
|
31
|
+
return USAGE_ERROR_CODE;
|
|
32
|
+
}
|
|
11
33
|
for (const path of GENERATED_PATHS) {
|
|
12
34
|
(0, node_fs_1.rmSync)((0, node_path_1.join)(opts.root, path), { recursive: true, force: true });
|
|
13
35
|
}
|
|
36
|
+
for (const entry of (0, node_fs_1.readdirSync)(opts.root, { withFileTypes: true })) {
|
|
37
|
+
if (entry.isFile() && entry.name.endsWith(BUILD_INFO_SUFFIX)) {
|
|
38
|
+
(0, node_fs_1.rmSync)((0, node_path_1.join)(opts.root, entry.name), { force: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
14
41
|
return 0;
|
|
15
42
|
}
|
|
16
43
|
}
|
package/dist/cli/clean.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/cli/clean.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/cli/clean.ts"],"names":[],"mappings":";;;AAAA,qCAA8C;AAC9C,yCAAiC;AAEjC,0EAA0E;AAC1E,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,MAAM,KAAK,GAAG;;;;;sCAKwB,CAAC;AAEvC,0CAA0C;AAC1C,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,wKAAwK;AACxK,MAAa,YAAY;IACvB,MAAM,CAAC,GAAG,CAAC,IAAuC;QAChD,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CACX,mCAAmC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CACxF,CAAC;YACF,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACnC,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAA,qBAAW,EAAC,IAAI,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAC7D,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AA5BD,oCA4BC","sourcesContent":["import { readdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** What a build and the checks generate, relative to the project root. */\nconst GENERATED_PATHS = ['dist', 'node_modules/.cache'];\n\n/**\n * `incremental` is on in the base tsconfig, so a type-check that emits nothing leaves\n * `<tsconfig name>.tsbuildinfo` next to the tsconfig. One inside `dist` is already removed with it.\n */\nconst BUILD_INFO_SUFFIX = '.tsbuildinfo';\n\nconst USAGE = `Usage: devz clean\n\nRemoves what the build and the checks generate, in the current folder: dist, node_modules/.cache and\nthe *.tsbuildinfo files next to the tsconfig. It takes no argument.\n\n --help print this text and exit`;\n\n/** A usage error: nothing was deleted. */\nconst USAGE_ERROR_CODE = 2;\n\n/** `devz clean`: removes what the build and the checks generate, and nothing else. `--help` prints the usage; any other argument is refused, and nothing is deleted. */\nexport class CleanCommand {\n static run(opts: { root: string; args?: string[] }): number {\n const { args = [] } = opts;\n\n if (args.includes('--help') || args.includes('-h')) {\n console.log(USAGE);\n return 0;\n }\n\n if (args.length > 0) {\n console.error(\n `devz clean: unexpected argument ${args.map((arg) => `\"${arg}\"`).join(', ')}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n for (const path of GENERATED_PATHS) {\n rmSync(join(opts.root, path), { recursive: true, force: true });\n }\n\n for (const entry of readdirSync(opts.root, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith(BUILD_INFO_SUFFIX)) {\n rmSync(join(opts.root, entry.name), { force: true });\n }\n }\n\n return 0;\n }\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The source files a codemod may touch. Inside a git repository the list comes from git, so a
|
|
3
|
+
* `.gitignore`d folder (a worktree, a clone, a build output) is never entered. Outside git there is
|
|
4
|
+
* no ignore file to read, so the walk skips every dot-directory as well as `node_modules`, `dist`,
|
|
5
|
+
* `build` and `.git`.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CodemodFiles {
|
|
8
|
+
/** Every `.ts`, `.tsx`, `.mts` or `.cts` file (declaration files excluded) the codemod may touch under `target`; a file target is returned as it is. */
|
|
9
|
+
static collect(opts: {
|
|
10
|
+
target: string;
|
|
11
|
+
}): string[];
|
|
12
|
+
/** Tracked files plus untracked files git does not ignore; `undefined` outside a repository or without git. */
|
|
13
|
+
static fromGit(opts: {
|
|
14
|
+
target: string;
|
|
15
|
+
}): string[] | undefined;
|
|
16
|
+
/** The directory walk used outside git: skips dot-directories and the build folders. */
|
|
17
|
+
static fromWalk(opts: {
|
|
18
|
+
target: string;
|
|
19
|
+
}): string[];
|
|
20
|
+
private static isSource;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/files.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,wJAAwJ;IACxJ,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE;IAUlD,+GAA+G;IAC/G,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE,GAAG,SAAS;IA2B9D,wFAAwF;IACxF,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAAE;IAoBnD,OAAO,CAAC,MAAM,CAAC,QAAQ;CAGxB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodemodFiles = void 0;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', 'build', '.git']);
|
|
8
|
+
const SOURCE_PATTERN = /\.(?:ts|tsx|mts|cts)$/;
|
|
9
|
+
/**
|
|
10
|
+
* The source files a codemod may touch. Inside a git repository the list comes from git, so a
|
|
11
|
+
* `.gitignore`d folder (a worktree, a clone, a build output) is never entered. Outside git there is
|
|
12
|
+
* no ignore file to read, so the walk skips every dot-directory as well as `node_modules`, `dist`,
|
|
13
|
+
* `build` and `.git`.
|
|
14
|
+
*/
|
|
15
|
+
class CodemodFiles {
|
|
16
|
+
/** Every `.ts`, `.tsx`, `.mts` or `.cts` file (declaration files excluded) the codemod may touch under `target`; a file target is returned as it is. */
|
|
17
|
+
static collect(opts) {
|
|
18
|
+
const { target } = opts;
|
|
19
|
+
if ((0, node_fs_1.statSync)(target).isFile()) {
|
|
20
|
+
return [target];
|
|
21
|
+
}
|
|
22
|
+
return CodemodFiles.fromGit({ target }) ?? CodemodFiles.fromWalk({ target });
|
|
23
|
+
}
|
|
24
|
+
/** Tracked files plus untracked files git does not ignore; `undefined` outside a repository or without git. */
|
|
25
|
+
static fromGit(opts) {
|
|
26
|
+
const { target } = opts;
|
|
27
|
+
let output;
|
|
28
|
+
try {
|
|
29
|
+
output = (0, node_child_process_1.execFileSync)('git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z'], {
|
|
30
|
+
cwd: target,
|
|
31
|
+
encoding: 'utf8',
|
|
32
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
33
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
return output
|
|
40
|
+
.split('\0')
|
|
41
|
+
.filter((path) => path !== '' && CodemodFiles.isSource({ name: path }))
|
|
42
|
+
.filter((path) => !path.split('/').some((segment) => SKIPPED_DIRECTORIES.has(segment)))
|
|
43
|
+
.map((path) => (0, node_path_1.join)(target, path))
|
|
44
|
+
.filter((path) => (0, node_fs_1.existsSync)(path) && (0, node_fs_1.statSync)(path).isFile());
|
|
45
|
+
}
|
|
46
|
+
/** The directory walk used outside git: skips dot-directories and the build folders. */
|
|
47
|
+
static fromWalk(opts) {
|
|
48
|
+
const { target } = opts;
|
|
49
|
+
const files = [];
|
|
50
|
+
for (const entry of (0, node_fs_1.readdirSync)(target, { withFileTypes: true })) {
|
|
51
|
+
if (entry.isDirectory()) {
|
|
52
|
+
if (!SKIPPED_DIRECTORIES.has(entry.name) && !entry.name.startsWith('.')) {
|
|
53
|
+
files.push(...CodemodFiles.fromWalk({ target: (0, node_path_1.join)(target, entry.name) }));
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (CodemodFiles.isSource({ name: entry.name })) {
|
|
58
|
+
files.push((0, node_path_1.join)(target, entry.name));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return files;
|
|
62
|
+
}
|
|
63
|
+
static isSource(opts) {
|
|
64
|
+
return SOURCE_PATTERN.test(opts.name) && !opts.name.endsWith('.d.ts');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.CodemodFiles = CodemodFiles;
|
|
68
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/cli/codemod/files.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { existsSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', 'build', '.git']);\nconst SOURCE_PATTERN = /\\.(?:ts|tsx|mts|cts)$/;\n\n/**\n * The source files a codemod may touch. Inside a git repository the list comes from git, so a\n * `.gitignore`d folder (a worktree, a clone, a build output) is never entered. Outside git there is\n * no ignore file to read, so the walk skips every dot-directory as well as `node_modules`, `dist`,\n * `build` and `.git`.\n */\nexport class CodemodFiles {\n /** Every `.ts`, `.tsx`, `.mts` or `.cts` file (declaration files excluded) the codemod may touch under `target`; a file target is returned as it is. */\n static collect(opts: { target: string }): string[] {\n const { target } = opts;\n\n if (statSync(target).isFile()) {\n return [target];\n }\n\n return CodemodFiles.fromGit({ target }) ?? CodemodFiles.fromWalk({ target });\n }\n\n /** Tracked files plus untracked files git does not ignore; `undefined` outside a repository or without git. */\n static fromGit(opts: { target: string }): string[] | undefined {\n const { target } = opts;\n let output: string;\n\n try {\n output = execFileSync(\n 'git',\n ['ls-files', '--cached', '--others', '--exclude-standard', '-z'],\n {\n cwd: target,\n encoding: 'utf8',\n maxBuffer: 256 * 1024 * 1024,\n stdio: ['ignore', 'pipe', 'ignore'],\n },\n );\n } catch {\n return undefined;\n }\n\n return output\n .split('\\0')\n .filter((path) => path !== '' && CodemodFiles.isSource({ name: path }))\n .filter((path) => !path.split('/').some((segment) => SKIPPED_DIRECTORIES.has(segment)))\n .map((path) => join(target, path))\n .filter((path) => existsSync(path) && statSync(path).isFile());\n }\n\n /** The directory walk used outside git: skips dot-directories and the build folders. */\n static fromWalk(opts: { target: string }): string[] {\n const { target } = opts;\n const files: string[] = [];\n\n for (const entry of readdirSync(target, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (!SKIPPED_DIRECTORIES.has(entry.name) && !entry.name.startsWith('.')) {\n files.push(...CodemodFiles.fromWalk({ target: join(target, entry.name) }));\n }\n continue;\n }\n\n if (CodemodFiles.isSource({ name: entry.name })) {\n files.push(join(target, entry.name));\n }\n }\n\n return files;\n }\n\n private static isSource(opts: { name: string }): boolean {\n return SOURCE_PATTERN.test(opts.name) && !opts.name.endsWith('.d.ts');\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `devz codemod model-settings [paths...] [--write | --check]`: moves `@model` settings from the
|
|
3
|
+
* flat keys (`defaultFilter`, `defaultLimit`, `maxLimit`, `scopeFilter`) to `query` and `access`,
|
|
4
|
+
* and `skipMigrate` to `migration.use`. It is a dry run unless `--write` is given: it lists what
|
|
5
|
+
* would change. `--check` is the same dry run, and exits 1 when anything would change.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CodemodCommand {
|
|
8
|
+
static run(opts: {
|
|
9
|
+
root: string;
|
|
10
|
+
args: string[];
|
|
11
|
+
}): Promise<number>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/index.ts"],"names":[],"mappings":"AAqCA;;;;;GAKG;AACH,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CA0F1E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodemodCommand = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const files_1 = require("./files");
|
|
7
|
+
const model_settings_1 = require("./model-settings");
|
|
8
|
+
const USAGE = `Usage: devz codemod model-settings [paths...] [--write | --check]
|
|
9
|
+
|
|
10
|
+
Moves @model settings to the grouped shape and skipMigrate to migration.use.
|
|
11
|
+
|
|
12
|
+
--write write the changed files (without it, nothing is written)
|
|
13
|
+
--check dry run that exits 1 when anything would change (for CI)
|
|
14
|
+
--help print this text and exit
|
|
15
|
+
|
|
16
|
+
With no flag it lists what would change and writes nothing. Inside a git repository it reads the
|
|
17
|
+
files git knows (tracked, or untracked and not ignored), so ignored folders are never touched.`;
|
|
18
|
+
/** A usage error: nothing was read or written. */
|
|
19
|
+
const USAGE_ERROR_CODE = 2;
|
|
20
|
+
class CodemodFlags {
|
|
21
|
+
static { this.WRITE = '--write'; }
|
|
22
|
+
static { this.CHECK = '--check'; }
|
|
23
|
+
static { this.HELP = '--help'; }
|
|
24
|
+
static { this.HELP_SHORT = '-h'; }
|
|
25
|
+
static { this.SCHEME_SET = new Set([
|
|
26
|
+
this.WRITE,
|
|
27
|
+
this.CHECK,
|
|
28
|
+
this.HELP,
|
|
29
|
+
this.HELP_SHORT,
|
|
30
|
+
]); }
|
|
31
|
+
static isValid(value) {
|
|
32
|
+
return this.SCHEME_SET.has(value);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* `devz codemod model-settings [paths...] [--write | --check]`: moves `@model` settings from the
|
|
37
|
+
* flat keys (`defaultFilter`, `defaultLimit`, `maxLimit`, `scopeFilter`) to `query` and `access`,
|
|
38
|
+
* and `skipMigrate` to `migration.use`. It is a dry run unless `--write` is given: it lists what
|
|
39
|
+
* would change. `--check` is the same dry run, and exits 1 when anything would change.
|
|
40
|
+
*/
|
|
41
|
+
class CodemodCommand {
|
|
42
|
+
static async run(opts) {
|
|
43
|
+
const { args } = opts;
|
|
44
|
+
if (args.includes(CodemodFlags.HELP) || args.includes(CodemodFlags.HELP_SHORT)) {
|
|
45
|
+
console.log(USAGE);
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
const [name, ...rest] = args;
|
|
49
|
+
if (name !== 'model-settings') {
|
|
50
|
+
console.error(`devz codemod: unknown codemod "${name ?? ''}"\n${USAGE}`);
|
|
51
|
+
return USAGE_ERROR_CODE;
|
|
52
|
+
}
|
|
53
|
+
const unknown = rest.filter((argument) => argument.startsWith('-') && !CodemodFlags.isValid(argument));
|
|
54
|
+
if (unknown.length > 0) {
|
|
55
|
+
console.error(`devz codemod: unknown option ${unknown.map((flag) => `"${flag}"`).join(', ')}\n${USAGE}`);
|
|
56
|
+
return USAGE_ERROR_CODE;
|
|
57
|
+
}
|
|
58
|
+
const isWrite = rest.includes(CodemodFlags.WRITE);
|
|
59
|
+
const isCheck = rest.includes(CodemodFlags.CHECK);
|
|
60
|
+
if (isWrite && isCheck) {
|
|
61
|
+
console.error(`devz codemod: ${CodemodFlags.WRITE} and ${CodemodFlags.CHECK} contradict each other\n${USAGE}`);
|
|
62
|
+
return USAGE_ERROR_CODE;
|
|
63
|
+
}
|
|
64
|
+
const paths = rest.filter((argument) => !argument.startsWith('-'));
|
|
65
|
+
const targets = (paths.length > 0 ? paths : ['.']).map((path) => (0, node_path_1.resolve)(opts.root, path));
|
|
66
|
+
let typescript;
|
|
67
|
+
try {
|
|
68
|
+
typescript = (await import('typescript')).default;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
console.error('devz codemod: the "typescript" package is required to read your sources');
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
let changedCount = 0;
|
|
75
|
+
let reportCount = 0;
|
|
76
|
+
for (const target of targets) {
|
|
77
|
+
for (const file of files_1.CodemodFiles.collect({ target })) {
|
|
78
|
+
const source = (0, node_fs_1.readFileSync)(file, 'utf8');
|
|
79
|
+
if (!source.includes('@model')) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const result = (0, model_settings_1.migrateModelSettings)({ typescript, fileName: file, source });
|
|
83
|
+
const shown = (0, node_path_1.relative)(opts.root, file) || file;
|
|
84
|
+
for (const report of result.reports) {
|
|
85
|
+
reportCount += 1;
|
|
86
|
+
console.warn(`${shown}:${report.line}:${report.column} ${report.reason}`);
|
|
87
|
+
}
|
|
88
|
+
if (!result.changed) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
changedCount += 1;
|
|
92
|
+
console.log(`${isWrite ? 'changed' : 'would change'} ${shown} (${result.rewritten} model(s))`);
|
|
93
|
+
if (isWrite) {
|
|
94
|
+
(0, node_fs_1.writeFileSync)(file, result.output);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
console.log(`devz codemod model-settings: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${reportCount} left untouched`);
|
|
99
|
+
if (!isWrite && changedCount > 0) {
|
|
100
|
+
console.log(`Nothing was written. Run again with ${CodemodFlags.WRITE} to apply.`);
|
|
101
|
+
}
|
|
102
|
+
return isCheck && changedCount > 0 ? 1 : 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.CodemodCommand = CodemodCommand;
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/codemod/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { CodemodFiles } from './files';\nimport { migrateModelSettings } from './model-settings';\n\nconst USAGE = `Usage: devz codemod model-settings [paths...] [--write | --check]\n\nMoves @model settings to the grouped shape and skipMigrate to migration.use.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 when anything would change (for CI)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), so ignored folders are never touched.`;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\nclass CodemodFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\n/**\n * `devz codemod model-settings [paths...] [--write | --check]`: moves `@model` settings from the\n * flat keys (`defaultFilter`, `defaultLimit`, `maxLimit`, `scopeFilter`) to `query` and `access`,\n * and `skipMigrate` to `migration.use`. It is a dry run unless `--write` is given: it lists what\n * would change. `--check` is the same dry run, and exits 1 when anything would change.\n */\nexport class CodemodCommand {\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { args } = opts;\n\n if (args.includes(CodemodFlags.HELP) || args.includes(CodemodFlags.HELP_SHORT)) {\n console.log(USAGE);\n return 0;\n }\n\n const [name, ...rest] = args;\n\n if (name !== 'model-settings') {\n console.error(`devz codemod: unknown codemod \"${name ?? ''}\"\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const unknown = rest.filter(\n (argument) => argument.startsWith('-') && !CodemodFlags.isValid(argument),\n );\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = rest.includes(CodemodFlags.WRITE);\n const isCheck = rest.includes(CodemodFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${CodemodFlags.WRITE} and ${CodemodFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const paths = rest.filter((argument) => !argument.startsWith('-'));\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(opts.root, path));\n\n let typescript: typeof import('typescript');\n try {\n typescript = (await import('typescript')).default;\n } catch {\n console.error('devz codemod: the \"typescript\" package is required to read your sources');\n return 1;\n }\n\n let changedCount = 0;\n let reportCount = 0;\n\n for (const target of targets) {\n for (const file of CodemodFiles.collect({ target })) {\n const source = readFileSync(file, 'utf8');\n\n if (!source.includes('@model')) {\n continue;\n }\n\n const result = migrateModelSettings({ typescript, fileName: file, source });\n const shown = relative(opts.root, file) || file;\n\n for (const report of result.reports) {\n reportCount += 1;\n console.warn(`${shown}:${report.line}:${report.column} ${report.reason}`);\n }\n\n if (!result.changed) {\n continue;\n }\n\n changedCount += 1;\n console.log(\n `${isWrite ? 'changed' : 'would change'} ${shown} (${result.rewritten} model(s))`,\n );\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod model-settings: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${reportCount} left untouched`,\n );\n\n if (!isWrite && changedCount > 0) {\n console.log(`Nothing was written. Run again with ${CodemodFlags.WRITE} to apply.`);\n }\n\n return isCheck && changedCount > 0 ? 1 : 0;\n }\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type ts from 'typescript';
|
|
2
|
+
type TTypeScript = typeof ts;
|
|
3
|
+
/** One thing the codemod could not decide and left alone. */
|
|
4
|
+
export interface IModelSettingsReport {
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
reason: string;
|
|
8
|
+
}
|
|
9
|
+
export interface IModelSettingsResult {
|
|
10
|
+
/** The source after the migration; equal to the input when nothing changed. */
|
|
11
|
+
output: string;
|
|
12
|
+
changed: boolean;
|
|
13
|
+
/** How many `@model` settings objects were rewritten. */
|
|
14
|
+
rewritten: number;
|
|
15
|
+
reports: IModelSettingsReport[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Rewrites `@model({ ... })` from the old keys to the grouped ones. `skipMigrate` becomes
|
|
19
|
+
* `migration: { use: false }`. In the `settings` object literal:
|
|
20
|
+
* `defaultFilter` to `query.filter`, `defaultLimit` and `maxLimit` to `query.limit.default` and
|
|
21
|
+
* `query.limit.max`, `scopeFilter` to `access` (`writeGuard` to `write.mode`, `sharedRows` to
|
|
22
|
+
* `write.sharedRows`).
|
|
23
|
+
*
|
|
24
|
+
* It edits by source range, so comments and formatting outside the rewritten properties stay. It
|
|
25
|
+
* never guesses: a `settings` value that is not an object literal, a spread, a computed key, or a
|
|
26
|
+
* `scopeFilter` that is not an object literal is reported and the model is left untouched.
|
|
27
|
+
*/
|
|
28
|
+
export declare const migrateModelSettings: (opts: {
|
|
29
|
+
typescript: TTypeScript;
|
|
30
|
+
fileName: string;
|
|
31
|
+
source: string;
|
|
32
|
+
}) => IModelSettingsResult;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=model-settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-settings.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/model-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,KAAK,WAAW,GAAG,OAAO,EAAE,CAAC;AAE7B,6DAA6D;AAC7D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAWD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAAI,MAAM;IACzC,UAAU,EAAE,WAAW,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,KAAG,oBAuXH,CAAC"}
|