@arcgis/eslint-config 5.1.0-next.99 → 5.2.0-next.1
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 +2 -2
- package/dist/config/applications.d.ts +2 -9
- package/dist/config/applications.js +2 -2
- package/dist/config/index.d.ts +3 -23
- package/dist/config/index.js +6 -4
- package/dist/{estree-BgIX506z.js → estree-CqRqIhAW.js} +1 -1
- package/dist/plugins/lumina/index.js +75 -31
- package/dist/plugins/lumina/rules/no-jsdoc-xref-links.d.ts +2 -0
- package/dist/plugins/webgis/index.js +3 -3
- package/dist/utils/defineBoundaries.d.ts +44 -0
- package/dist/utils/defineBoundaries.js +50 -0
- package/package.json +6 -5
- /package/dist/utils/{disable-rules.d.ts → disableRules.d.ts} +0 -0
- /package/dist/utils/{disable-rules.js → disableRules.js} +0 -0
package/README.md
CHANGED
|
@@ -8,5 +8,5 @@ It is not intended to be used directly, but rather used as a dependency by other
|
|
|
8
8
|
|
|
9
9
|
## License
|
|
10
10
|
|
|
11
|
-
This package is licensed under the terms described in the `LICENSE.md` file, located in the root of the package, and at https://js.arcgis.com/5.
|
|
12
|
-
For third party notices, see https://js.arcgis.com/5.
|
|
11
|
+
This package is licensed under the terms described in the `LICENSE.md` file, located in the root of the package, and at https://js.arcgis.com/5.1/LICENSE.txt.
|
|
12
|
+
For third party notices, see https://js.arcgis.com/5.1/third-party-notices.txt.
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* disables rules that are less important for applications compared to libraries.
|
|
4
|
-
*/
|
|
5
|
-
declare const _default: (import('eslint/config').Config | {
|
|
6
|
-
files: string[];
|
|
7
|
-
name?: string;
|
|
8
|
-
rules?: object;
|
|
9
|
-
})[];
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
declare const _default: TSESLint.FlatConfig.Config[];
|
|
10
3
|
export default _default;
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* Some advice on editing rules:
|
|
6
|
-
* - prioritize autofixable rules to make adoption in existing codebases easier
|
|
7
|
-
* - disable redundant rules (rules redundant with TypeScript, or each other),
|
|
8
|
-
* to reduce noise and performance impact
|
|
9
|
-
* - if rule is always auto-fixable, it may be a good idea to emit it as a
|
|
10
|
-
* warning instead of an error to be less disruptive when the developer is
|
|
11
|
-
* typing code
|
|
12
|
-
* - emit rules that have a lot of false positives as warnings instead of errors
|
|
13
|
-
* - provide justification for enabling opinionated rules
|
|
14
|
-
* - provide justification for disabling default rules
|
|
15
|
-
* - if rule is disabled because it's buggy, describe how so
|
|
16
|
-
* (code sample, GitHub issue, permalink to file, etc)
|
|
17
|
-
*/
|
|
18
|
-
declare const _default: (import('eslint/config').Config | {
|
|
19
|
-
files: string[];
|
|
20
|
-
name?: string;
|
|
21
|
-
rules?: object;
|
|
22
|
-
})[];
|
|
23
|
-
export default _default;
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
declare const config: TSESLint.FlatConfig.ConfigArray;
|
|
3
|
+
export default config;
|
package/dist/config/index.js
CHANGED
|
@@ -6,23 +6,25 @@ import { webgisPlugin } from "../plugins/webgis/index.js";
|
|
|
6
6
|
import { globalIgnores } from "eslint/config";
|
|
7
7
|
import markdown from "@eslint/markdown";
|
|
8
8
|
import packageJson from "eslint-plugin-package-json";
|
|
9
|
+
import { importX } from "eslint-plugin-import-x";
|
|
9
10
|
const packageJsonSortableCollections = packageJson.rules["sort-collections"].meta.defaultOptions[0].filter(
|
|
10
11
|
(collection) => !["scripts", "exports"].includes(collection)
|
|
11
12
|
) ?? [];
|
|
12
|
-
const
|
|
13
|
+
const config = [
|
|
13
14
|
globalIgnores(["**/www", "**/dist", "**/assets", "**/coverage", "**/.docs"]),
|
|
14
15
|
{
|
|
15
16
|
files: ["**/*.js", "**/*.mjs", "**/*.cjs"],
|
|
16
17
|
...eslint.configs.recommended
|
|
17
18
|
},
|
|
18
|
-
...[...tsEslint.configs.strictTypeChecked, ...tsEslint.configs.stylisticTypeChecked].map((
|
|
19
|
-
...
|
|
19
|
+
...[...tsEslint.configs.strictTypeChecked, ...tsEslint.configs.stylisticTypeChecked].map((config2) => ({
|
|
20
|
+
...config2,
|
|
20
21
|
files: ["**/*.ts", "**/*.tsx"]
|
|
21
22
|
})),
|
|
22
23
|
{
|
|
23
24
|
...webgisPlugin.configs.recommended,
|
|
24
25
|
files: ["**/*.ts", "**/*.tsx"]
|
|
25
26
|
},
|
|
27
|
+
importX.flatConfigs.typescript,
|
|
26
28
|
{
|
|
27
29
|
files: ["**/*.ts", "**/*.tsx"],
|
|
28
30
|
linterOptions: {
|
|
@@ -653,5 +655,5 @@ const defaultConfig = [
|
|
|
653
655
|
}
|
|
654
656
|
];
|
|
655
657
|
export {
|
|
656
|
-
|
|
658
|
+
config as default
|
|
657
659
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as makeEslintPlugin, l as luminaJsxExportName, a as luminaEntrypointName, b as luminaTestEntrypointName, s as sourceCodeDeclaresComponent, p as parsePropertyDecorator, c as getProperty, i as isGetterWithoutSetter, e as extractDeclareElementsInterface, d as isCreateEvent, h as hasDecorator, f as getName, j as checkForLuminaJsx, k as isBindThisCallee, g as getComponentDeclaration, u as unwrapExpression } from "../../estree-
|
|
1
|
+
import { m as makeEslintPlugin, l as luminaJsxExportName, a as luminaEntrypointName, b as luminaTestEntrypointName, s as sourceCodeDeclaresComponent, p as parsePropertyDecorator, c as getProperty, i as isGetterWithoutSetter, e as extractDeclareElementsInterface, d as isCreateEvent, h as hasDecorator, f as getName, j as checkForLuminaJsx, k as isBindThisCallee, g as getComponentDeclaration, u as unwrapExpression } from "../../estree-CqRqIhAW.js";
|
|
2
2
|
import { AST_NODE_TYPES, ESLintUtils, AST_TOKEN_TYPES } from "@typescript-eslint/utils";
|
|
3
3
|
import ts from "typescript";
|
|
4
4
|
import { camelToKebab } from "@arcgis/toolkit/string";
|
|
@@ -7,16 +7,16 @@ const plugin = makeEslintPlugin(
|
|
|
7
7
|
(rule) => `https://devtopia.esri.com/WebGIS/arcgis-web-components/tree/main/packages/support-packages/eslint-config/src/plugins/lumina/rules/${rule}.ts`
|
|
8
8
|
);
|
|
9
9
|
const importDeclaration = `import { ${luminaJsxExportName} } from "${luminaEntrypointName}";`;
|
|
10
|
-
const description$
|
|
10
|
+
const description$m = `To use Lumina's JSX, you need to ${importDeclaration}`;
|
|
11
11
|
plugin.createRule({
|
|
12
12
|
name: "add-missing-jsx-import",
|
|
13
13
|
meta: {
|
|
14
14
|
docs: {
|
|
15
|
-
description: description$
|
|
15
|
+
description: description$m,
|
|
16
16
|
defaultLevel: "error"
|
|
17
17
|
},
|
|
18
18
|
messages: {
|
|
19
|
-
addMissingJsxImport: description$
|
|
19
|
+
addMissingJsxImport: description$m
|
|
20
20
|
},
|
|
21
21
|
type: "problem",
|
|
22
22
|
schema: [],
|
|
@@ -73,12 +73,12 @@ plugin.createRule({
|
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
-
const description$
|
|
76
|
+
const description$l = "Auto add { type: Boolean } or { type: Number } where necessary";
|
|
77
77
|
plugin.createRule({
|
|
78
78
|
name: "auto-add-type",
|
|
79
79
|
meta: {
|
|
80
80
|
docs: {
|
|
81
|
-
description: description$
|
|
81
|
+
description: description$l,
|
|
82
82
|
defaultLevel: "warn"
|
|
83
83
|
},
|
|
84
84
|
messages: {
|
|
@@ -115,7 +115,7 @@ More information: https://devtopia.esri.com/WebGIS/arcgis-web-components/issues/
|
|
|
115
115
|
const typeProperty = getProperty(properties, "type");
|
|
116
116
|
const converterProperty = getProperty(properties, "converter");
|
|
117
117
|
const isTrivialType = trivialType === "Number" || trivialType === "Boolean";
|
|
118
|
-
if (isTrivialType && typeProperty
|
|
118
|
+
if (isTrivialType && typeProperty?.type === AST_NODE_TYPES.Identifier && (typeProperty.name === "Number" || typeProperty.name === "Boolean")) {
|
|
119
119
|
context.report({
|
|
120
120
|
node: typeProperty,
|
|
121
121
|
messageId: "noUnnecessaryType",
|
|
@@ -312,12 +312,12 @@ plugin.createRule({
|
|
|
312
312
|
};
|
|
313
313
|
}
|
|
314
314
|
});
|
|
315
|
-
const description$
|
|
315
|
+
const description$k = `Lumina component must be declared in a TSX file with a matching folder name located inside of src/components folder.`;
|
|
316
316
|
plugin.createRule({
|
|
317
317
|
name: "component-placement-rules",
|
|
318
318
|
meta: {
|
|
319
319
|
docs: {
|
|
320
|
-
description: description$
|
|
320
|
+
description: description$k,
|
|
321
321
|
defaultLevel: "error"
|
|
322
322
|
},
|
|
323
323
|
messages: {
|
|
@@ -356,7 +356,7 @@ plugin.createRule({
|
|
|
356
356
|
};
|
|
357
357
|
}
|
|
358
358
|
});
|
|
359
|
-
const description$
|
|
359
|
+
const description$j = `Enforce consistent event naming.`;
|
|
360
360
|
const defaultOptions$1 = [
|
|
361
361
|
{
|
|
362
362
|
eventNamespaces: ["arcgis"],
|
|
@@ -367,7 +367,7 @@ plugin.createRule({
|
|
|
367
367
|
name: "consistent-event-naming",
|
|
368
368
|
meta: {
|
|
369
369
|
docs: {
|
|
370
|
-
description: description$
|
|
370
|
+
description: description$j,
|
|
371
371
|
defaultLevel: "warn"
|
|
372
372
|
},
|
|
373
373
|
messages: {
|
|
@@ -468,12 +468,12 @@ Discussion: https://devtopia.esri.com/WebGIS/arcgis-web-components/discussions/3
|
|
|
468
468
|
}
|
|
469
469
|
});
|
|
470
470
|
const capitalAfterLower = /(?<=[a-z\d])[A-Z]/u;
|
|
471
|
-
const description$
|
|
471
|
+
const description$i = `Enforce consistent usage of ? for marking property as nullable, rather than |null, |undefined or |Nil.`;
|
|
472
472
|
plugin.createRule({
|
|
473
473
|
name: "consistent-nullability",
|
|
474
474
|
meta: {
|
|
475
475
|
docs: {
|
|
476
|
-
description: description$
|
|
476
|
+
description: description$i,
|
|
477
477
|
// TODO: enable this by default
|
|
478
478
|
defaultLevel: "off"
|
|
479
479
|
},
|
|
@@ -549,18 +549,18 @@ plugin.createRule({
|
|
|
549
549
|
};
|
|
550
550
|
}
|
|
551
551
|
});
|
|
552
|
-
const description$
|
|
552
|
+
const description$h = `Enforce that @property(), @method() and createEvent() members are used in the correct context.`;
|
|
553
553
|
plugin.createRule({
|
|
554
554
|
name: "decorators-context",
|
|
555
555
|
meta: {
|
|
556
556
|
docs: {
|
|
557
|
-
description: description$
|
|
557
|
+
description: description$h,
|
|
558
558
|
defaultLevel: "error"
|
|
559
559
|
},
|
|
560
560
|
messages: {
|
|
561
561
|
publicApiMustBePublic: `@property(), @method() and createEvent() members must not have private or protected modifier.
|
|
562
562
|
|
|
563
|
-
If you wish to hide this member from public documentation, use @private or @
|
|
563
|
+
If you wish to hide this member from public documentation, use @private or @internal JSDoc tags instead. Documentation: https://webgis.esri.com/references/api-extractor/tags-reference`,
|
|
564
564
|
noPropertyDecoratorOnMethods: `Methods must not have @property() nor @state() decorator. Did you mean @property() instead?`,
|
|
565
565
|
noCombinedPropertyEvent: `Property may either be an event (initialized with createEvent()) or a property (has @property() decorator), but not both`,
|
|
566
566
|
noCombinedPropertyState: `Property may either be a state (initialized with @state()) or a property (has @property() decorator), but not both`,
|
|
@@ -651,7 +651,7 @@ function isLuminaJsxType(type) {
|
|
|
651
651
|
}
|
|
652
652
|
const hasTypeFlag = (type, flag) => type.flags & flag ? true : (type.flags & ts.TypeFlags.Union) !== 0 && type.types.some((t) => hasTypeFlag(t, flag));
|
|
653
653
|
const literalTypeFlag = ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BooleanLike;
|
|
654
|
-
const description$
|
|
654
|
+
const description$g = `Need to add explicit type annotation: {{ setterType }}
|
|
655
655
|
|
|
656
656
|
Explanation:
|
|
657
657
|
Lumina automatically creates an attribute for a property if property type includes a literal type (string|number|boolean).
|
|
@@ -662,11 +662,11 @@ plugin.createRule({
|
|
|
662
662
|
name: "explicit-setter-type",
|
|
663
663
|
meta: {
|
|
664
664
|
docs: {
|
|
665
|
-
description: description$
|
|
665
|
+
description: description$g,
|
|
666
666
|
defaultLevel: "error"
|
|
667
667
|
},
|
|
668
668
|
messages: {
|
|
669
|
-
explicitSetterType: description$
|
|
669
|
+
explicitSetterType: description$g,
|
|
670
670
|
addExplicitSetterType: `Add {{ setterType }} type annotation`
|
|
671
671
|
},
|
|
672
672
|
type: "problem",
|
|
@@ -1212,16 +1212,16 @@ function isCreateElementComponent(node) {
|
|
|
1212
1212
|
}
|
|
1213
1213
|
return false;
|
|
1214
1214
|
}
|
|
1215
|
-
const description$
|
|
1215
|
+
const description$f = `Use @internal or @private JSDoc tag over @ignore. See https://webgis.esri.com/references/api-extractor/tags-reference`;
|
|
1216
1216
|
plugin.createRule({
|
|
1217
1217
|
name: "no-ignore-jsdoc-tag",
|
|
1218
1218
|
meta: {
|
|
1219
1219
|
docs: {
|
|
1220
|
-
description: description$
|
|
1220
|
+
description: description$f,
|
|
1221
1221
|
defaultLevel: "error"
|
|
1222
1222
|
},
|
|
1223
1223
|
messages: {
|
|
1224
|
-
noIgnoreJsDocTag: description$
|
|
1224
|
+
noIgnoreJsDocTag: description$f
|
|
1225
1225
|
},
|
|
1226
1226
|
type: "problem",
|
|
1227
1227
|
schema: []
|
|
@@ -1250,12 +1250,12 @@ plugin.createRule({
|
|
|
1250
1250
|
}
|
|
1251
1251
|
});
|
|
1252
1252
|
const reIgnore = /\* @ignore/gu;
|
|
1253
|
-
const description$
|
|
1253
|
+
const description$e = `Detect incorrect usage of dynamic JSX tag name`;
|
|
1254
1254
|
plugin.createRule({
|
|
1255
1255
|
name: "no-incorrect-dynamic-tag-name",
|
|
1256
1256
|
meta: {
|
|
1257
1257
|
docs: {
|
|
1258
|
-
description: description$
|
|
1258
|
+
description: description$e,
|
|
1259
1259
|
defaultLevel: "error"
|
|
1260
1260
|
},
|
|
1261
1261
|
messages: {
|
|
@@ -1298,18 +1298,18 @@ plugin.createRule({
|
|
|
1298
1298
|
};
|
|
1299
1299
|
}
|
|
1300
1300
|
});
|
|
1301
|
-
const description$
|
|
1301
|
+
const description$d = `If inline arrow function is passed to ref, it will be called again on each render.
|
|
1302
1302
|
|
|
1303
1303
|
If this is not desirable, see alternatives: https://webgis.esri.com/references/lumina/jsx#refs`;
|
|
1304
1304
|
plugin.createRule({
|
|
1305
1305
|
name: "no-inline-arrow-in-ref",
|
|
1306
1306
|
meta: {
|
|
1307
1307
|
docs: {
|
|
1308
|
-
description: description$
|
|
1308
|
+
description: description$d,
|
|
1309
1309
|
defaultLevel: "warn"
|
|
1310
1310
|
},
|
|
1311
1311
|
messages: {
|
|
1312
|
-
errorInlineArrow: description$
|
|
1312
|
+
errorInlineArrow: description$d
|
|
1313
1313
|
},
|
|
1314
1314
|
type: "problem",
|
|
1315
1315
|
schema: []
|
|
@@ -1335,16 +1335,16 @@ plugin.createRule({
|
|
|
1335
1335
|
};
|
|
1336
1336
|
}
|
|
1337
1337
|
});
|
|
1338
|
-
const description$
|
|
1338
|
+
const description$c = `Put @internal and @private on their own JSDoc line, not inline.`;
|
|
1339
1339
|
plugin.createRule({
|
|
1340
1340
|
name: "no-inline-exposure-jsdoc-tag",
|
|
1341
1341
|
meta: {
|
|
1342
1342
|
docs: {
|
|
1343
|
-
description: description$
|
|
1343
|
+
description: description$c,
|
|
1344
1344
|
defaultLevel: "error"
|
|
1345
1345
|
},
|
|
1346
1346
|
messages: {
|
|
1347
|
-
inlineExposure: description$
|
|
1347
|
+
inlineExposure: description$c
|
|
1348
1348
|
},
|
|
1349
1349
|
type: "problem",
|
|
1350
1350
|
schema: []
|
|
@@ -1379,6 +1379,50 @@ plugin.createRule({
|
|
|
1379
1379
|
};
|
|
1380
1380
|
}
|
|
1381
1381
|
});
|
|
1382
|
+
const absoluteDocsBaseUrl = "https://next.gha.afd.arcgis.com/";
|
|
1383
|
+
const description$b = `xref:// URLs are not supported in JSDoc. Use absolute links to ${absoluteDocsBaseUrl} instead.`;
|
|
1384
|
+
plugin.createRule({
|
|
1385
|
+
name: "no-jsdoc-xref-links",
|
|
1386
|
+
meta: {
|
|
1387
|
+
docs: {
|
|
1388
|
+
description: description$b,
|
|
1389
|
+
defaultLevel: "error"
|
|
1390
|
+
},
|
|
1391
|
+
messages: {
|
|
1392
|
+
noJsDocXrefLinks: description$b
|
|
1393
|
+
},
|
|
1394
|
+
type: "problem",
|
|
1395
|
+
schema: []
|
|
1396
|
+
},
|
|
1397
|
+
defaultOptions: [],
|
|
1398
|
+
create(context) {
|
|
1399
|
+
return {
|
|
1400
|
+
"Program:exit"() {
|
|
1401
|
+
const source = context.sourceCode.text;
|
|
1402
|
+
if (!source.includes("xref://")) {
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
for (const comment of context.sourceCode.getAllComments()) {
|
|
1406
|
+
const commentText = source.slice(comment.range[0], comment.range[1]);
|
|
1407
|
+
if (!commentText.startsWith("/**") || !commentText.includes("xref://")) {
|
|
1408
|
+
continue;
|
|
1409
|
+
}
|
|
1410
|
+
for (const match of commentText.matchAll(reXrefUrl)) {
|
|
1411
|
+
const idx = comment.range[0] + (match.index ?? 0);
|
|
1412
|
+
context.report({
|
|
1413
|
+
messageId: "noJsDocXrefLinks",
|
|
1414
|
+
loc: {
|
|
1415
|
+
start: context.sourceCode.getLocFromIndex(idx),
|
|
1416
|
+
end: context.sourceCode.getLocFromIndex(idx + match[0].length)
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
});
|
|
1425
|
+
const reXrefUrl = /xref:\/\/[\w./#-]+/gu;
|
|
1382
1426
|
const description$a = `directives={} prop value must be an array literal. Documentation: https://webgis.esri.com/references/lumina/jsx#lit-directives`;
|
|
1383
1427
|
plugin.createRule({
|
|
1384
1428
|
name: "no-invalid-directives-prop",
|
|
@@ -1740,7 +1784,7 @@ plugin.createRule({
|
|
|
1740
1784
|
return;
|
|
1741
1785
|
}
|
|
1742
1786
|
const argument = functionParent.params.at(0);
|
|
1743
|
-
if (argument
|
|
1787
|
+
if (argument?.type !== AST_NODE_TYPES.Identifier || argument.name !== eventVariableName) {
|
|
1744
1788
|
return;
|
|
1745
1789
|
}
|
|
1746
1790
|
const reportPossiblyUnnecessaryTypeAssertion = () => context.report({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as makeEslintPlugin, e as extractDeclareElementsInterface, g as getComponentDeclaration } from "../../estree-
|
|
1
|
+
import { m as makeEslintPlugin, e as extractDeclareElementsInterface, g as getComponentDeclaration } from "../../estree-CqRqIhAW.js";
|
|
2
2
|
import { resolve } from "path/posix";
|
|
3
3
|
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
4
4
|
const plugin = makeEslintPlugin(
|
|
@@ -29,7 +29,7 @@ plugin.createRule({
|
|
|
29
29
|
return {};
|
|
30
30
|
}
|
|
31
31
|
const basePath = fileName.slice(0, srcIndex + "/src/".length);
|
|
32
|
-
if (isTestFile(fileName)) {
|
|
32
|
+
if (isTestFile(fileName) || isStorybookFile(fileName)) {
|
|
33
33
|
return {};
|
|
34
34
|
}
|
|
35
35
|
return {
|
|
@@ -217,7 +217,7 @@ plugin.createRule({
|
|
|
217
217
|
};
|
|
218
218
|
}
|
|
219
219
|
});
|
|
220
|
-
const description$1 = `Do not use links like [](#something) as they are not portable across .d.ts, and are not validated at build time. Use {@link } syntax, or absolute links. See https://webgis.esri.com/
|
|
220
|
+
const description$1 = `Do not use links like [](#something) as they are not portable across .d.ts, and are not validated at build time. Use {@link } syntax, or absolute links. See https://webgis.esri.com/references/api-extractor/tags-reference#link)`;
|
|
221
221
|
plugin.createRule({
|
|
222
222
|
name: "no-unsafe-hash-links",
|
|
223
223
|
meta: {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
/**
|
|
3
|
+
* Restrict which parts of the package can import what packages.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface Boundaries<BoundaryNames extends string, DependencyNames extends string> {
|
|
8
|
+
/**
|
|
9
|
+
* List all dependencies that may be imported in src/.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
dependencyNames: readonly DependencyNames[];
|
|
14
|
+
/**
|
|
15
|
+
* Define the boundaries within the package and their allowed dependencies.
|
|
16
|
+
* Boundary name must start with `./` and be a path relative to the src/ folder.
|
|
17
|
+
* For example, `./components`
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
boundaries: Record<BoundaryNames, Boundary<BoundaryNames, DependencyNames>>;
|
|
22
|
+
}
|
|
23
|
+
/** @public */
|
|
24
|
+
export type Boundary<BoundaryNames extends string, DependencyNames extends string> = {
|
|
25
|
+
/**
|
|
26
|
+
* Dependencies this boundary may import.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
allowedDependencies: readonly DependencyNames[];
|
|
31
|
+
/**
|
|
32
|
+
* Boundaries this boundary may import.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
allowedBoundaries: readonly BoundaryNames[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* @param boundaries
|
|
40
|
+
* @param monorepoRoot
|
|
41
|
+
* @param basePath example: "packages/ai-packages/ai-components/src"
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export declare function boundariesToEslintRules(boundaries: Boundaries<string, string>, monorepoRoot: string, basePath: string, message: string): TSESLint.FlatConfig.Config[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function boundariesToEslintRules(boundaries, monorepoRoot, basePath, message) {
|
|
2
|
+
const boundaryNames = Object.keys(boundaries.boundaries);
|
|
3
|
+
const boundaryEntries = Object.entries(boundaries.boundaries);
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
6
|
+
files: [`${basePath}/**/*.+(ts|tsx)`],
|
|
7
|
+
rules: {
|
|
8
|
+
"import-x/no-restricted-paths": [
|
|
9
|
+
"error",
|
|
10
|
+
{
|
|
11
|
+
basePath: `${monorepoRoot}${basePath}`,
|
|
12
|
+
zones: boundaryEntries.flatMap(
|
|
13
|
+
([boundaryName, boundary]) => boundaryNames.filter((name) => name !== boundaryName && !boundary.allowedBoundaries.includes(name)).map((targetBoundary) => ({
|
|
14
|
+
from: targetBoundary,
|
|
15
|
+
target: boundaryName,
|
|
16
|
+
message
|
|
17
|
+
}))
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
...boundaryEntries.flatMap(([boundaryName, boundary]) => {
|
|
24
|
+
const blockedDependencies = boundaries.dependencyNames.filter(
|
|
25
|
+
(dependency) => !boundary.allowedDependencies.includes(dependency)
|
|
26
|
+
);
|
|
27
|
+
return blockedDependencies.length === 0 ? [] : [
|
|
28
|
+
{
|
|
29
|
+
files: [`${basePath}/${boundaryName.slice(2)}/**/*.+(ts|tsx)`],
|
|
30
|
+
rules: {
|
|
31
|
+
"@typescript-eslint/no-restricted-imports": [
|
|
32
|
+
"error",
|
|
33
|
+
{
|
|
34
|
+
patterns: [
|
|
35
|
+
{
|
|
36
|
+
group: blockedDependencies.map((dependency) => `/${dependency}`),
|
|
37
|
+
message
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
})
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
boundariesToEslintRules
|
|
50
|
+
};
|
package/package.json
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcgis/eslint-config",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0-next.1",
|
|
4
4
|
"description": "ESLint configuration for WebGIS SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dist/config/index.js",
|
|
8
|
-
"./ts": "./src/config/index.ts",
|
|
9
8
|
"./application": "./dist/config/applications.js",
|
|
10
9
|
"./extra": "./dist/config/extra.js",
|
|
11
10
|
"./lumina": "./dist/config/lumina.js",
|
|
12
|
-
"./lumina/ts": "./src/config/lumina.ts",
|
|
13
11
|
"./plugins/webgis": "./dist/plugins/webgis/index.js",
|
|
14
12
|
"./plugins/lumina": "./dist/plugins/lumina/index.js",
|
|
15
|
-
"./utils/
|
|
13
|
+
"./utils/defineBoundaries": "./dist/utils/defineBoundaries.js",
|
|
14
|
+
"./utils/disableRules": "./dist/utils/disableRules.js",
|
|
16
15
|
"./package.json": "./package.json"
|
|
17
16
|
},
|
|
18
17
|
"files": [
|
|
@@ -25,6 +24,8 @@
|
|
|
25
24
|
"@types/confusing-browser-globals": "^1.0.3",
|
|
26
25
|
"@typescript-eslint/utils": "^8.58.0",
|
|
27
26
|
"confusing-browser-globals": "^1.0.11",
|
|
27
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
28
|
+
"eslint-plugin-import-x": "^4.16.2",
|
|
28
29
|
"eslint-plugin-package-json": "~0.91.1",
|
|
29
30
|
"eslint-plugin-storybook": "^10.3.4",
|
|
30
31
|
"globals": "^16.5.0",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"tslib": "^2.8.1",
|
|
33
34
|
"typescript": "~6.0.2",
|
|
34
35
|
"typescript-eslint": "^8.58.0",
|
|
35
|
-
"@arcgis/toolkit": "5.
|
|
36
|
+
"@arcgis/toolkit": "5.2.0-next.1"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"eslint": "^10.2.0"
|
|
File without changes
|
|
File without changes
|