@craft-ng/dev-tools 0.5.1-beta.0 → 0.6.0-beta.2
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 +66 -0
- package/generators.json +26 -0
- package/package.json +18 -1
- package/src/bin/craft.d.ts +2 -0
- package/src/bin/craft.js +166 -0
- package/src/bin/craft.js.map +1 -0
- package/src/eslint-rules/craft-computed-name-match.cjs +8 -125
- package/src/eslint-rules/craft-method-name-match.cjs +8 -166
- package/src/eslint-rules/craft-name-match-utils.cjs +179 -0
- package/src/eslint-rules/craft-signal-source-name-match.cjs +8 -0
- package/src/eslint-rules/craft-source-name-match.cjs +8 -0
- package/src/eslint-rules/global-exception-registry-match.cjs +78 -13
- package/src/eslint-rules/index.cjs +8 -2
- package/src/eslint-rules/require-cascade-route-di-check.cjs +223 -0
- package/src/eslint-rules/require-primitive-generator-unwrap.cjs +267 -0
- package/src/generators/route/compat.d.ts +3 -0
- package/src/generators/route/compat.js +6 -0
- package/src/generators/route/compat.js.map +1 -0
- package/src/generators/route/generator.d.ts +31 -0
- package/src/generators/route/generator.js +434 -0
- package/src/generators/route/generator.js.map +1 -0
- package/src/generators/route/schema.json +50 -0
- package/src/generators/route/split-schema.json +19 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/scripts/primitives/migrate-primitive-generators.d.ts +27 -0
- package/src/scripts/primitives/migrate-primitive-generators.js +315 -0
- package/src/scripts/primitives/migrate-primitive-generators.js.map +1 -0
- package/src/scripts/primitives/migrate-primitive-generators.ts +402 -0
- package/src/scripts/primitives/migrate-primitives.js +36 -4
- package/src/scripts/primitives/migrate-primitives.js.map +1 -1
- package/src/scripts/primitives/migrate-primitives.spec.ts +43 -0
- package/src/scripts/primitives/migrate-primitives.ts +62 -4
- package/src/scripts/primitives/migration-diagnostic.d.ts +1 -1
- package/src/scripts/primitives/migration-diagnostic.ts +1 -0
- package/src/scripts/routes/migrate-routes.js +4 -4
- package/src/scripts/routes/migrate-routes.js.map +1 -1
- package/src/scripts/routes/migrate-routes.ts +4 -6
- package/src/scripts/routes/route-command.d.ts +75 -0
- package/src/scripts/routes/route-command.js +1187 -0
- package/src/scripts/routes/route-command.js.map +1 -0
- package/src/scripts/routes/route-command.spec.ts +553 -0
- package/src/scripts/routes/route-command.ts +1790 -0
- package/src/scripts/services/migrate-services.js +45 -11
- package/src/scripts/services/migrate-services.js.map +1 -1
- package/src/scripts/services/migrate-services.spec.ts +46 -4
- package/src/scripts/services/migrate-services.ts +64 -13
- package/src/scripts/services/migration-diagnostic.d.ts +1 -1
- package/src/scripts/services/migration-diagnostic.ts +1 -0
- package/src/eslint-rules/require-track-on-dependent-primitives.cjs +0 -219
package/README.md
CHANGED
|
@@ -147,6 +147,71 @@ The service migration also:
|
|
|
147
147
|
statically resolvable component routes with `craftRoute`, generates or reuses
|
|
148
148
|
their `GenDeps_*` type, and adds the file-level DI check.
|
|
149
149
|
|
|
150
|
+
For new routes, use the `craft` façade rather than the migration command:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npx craft route add /users/:userId --component src/app/users/user-detail.ts#UserDetailComponent
|
|
154
|
+
npx craft route add /users/:userId --create-component users/user-detail
|
|
155
|
+
npx craft route add /legacy --redirect-to /users --parent src/app/app.routes.ts#appRoutes
|
|
156
|
+
npx craft route split --parent src/app/app.routes.ts#appRoutes --prefix users --target src/app/users/users.routes.ts
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The same route engine is also published as a native Nx generator and as an
|
|
160
|
+
Angular CLI schematic. Both use a virtual workspace tree, so their host CLI
|
|
161
|
+
provides project-name resolution and `--dry-run` without direct filesystem
|
|
162
|
+
writes:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Nx workspace
|
|
166
|
+
npx nx g @craft-ng/dev-tools:route /users/:userId \
|
|
167
|
+
--project=my-app \
|
|
168
|
+
--create-component=users/UserDetail
|
|
169
|
+
|
|
170
|
+
npx nx g @craft-ng/dev-tools:route-split \
|
|
171
|
+
--project=my-app \
|
|
172
|
+
--parent=apps/my-app/src/app/app.routes.ts#appRoutes \
|
|
173
|
+
--prefix=users \
|
|
174
|
+
--target=apps/my-app/src/app/users/users.routes.ts
|
|
175
|
+
|
|
176
|
+
# Angular CLI workspace
|
|
177
|
+
npx ng g @craft-ng/dev-tools:route /users/:userId \
|
|
178
|
+
--project=my-app \
|
|
179
|
+
--create-component=users/UserDetail
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Without route target options, the generator asks for the target kind. Component
|
|
183
|
+
creation then asks for the path relative to the application's `src/app` base,
|
|
184
|
+
followed by the component name. Before mutating the virtual tree it prints the
|
|
185
|
+
planned `CREATE` and `UPDATE` operations and asks for confirmation. Use `--yes`
|
|
186
|
+
for non-interactive automation; Nx/Angular `--dry-run` prints the preview without
|
|
187
|
+
asking for confirmation or writing files.
|
|
188
|
+
|
|
189
|
+
When `--parent` is omitted in an interactive terminal, the generator discovers
|
|
190
|
+
every `craftRoutes(...)` collection in the selected Angular project and lists
|
|
191
|
+
its exported routes name, source file, and prefix. Select `0` to retain route
|
|
192
|
+
path-based auto-detection, or choose a collection number. Scripted calls can
|
|
193
|
+
still pass `--parent=path/to/routes.ts#routesName` directly.
|
|
194
|
+
|
|
195
|
+
Pass `--skip-validation` when another task will run lint and the Angular build.
|
|
196
|
+
Otherwise validation runs after the virtual tree has been committed. Nx
|
|
197
|
+
workspaces compose the native `@nx/angular:component` generator; Angular CLI
|
|
198
|
+
workspaces compose the local `@schematics/angular:component` schematic. New
|
|
199
|
+
components use an inline template and inline styles, so the generator creates a
|
|
200
|
+
single component `.ts` file rather than separate `.ts`, `.html`, and `.css`
|
|
201
|
+
files. Component filenames are always normalized to kebab-case: a component
|
|
202
|
+
name such as `DemoPage` produces `demo-page.ts` while retaining the `DemoPage`
|
|
203
|
+
class name.
|
|
204
|
+
|
|
205
|
+
The add command defaults to a lazy routes file per feature and generates
|
|
206
|
+
`componentDeps`, `withRetry`, the cascade DI proof, exception assertion,
|
|
207
|
+
`.withParent`, and the parent mount assertion. Both commands print their plan
|
|
208
|
+
before writing. `--dry-run`, `--yes`, `--json`, `--project`, `--parent`, and
|
|
209
|
+
`--feature-file` support scripted usage. After writing, ESLint autofix and the
|
|
210
|
+
project TypeScript diagnostics run automatically; failed validation leaves the
|
|
211
|
+
changes in place and returns a non-zero exit code with diagnostics.
|
|
212
|
+
Component creation uses the local Angular CLI in an `angular.json` workspace,
|
|
213
|
+
or the local Nx Angular schematic in an `nx.json` workspace.
|
|
214
|
+
|
|
150
215
|
Start with a dry run:
|
|
151
216
|
|
|
152
217
|
```bash
|
|
@@ -197,6 +262,7 @@ export default [
|
|
|
197
262
|
'craft-ng/prefer-craft-http-client': 'error',
|
|
198
263
|
'craft-ng/prefer-browser-boundaries': 'error',
|
|
199
264
|
'craft-ng/require-lazy-load-with-retry': 'error',
|
|
265
|
+
'craft-ng/require-cascade-route-di-check': 'error',
|
|
200
266
|
}
|
|
201
267
|
}
|
|
202
268
|
];
|
package/generators.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generators": {
|
|
3
|
+
"route": {
|
|
4
|
+
"factory": "./src/generators/route/generator#routeGenerator",
|
|
5
|
+
"schema": "./src/generators/route/schema.json",
|
|
6
|
+
"description": "Add a type-safe Craft NG route."
|
|
7
|
+
},
|
|
8
|
+
"route-split": {
|
|
9
|
+
"factory": "./src/generators/route/generator#routeSplitGenerator",
|
|
10
|
+
"schema": "./src/generators/route/split-schema.json",
|
|
11
|
+
"description": "Split Craft NG routes into a lazy collection."
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"schematics": {
|
|
15
|
+
"route": {
|
|
16
|
+
"factory": "./src/generators/route/compat#routeSchematic",
|
|
17
|
+
"schema": "./src/generators/route/schema.json",
|
|
18
|
+
"description": "Add a type-safe Craft NG route."
|
|
19
|
+
},
|
|
20
|
+
"route-split": {
|
|
21
|
+
"factory": "./src/generators/route/compat#routeSplitSchematic",
|
|
22
|
+
"schema": "./src/generators/route/split-schema.json",
|
|
23
|
+
"description": "Split Craft NG routes into a lazy collection."
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@craft-ng/dev-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-beta.2",
|
|
4
4
|
"description": "Development tools for ng-craft: ESLint configs, ESLint rules, and codemods",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/ng-angular-stack/ng-craft.git"
|
|
8
|
+
},
|
|
5
9
|
"type": "module",
|
|
6
10
|
"main": "./src/index.js",
|
|
7
11
|
"types": "./src/index.d.ts",
|
|
@@ -16,7 +20,10 @@
|
|
|
16
20
|
},
|
|
17
21
|
"./package.json": "./package.json"
|
|
18
22
|
},
|
|
23
|
+
"generators": "./generators.json",
|
|
24
|
+
"schematics": "./generators.json",
|
|
19
25
|
"bin": {
|
|
26
|
+
"craft": "./src/bin/craft.js",
|
|
20
27
|
"craft-brand": "./src/bin/craft-brand.js",
|
|
21
28
|
"craft-migrate": "./src/bin/craft-migrate.js",
|
|
22
29
|
"craft-migrate-primitives": "./src/bin/craft-migrate-primitives.js",
|
|
@@ -24,10 +31,12 @@
|
|
|
24
31
|
"craft-migrate-routes": "./src/bin/craft-migrate-routes.js"
|
|
25
32
|
},
|
|
26
33
|
"files": [
|
|
34
|
+
"generators.json",
|
|
27
35
|
"src/**/*",
|
|
28
36
|
"README.md"
|
|
29
37
|
],
|
|
30
38
|
"dependencies": {
|
|
39
|
+
"@nx/devkit": "^22.3.1",
|
|
31
40
|
"tslib": "^2.3.0",
|
|
32
41
|
"ts-morph": "^24.0.0",
|
|
33
42
|
"ts-node": "^10.9.2",
|
|
@@ -35,6 +44,8 @@
|
|
|
35
44
|
},
|
|
36
45
|
"peerDependencies": {
|
|
37
46
|
"@angular-eslint/eslint-plugin": ">=21.0.0",
|
|
47
|
+
"@nx/angular": ">=21.0.0 <24.0.0",
|
|
48
|
+
"@schematics/angular": ">=20.0.0 <23.0.0",
|
|
38
49
|
"@typescript-eslint/eslint-plugin": ">=8.0.0",
|
|
39
50
|
"eslint": ">=9.0.0"
|
|
40
51
|
},
|
|
@@ -42,6 +53,12 @@
|
|
|
42
53
|
"@angular-eslint/eslint-plugin": {
|
|
43
54
|
"optional": true
|
|
44
55
|
},
|
|
56
|
+
"@nx/angular": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@schematics/angular": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
45
62
|
"@typescript-eslint/eslint-plugin": {
|
|
46
63
|
"optional": true
|
|
47
64
|
},
|
package/src/bin/craft.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { __awaiter } from "tslib";
|
|
3
|
+
import { createInterface } from 'node:readline/promises';
|
|
4
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
5
|
+
import { listAngularProjects, runRouteAdd, runRouteSplit, } from '../scripts/routes/route-command.js';
|
|
6
|
+
function main(argv) {
|
|
7
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
if (argv[0] !== 'route' || !['add', 'split'].includes((_a = argv[1]) !== null && _a !== void 0 ? _a : '')) {
|
|
10
|
+
printHelp();
|
|
11
|
+
return argv.includes('--help') ? 0 : 1;
|
|
12
|
+
}
|
|
13
|
+
const command = argv[1];
|
|
14
|
+
const parsed = parseArgs(argv.slice(2));
|
|
15
|
+
if (parsed.help) {
|
|
16
|
+
printHelp();
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
const common = {
|
|
20
|
+
rootDir: parsed.values['root'],
|
|
21
|
+
project: parsed.values['project'],
|
|
22
|
+
parent: parsed.values['parent'],
|
|
23
|
+
dryRun: parsed.flags.has('dry-run'),
|
|
24
|
+
yes: parsed.flags.has('yes'),
|
|
25
|
+
json: parsed.flags.has('json'),
|
|
26
|
+
};
|
|
27
|
+
const readline = createInterface({ input, output });
|
|
28
|
+
try {
|
|
29
|
+
if (!common.project && !common.yes) {
|
|
30
|
+
const projects = listAngularProjects(common.rootDir);
|
|
31
|
+
if (projects.length > 1) {
|
|
32
|
+
output.write(projects
|
|
33
|
+
.map((project, index) => `${index + 1}. ${project}`)
|
|
34
|
+
.join('\n') + '\n');
|
|
35
|
+
const selected = Number(yield readline.question('Angular project number: '));
|
|
36
|
+
common.project = projects[selected - 1];
|
|
37
|
+
if (!common.project)
|
|
38
|
+
throw new Error('Invalid project selection.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const confirm = (_plan) => __awaiter(this, void 0, void 0, function* () { return /^y(?:es)?$/i.test(yield readline.question('Apply this plan? [y/N] ')); });
|
|
42
|
+
let result;
|
|
43
|
+
if (command === 'add') {
|
|
44
|
+
const options = Object.assign(Object.assign({}, common), { path: (_b = parsed.positionals[0]) !== null && _b !== void 0 ? _b : (yield readline.question('Route path: ')), component: parsed.values['component'], createComponent: parsed.values['create-component'], featureFile: parsed.values['feature-file'], redirectTo: parsed.values['redirect-to'], confirm });
|
|
45
|
+
if (!options.component &&
|
|
46
|
+
!options.createComponent &&
|
|
47
|
+
!options.redirectTo) {
|
|
48
|
+
const kind = (yield readline.question('Target: [e]xisting component, [c]reate component, [r]edirect? ')).toLowerCase();
|
|
49
|
+
if (kind.startsWith('e')) {
|
|
50
|
+
options.component = yield readline.question('Component <file#Class>: ');
|
|
51
|
+
}
|
|
52
|
+
else if (kind.startsWith('c')) {
|
|
53
|
+
options.createComponent = yield readline.question('Angular component name/path: ');
|
|
54
|
+
}
|
|
55
|
+
else if (kind.startsWith('r')) {
|
|
56
|
+
options.redirectTo = yield readline.question('Redirect target: ');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
result = yield runRouteAdd(options);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const parent = common.parent;
|
|
63
|
+
const prefix = parsed.values['prefix'];
|
|
64
|
+
const target = parsed.values['target'];
|
|
65
|
+
if (!parent || !prefix || !target) {
|
|
66
|
+
throw new Error('route split requires --parent, --prefix, and --target.');
|
|
67
|
+
}
|
|
68
|
+
const options = Object.assign(Object.assign({}, common), { parent,
|
|
69
|
+
prefix,
|
|
70
|
+
target,
|
|
71
|
+
confirm });
|
|
72
|
+
result = yield runRouteSplit(options);
|
|
73
|
+
}
|
|
74
|
+
printResult(result, common.json === true);
|
|
75
|
+
return result.exitCode;
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
readline.close();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function parseArgs(argv) {
|
|
83
|
+
const values = {};
|
|
84
|
+
const flags = new Set();
|
|
85
|
+
const positionals = [];
|
|
86
|
+
let help = false;
|
|
87
|
+
const valueOptions = new Set([
|
|
88
|
+
'root',
|
|
89
|
+
'project',
|
|
90
|
+
'parent',
|
|
91
|
+
'component',
|
|
92
|
+
'create-component',
|
|
93
|
+
'feature-file',
|
|
94
|
+
'redirect-to',
|
|
95
|
+
'prefix',
|
|
96
|
+
'target',
|
|
97
|
+
]);
|
|
98
|
+
const flagOptions = new Set(['dry-run', 'yes', 'json']);
|
|
99
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
100
|
+
const argument = argv[index];
|
|
101
|
+
if (argument === '--help' || argument === '-h') {
|
|
102
|
+
help = true;
|
|
103
|
+
}
|
|
104
|
+
else if (argument.startsWith('--')) {
|
|
105
|
+
const name = argument.slice(2);
|
|
106
|
+
if (valueOptions.has(name)) {
|
|
107
|
+
const value = argv[++index];
|
|
108
|
+
if (!value || value.startsWith('--')) {
|
|
109
|
+
throw new Error(`Missing value for --${name}.`);
|
|
110
|
+
}
|
|
111
|
+
values[name] = value;
|
|
112
|
+
}
|
|
113
|
+
else if (flagOptions.has(name)) {
|
|
114
|
+
flags.add(name);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
throw new Error(`Unknown option --${name}.`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
positionals.push(argument);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return { values, flags, positionals, help };
|
|
125
|
+
}
|
|
126
|
+
function printResult(result, json) {
|
|
127
|
+
if (json) {
|
|
128
|
+
console.log(JSON.stringify(result, null, 2));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
for (const diagnostic of result.diagnostics) {
|
|
132
|
+
console.error(`${diagnostic.code}: ${diagnostic.message}`);
|
|
133
|
+
}
|
|
134
|
+
if (result.changedFiles.length > 0) {
|
|
135
|
+
console.log(`Changed:\n${result.changedFiles.map((file) => ` ${file}`).join('\n')}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function printHelp() {
|
|
139
|
+
console.log(`Usage:
|
|
140
|
+
craft route add [path] [options]
|
|
141
|
+
craft route split --parent <file#collection> --prefix <path> --target <file>
|
|
142
|
+
|
|
143
|
+
Options:
|
|
144
|
+
--root <dir> Workspace root (defaults to cwd)
|
|
145
|
+
--project <name|tsconfig> Angular project or tsconfig
|
|
146
|
+
--parent <file#collection> Parent craftRoutes collection
|
|
147
|
+
--component <file#Class> Existing routed component
|
|
148
|
+
--create-component <name> Generate with the local Angular CLI or Nx
|
|
149
|
+
--feature-file <file> Create/use an explicit lazy feature collection
|
|
150
|
+
--redirect-to <path> Add a static redirect
|
|
151
|
+
--prefix <path> Static prefix moved by route split
|
|
152
|
+
--target <file> New lazy collection written by route split
|
|
153
|
+
--dry-run Print the plan without writing
|
|
154
|
+
--yes Apply without confirmation
|
|
155
|
+
--json Emit machine-readable output
|
|
156
|
+
`);
|
|
157
|
+
}
|
|
158
|
+
main(process.argv.slice(2))
|
|
159
|
+
.then((exitCode) => {
|
|
160
|
+
process.exitCode = exitCode;
|
|
161
|
+
})
|
|
162
|
+
.catch((error) => {
|
|
163
|
+
console.error(error instanceof Error ? error.message : error);
|
|
164
|
+
process.exitCode = 1;
|
|
165
|
+
});
|
|
166
|
+
//# sourceMappingURL=craft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"craft.js","sourceRoot":"","sources":["../../../../../libs/dev-tools/src/bin/craft.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,125 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
schema: [],
|
|
10
|
-
messages: {
|
|
11
|
-
missingName:
|
|
12
|
-
"craftComputed must be called with a string literal name matching '{{declaredName}}' as the first argument.",
|
|
13
|
-
mismatchedName:
|
|
14
|
-
"craftComputed first argument '{{actual}}' must match the declared name '{{declaredName}}'.",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
create(context) {
|
|
18
|
-
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
CallExpression(node) {
|
|
22
|
-
if (
|
|
23
|
-
node.callee.type !== 'Identifier' ||
|
|
24
|
-
node.callee.name !== 'craftComputed'
|
|
25
|
-
) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const declaredName = getDeclaredName(node);
|
|
30
|
-
if (!declaredName) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const firstArg = node.arguments[0];
|
|
35
|
-
|
|
36
|
-
if (!firstArg) {
|
|
37
|
-
context.report({
|
|
38
|
-
node,
|
|
39
|
-
messageId: 'missingName',
|
|
40
|
-
data: { declaredName },
|
|
41
|
-
fix(fixer) {
|
|
42
|
-
const openParen = sourceCode.getTokenAfter(
|
|
43
|
-
node.callee,
|
|
44
|
-
(token) => token.type === 'Punctuator' && token.value === '(',
|
|
45
|
-
);
|
|
46
|
-
if (!openParen) return null;
|
|
47
|
-
return fixer.insertTextAfter(openParen, `'${declaredName}'`);
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (isStringLiteral(firstArg)) {
|
|
54
|
-
const actual = getStringLiteralValue(firstArg);
|
|
55
|
-
if (actual === declaredName) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
context.report({
|
|
59
|
-
node: firstArg,
|
|
60
|
-
messageId: 'mismatchedName',
|
|
61
|
-
data: { declaredName, actual },
|
|
62
|
-
fix(fixer) {
|
|
63
|
-
return fixer.replaceText(firstArg, `'${declaredName}'`);
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
context.report({
|
|
70
|
-
node: firstArg,
|
|
71
|
-
messageId: 'missingName',
|
|
72
|
-
data: { declaredName },
|
|
73
|
-
fix(fixer) {
|
|
74
|
-
return fixer.insertTextBefore(firstArg, `'${declaredName}', `);
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
function getDeclaredName(callNode) {
|
|
83
|
-
const parent = callNode.parent;
|
|
84
|
-
if (!parent) return undefined;
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
parent.type === 'VariableDeclarator' &&
|
|
88
|
-
parent.init === callNode &&
|
|
89
|
-
parent.id.type === 'Identifier'
|
|
90
|
-
) {
|
|
91
|
-
return parent.id.name;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
parent.type === 'PropertyDefinition' &&
|
|
96
|
-
parent.value === callNode &&
|
|
97
|
-
!parent.computed &&
|
|
98
|
-
parent.key.type === 'Identifier'
|
|
99
|
-
) {
|
|
100
|
-
return parent.key.name;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function isStringLiteral(node) {
|
|
107
|
-
if (node.type === 'Literal' && typeof node.value === 'string') {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
if (
|
|
111
|
-
node.type === 'TemplateLiteral' &&
|
|
112
|
-
node.expressions.length === 0 &&
|
|
113
|
-
node.quasis.length === 1
|
|
114
|
-
) {
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function getStringLiteralValue(node) {
|
|
121
|
-
if (node.type === 'Literal') {
|
|
122
|
-
return node.value;
|
|
123
|
-
}
|
|
124
|
-
return node.quasis[0].value.cooked;
|
|
125
|
-
}
|
|
1
|
+
const { createNameMatchRule } = require('./craft-name-match-utils.cjs');
|
|
2
|
+
|
|
3
|
+
module.exports = createNameMatchRule({
|
|
4
|
+
calleeName: 'craftComputed',
|
|
5
|
+
description:
|
|
6
|
+
"Ensure craftComputed(name, ...) is called with a string literal first argument that matches the declared variable or class property name.",
|
|
7
|
+
supportsObjectConfigForm: false,
|
|
8
|
+
});
|
|
@@ -1,166 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
schema: [],
|
|
10
|
-
messages: {
|
|
11
|
-
missingName:
|
|
12
|
-
"craftMethod must be called with a string literal name matching '{{declaredName}}' as the first argument.",
|
|
13
|
-
mismatchedName:
|
|
14
|
-
"craftMethod first argument '{{actual}}' must match the declared name '{{declaredName}}'.",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
create(context) {
|
|
18
|
-
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
CallExpression(node) {
|
|
22
|
-
if (
|
|
23
|
-
node.callee.type !== 'Identifier' ||
|
|
24
|
-
node.callee.name !== 'craftMethod'
|
|
25
|
-
) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const declaredName = getDeclaredName(node);
|
|
30
|
-
if (!declaredName) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const firstArg = node.arguments[0];
|
|
35
|
-
|
|
36
|
-
if (!firstArg) {
|
|
37
|
-
context.report({
|
|
38
|
-
node,
|
|
39
|
-
messageId: 'missingName',
|
|
40
|
-
data: { declaredName },
|
|
41
|
-
fix(fixer) {
|
|
42
|
-
const openParen = sourceCode.getTokenAfter(
|
|
43
|
-
node.callee,
|
|
44
|
-
(token) => token.type === 'Punctuator' && token.value === '(',
|
|
45
|
-
);
|
|
46
|
-
if (!openParen) return null;
|
|
47
|
-
return fixer.insertTextAfter(openParen, `'${declaredName}'`);
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Handle object config form: { name: 'methodName', providers: [...] }
|
|
54
|
-
if (firstArg.type === 'ObjectExpression') {
|
|
55
|
-
const nameProp = firstArg.properties.find(
|
|
56
|
-
(p) =>
|
|
57
|
-
p.type === 'Property' &&
|
|
58
|
-
!p.computed &&
|
|
59
|
-
p.key.type === 'Identifier' &&
|
|
60
|
-
p.key.name === 'name',
|
|
61
|
-
);
|
|
62
|
-
if (!nameProp) {
|
|
63
|
-
context.report({
|
|
64
|
-
node: firstArg,
|
|
65
|
-
messageId: 'missingName',
|
|
66
|
-
data: { declaredName },
|
|
67
|
-
});
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const nameValue = nameProp.value;
|
|
71
|
-
if (isStringLiteral(nameValue)) {
|
|
72
|
-
const actual = getStringLiteralValue(nameValue);
|
|
73
|
-
if (actual === declaredName) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
context.report({
|
|
77
|
-
node: nameValue,
|
|
78
|
-
messageId: 'mismatchedName',
|
|
79
|
-
data: { declaredName, actual },
|
|
80
|
-
fix(fixer) {
|
|
81
|
-
return fixer.replaceText(nameValue, `'${declaredName}'`);
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
} else {
|
|
85
|
-
context.report({
|
|
86
|
-
node: nameValue,
|
|
87
|
-
messageId: 'mismatchedName',
|
|
88
|
-
data: { declaredName, actual: sourceCode.getText(nameValue) },
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (isStringLiteral(firstArg)) {
|
|
95
|
-
const actual = getStringLiteralValue(firstArg);
|
|
96
|
-
if (actual === declaredName) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
context.report({
|
|
100
|
-
node: firstArg,
|
|
101
|
-
messageId: 'mismatchedName',
|
|
102
|
-
data: { declaredName, actual },
|
|
103
|
-
fix(fixer) {
|
|
104
|
-
return fixer.replaceText(firstArg, `'${declaredName}'`);
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
context.report({
|
|
111
|
-
node: firstArg,
|
|
112
|
-
messageId: 'missingName',
|
|
113
|
-
data: { declaredName },
|
|
114
|
-
fix(fixer) {
|
|
115
|
-
return fixer.insertTextBefore(firstArg, `'${declaredName}', `);
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
},
|
|
119
|
-
};
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
function getDeclaredName(callNode) {
|
|
124
|
-
const parent = callNode.parent;
|
|
125
|
-
if (!parent) return undefined;
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
parent.type === 'VariableDeclarator' &&
|
|
129
|
-
parent.init === callNode &&
|
|
130
|
-
parent.id.type === 'Identifier'
|
|
131
|
-
) {
|
|
132
|
-
return parent.id.name;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (
|
|
136
|
-
parent.type === 'PropertyDefinition' &&
|
|
137
|
-
parent.value === callNode &&
|
|
138
|
-
!parent.computed &&
|
|
139
|
-
parent.key.type === 'Identifier'
|
|
140
|
-
) {
|
|
141
|
-
return parent.key.name;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return undefined;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function isStringLiteral(node) {
|
|
148
|
-
if (node.type === 'Literal' && typeof node.value === 'string') {
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
if (
|
|
152
|
-
node.type === 'TemplateLiteral' &&
|
|
153
|
-
node.expressions.length === 0 &&
|
|
154
|
-
node.quasis.length === 1
|
|
155
|
-
) {
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function getStringLiteralValue(node) {
|
|
162
|
-
if (node.type === 'Literal') {
|
|
163
|
-
return node.value;
|
|
164
|
-
}
|
|
165
|
-
return node.quasis[0].value.cooked;
|
|
166
|
-
}
|
|
1
|
+
const { createNameMatchRule } = require('./craft-name-match-utils.cjs');
|
|
2
|
+
|
|
3
|
+
module.exports = createNameMatchRule({
|
|
4
|
+
calleeName: 'craftMethod',
|
|
5
|
+
description:
|
|
6
|
+
"Ensure craftMethod(name, ...) is called with a string literal first argument (or { name } object) that matches the declared variable or class property name.",
|
|
7
|
+
supportsObjectConfigForm: true,
|
|
8
|
+
});
|