@servicetitan/eslint-plugin 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/processors/stub.d.ts +3 -0
- package/dist/processors/stub.d.ts.map +1 -0
- package/dist/processors/stub.js +8 -0
- package/dist/processors/stub.js.map +1 -0
- package/dist/rules/decorators-declare.d.ts +3 -0
- package/dist/rules/decorators-declare.d.ts.map +1 -0
- package/dist/rules/decorators-declare.js +44 -0
- package/dist/rules/decorators-declare.js.map +1 -0
- package/dist/rules/mobx/no-abstract-decorators.d.ts +3 -0
- package/dist/rules/mobx/no-abstract-decorators.d.ts.map +1 -0
- package/dist/rules/mobx/no-abstract-decorators.js +43 -0
- package/dist/rules/mobx/no-abstract-decorators.js.map +1 -0
- package/dist/rules/mobx/use-makeObservable-with-decorators.d.ts +3 -0
- package/dist/rules/mobx/use-makeObservable-with-decorators.d.ts.map +1 -0
- package/dist/rules/mobx/use-makeObservable-with-decorators.js +63 -0
- package/dist/rules/mobx/use-makeObservable-with-decorators.js.map +1 -0
- package/dist/rules/react/destructure-default-import.d.ts +3 -0
- package/dist/rules/react/destructure-default-import.d.ts.map +1 -0
- package/dist/rules/react/destructure-default-import.js +40 -0
- package/dist/rules/react/destructure-default-import.js.map +1 -0
- package/dist/rules/react/no-qualified-type.d.ts +3 -0
- package/dist/rules/react/no-qualified-type.d.ts.map +1 -0
- package/dist/rules/react/no-qualified-type.js +33 -0
- package/dist/rules/react/no-qualified-type.js.map +1 -0
- package/package.json +30 -0
- package/src/index.ts +16 -0
- package/src/processors/stub.ts +6 -0
- package/src/rules/decorators-declare.ts +43 -0
- package/src/rules/mobx/no-abstract-decorators.ts +43 -0
- package/src/rules/mobx/use-makeObservable-with-decorators.ts +68 -0
- package/src/rules/react/destructure-default-import.ts +41 -0
- package/src/rules/react/no-qualified-type.ts +31 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const rules: {
|
|
2
|
+
'use-declare-with-decorators': import("eslint").Rule.RuleModule;
|
|
3
|
+
'mobx/use-makeObservable-with-decorators': import("eslint").Rule.RuleModule;
|
|
4
|
+
'mobx/no-abstract-decorators': import("eslint").Rule.RuleModule;
|
|
5
|
+
'react/destructure-default-import': import("eslint").Rule.RuleModule;
|
|
6
|
+
'react/no-qualified-type': import("eslint").Rule.RuleModule;
|
|
7
|
+
};
|
|
8
|
+
export declare const processors: {
|
|
9
|
+
stub: import("eslint").Linter.LintOptions;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,KAAK;;;;;;CAMjB,CAAC;AAEF,eAAO,MAAM,UAAU;;CAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processors = exports.rules = void 0;
|
|
4
|
+
const decorators_declare_1 = require("./rules/decorators-declare");
|
|
5
|
+
const use_makeObservable_with_decorators_1 = require("./rules/mobx/use-makeObservable-with-decorators");
|
|
6
|
+
const no_abstract_decorators_1 = require("./rules/mobx/no-abstract-decorators");
|
|
7
|
+
const destructure_default_import_1 = require("./rules/react/destructure-default-import");
|
|
8
|
+
const no_qualified_type_1 = require("./rules/react/no-qualified-type");
|
|
9
|
+
const stub_1 = require("./processors/stub");
|
|
10
|
+
exports.rules = {
|
|
11
|
+
'use-declare-with-decorators': decorators_declare_1.useDeclareWithDecorators,
|
|
12
|
+
'mobx/use-makeObservable-with-decorators': use_makeObservable_with_decorators_1.mobxUseMakeObservableWithDecorators,
|
|
13
|
+
'mobx/no-abstract-decorators': no_abstract_decorators_1.mobxNoAbstractDecorators,
|
|
14
|
+
'react/destructure-default-import': destructure_default_import_1.reactDestructureDefaultImport,
|
|
15
|
+
'react/no-qualified-type': no_qualified_type_1.reactNoQualifiedType,
|
|
16
|
+
};
|
|
17
|
+
exports.processors = { stub: stub_1.stub };
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mEAAsE;AACtE,wGAAsG;AACtG,gFAA+E;AAC/E,yFAAyF;AACzF,uEAAuE;AACvE,4CAAyC;AAE5B,QAAA,KAAK,GAAG;IACjB,6BAA6B,EAAE,6CAAwB;IACvD,yCAAyC,EAAE,wEAAmC;IAC9E,6BAA6B,EAAE,iDAAwB;IACvD,kCAAkC,EAAE,0DAA6B;IACjE,yBAAyB,EAAE,wCAAoB;CAClD,CAAC;AAEW,QAAA,UAAU,GAAG,EAAE,IAAI,EAAJ,WAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../../src/processors/stub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,WAGzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../src/processors/stub.ts"],"names":[],"mappings":";;;AAEa,QAAA,IAAI,GAAuB;IACpC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IACtB,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ;CACxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators-declare.d.ts","sourceRoot":"","sources":["../../src/rules/decorators-declare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAI9B,eAAO,MAAM,wBAAwB,EAAE,IAAI,CAAC,UAsC3C,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useDeclareWithDecorators = void 0;
|
|
4
|
+
const customDecorators = ['injectDependency', 'koObservableToMobx'];
|
|
5
|
+
exports.useDeclareWithDecorators = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Disallow custom @servicetitan class field decorators without declare',
|
|
10
|
+
category: 'Possible Errors',
|
|
11
|
+
recommended: false,
|
|
12
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
decoratorsDeclare: "Use declare when decorating with '@{{name}}'",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
create(context) {
|
|
19
|
+
return {
|
|
20
|
+
ClassProperty(node) {
|
|
21
|
+
var _a;
|
|
22
|
+
if (node.declare) {
|
|
23
|
+
return; // field is already defined with declare
|
|
24
|
+
}
|
|
25
|
+
if ((_a = node === null || node === void 0 ? void 0 : node.decorators) === null || _a === void 0 ? void 0 : _a.length) {
|
|
26
|
+
node.decorators.forEach((decorator) => {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
const name = (_b = (_a = decorator.expression) === null || _a === void 0 ? void 0 : _a.callee) === null || _b === void 0 ? void 0 : _b.name;
|
|
29
|
+
if (name && customDecorators.includes(name)) {
|
|
30
|
+
context.report({
|
|
31
|
+
node,
|
|
32
|
+
messageId: 'decoratorsDeclare',
|
|
33
|
+
data: {
|
|
34
|
+
name,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=decorators-declare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators-declare.js","sourceRoot":"","sources":["../../src/rules/decorators-declare.ts"],"names":[],"mappings":";;;AAEA,MAAM,gBAAgB,GAAG,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC;AAEvD,QAAA,wBAAwB,GAAoB;IACrD,IAAI,EAAE;QACF,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACF,WAAW,EAAE,sEAAsE;YACnF,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,2CAA2C;SACnD;QACD,QAAQ,EAAE;YACN,iBAAiB,EAAE,8CAA8C;SACpE;KACJ;IACD,MAAM,CAAC,OAAO;QACV,OAAO;YACH,aAAa,CAAC,IAAS;;gBACnB,IAAI,IAAI,CAAC,OAAO,EAAE;oBACd,OAAO,CAAC,wCAAwC;iBACnD;gBAED,IAAI,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,UAAU,0CAAE,MAAM,EAAE;oBAC1B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAc,EAAE,EAAE;;wBACvC,MAAM,IAAI,GAAG,MAAA,MAAA,SAAS,CAAC,UAAU,0CAAE,MAAM,0CAAE,IAAI,CAAC;wBAEhD,IAAI,IAAI,IAAI,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;4BACzC,OAAO,CAAC,MAAM,CAAC;gCACX,IAAI;gCACJ,SAAS,EAAE,mBAAmB;gCAC9B,IAAI,EAAE;oCACF,IAAI;iCACP;6BACJ,CAAC,CAAC;yBACN;oBACL,CAAC,CAAC,CAAC;iBACN;YACL,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-abstract-decorators.d.ts","sourceRoot":"","sources":["../../../src/rules/mobx/no-abstract-decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAI9B,eAAO,MAAM,wBAAwB,EAAE,IAAI,CAAC,UAsC3C,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mobxNoAbstractDecorators = void 0;
|
|
4
|
+
const mobxDecorators = ['observable', 'action', 'computed', 'override'];
|
|
5
|
+
exports.mobxNoAbstractDecorators = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Disallow MobX decorators on abstract class fields',
|
|
10
|
+
category: 'Possible Errors',
|
|
11
|
+
recommended: false,
|
|
12
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
noAbstractMobxDecorators: "Don't decorate abstract class fields or methods with '@{{name}}'",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
create(context) {
|
|
19
|
+
function checkFn(node) {
|
|
20
|
+
var _a;
|
|
21
|
+
if ((_a = node === null || node === void 0 ? void 0 : node.decorators) === null || _a === void 0 ? void 0 : _a.length) {
|
|
22
|
+
node.decorators.forEach((decorator) => {
|
|
23
|
+
var _a, _b, _c;
|
|
24
|
+
const name = ((_a = decorator === null || decorator === void 0 ? void 0 : decorator.expression) === null || _a === void 0 ? void 0 : _a.name) || ((_c = (_b = decorator === null || decorator === void 0 ? void 0 : decorator.expression) === null || _b === void 0 ? void 0 : _b.object) === null || _c === void 0 ? void 0 : _c.name);
|
|
25
|
+
if (name && mobxDecorators.includes(name)) {
|
|
26
|
+
context.report({
|
|
27
|
+
node,
|
|
28
|
+
messageId: 'noAbstractMobxDecorators',
|
|
29
|
+
data: {
|
|
30
|
+
name,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
TSAbstractClassProperty: checkFn,
|
|
39
|
+
TSAbstractMethodDefinition: checkFn,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=no-abstract-decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-abstract-decorators.js","sourceRoot":"","sources":["../../../src/rules/mobx/no-abstract-decorators.ts"],"names":[],"mappings":";;;AAEA,MAAM,cAAc,GAAG,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAE3D,QAAA,wBAAwB,GAAoB;IACrD,IAAI,EAAE;QACF,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACF,WAAW,EAAE,mDAAmD;YAChE,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,2CAA2C;SACnD;QACD,QAAQ,EAAE;YACN,wBAAwB,EACpB,kEAAkE;SACzE;KACJ;IACD,MAAM,CAAC,OAAY;QACf,SAAS,OAAO,CAAC,IAAS;;YACtB,IAAI,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,UAAU,0CAAE,MAAM,EAAE;gBAC1B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAc,EAAE,EAAE;;oBACvC,MAAM,IAAI,GAAG,CAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,UAAU,0CAAE,IAAI,MAAI,MAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,UAAU,0CAAE,MAAM,0CAAE,IAAI,CAAA,CAAC;oBAEhF,IAAI,IAAI,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;wBACvC,OAAO,CAAC,MAAM,CAAC;4BACX,IAAI;4BACJ,SAAS,EAAE,0BAA0B;4BACrC,IAAI,EAAE;gCACF,IAAI;6BACP;yBACJ,CAAC,CAAC;qBACN;gBACL,CAAC,CAAC,CAAC;aACN;QACL,CAAC;QAED,OAAO;YACH,uBAAuB,EAAE,OAAO;YAChC,0BAA0B,EAAE,OAAO;SACtC,CAAC;IACN,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-makeObservable-with-decorators.d.ts","sourceRoot":"","sources":["../../../src/rules/mobx/use-makeObservable-with-decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAK9B,eAAO,MAAM,mCAAmC,EAAE,IAAI,CAAC,UA8DtD,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mobxUseMakeObservableWithDecorators = void 0;
|
|
4
|
+
// NOTE: "action" also covers "action.bound"
|
|
5
|
+
const mobxDecorators = ['observable', 'action', 'computed', 'override'];
|
|
6
|
+
exports.mobxUseMakeObservableWithDecorators = {
|
|
7
|
+
meta: {
|
|
8
|
+
type: 'problem',
|
|
9
|
+
docs: {
|
|
10
|
+
description: 'Testing makeObservable used with decorators',
|
|
11
|
+
category: 'Possible Errors',
|
|
12
|
+
recommended: false,
|
|
13
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
makeObservable: 'Use makeObservable in the constructor with MobX decorators',
|
|
17
|
+
constructor: 'Add constructor with makeObservable when using MobX decorators',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
ClassDeclaration(node) {
|
|
23
|
+
let hasMobxDecorator = false;
|
|
24
|
+
let hasConstructor = false;
|
|
25
|
+
let hasMakeObservable = false;
|
|
26
|
+
node.body.body.forEach((methodOrProperty) => {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
if (methodOrProperty.decorators) {
|
|
29
|
+
methodOrProperty.decorators.forEach((decorator) => {
|
|
30
|
+
var _a, _b, _c;
|
|
31
|
+
if (mobxDecorators.includes(((_a = decorator === null || decorator === void 0 ? void 0 : decorator.expression) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
32
|
+
((_c = (_b = decorator === null || decorator === void 0 ? void 0 : decorator.expression) === null || _b === void 0 ? void 0 : _b.object) === null || _c === void 0 ? void 0 : _c.name))) {
|
|
33
|
+
hasMobxDecorator = true;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (methodOrProperty.kind === 'constructor') {
|
|
38
|
+
hasConstructor = true;
|
|
39
|
+
(_b = (_a = methodOrProperty.value) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.body.forEach((statement) => {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
if (((_b = (_a = statement === null || statement === void 0 ? void 0 : statement.expression) === null || _a === void 0 ? void 0 : _a.callee) === null || _b === void 0 ? void 0 : _b.name) === 'makeObservable') {
|
|
42
|
+
hasMakeObservable = true;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
if (hasMobxDecorator && !hasMakeObservable && hasConstructor) {
|
|
48
|
+
context.report({
|
|
49
|
+
node,
|
|
50
|
+
messageId: 'makeObservable',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (hasMobxDecorator && !hasMakeObservable && !hasConstructor) {
|
|
54
|
+
context.report({
|
|
55
|
+
node,
|
|
56
|
+
messageId: 'constructor',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=use-makeObservable-with-decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-makeObservable-with-decorators.js","sourceRoot":"","sources":["../../../src/rules/mobx/use-makeObservable-with-decorators.ts"],"names":[],"mappings":";;;AAEA,4CAA4C;AAC5C,MAAM,cAAc,GAAG,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAE3D,QAAA,mCAAmC,GAAoB;IAChE,IAAI,EAAE;QACF,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACF,WAAW,EAAE,6CAA6C;YAC1D,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,2CAA2C;SACnD;QACD,QAAQ,EAAE;YACN,cAAc,EAAE,4DAA4D;YAC5E,WAAW,EAAE,gEAAgE;SAChF;KACJ;IACD,MAAM,CAAC,OAAO;QACV,OAAO;YACH,gBAAgB,CAAC,IAAI;gBACjB,IAAI,gBAAgB,GAAG,KAAK,CAAC;gBAC7B,IAAI,cAAc,GAAG,KAAK,CAAC;gBAC3B,IAAI,iBAAiB,GAAG,KAAK,CAAC;gBAE9B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,gBAAqB,EAAE,EAAE;;oBAC7C,IAAI,gBAAgB,CAAC,UAAU,EAAE;wBAC7B,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAc,EAAE,EAAE;;4BACnD,IACI,cAAc,CAAC,QAAQ,CACnB,CAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,UAAU,0CAAE,IAAI;iCACvB,MAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,UAAU,0CAAE,MAAM,0CAAE,IAAI,CAAA,CAC1C,EACH;gCACE,gBAAgB,GAAG,IAAI,CAAC;6BAC3B;wBACL,CAAC,CAAC,CAAC;qBACN;oBAED,IAAI,gBAAgB,CAAC,IAAI,KAAK,aAAa,EAAE;wBACzC,cAAc,GAAG,IAAI,CAAC;wBAEtB,MAAA,MAAA,gBAAgB,CAAC,KAAK,0CAAE,IAAI,0CAAE,IAAI,CAAC,OAAO,CAAC,CAAC,SAAc,EAAE,EAAE;;4BAC1D,IAAI,CAAA,MAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,UAAU,0CAAE,MAAM,0CAAE,IAAI,MAAK,gBAAgB,EAAE;gCAC1D,iBAAiB,GAAG,IAAI,CAAC;6BAC5B;wBACL,CAAC,CAAC,CAAC;qBACN;gBACL,CAAC,CAAC,CAAC;gBAEH,IAAI,gBAAgB,IAAI,CAAC,iBAAiB,IAAI,cAAc,EAAE;oBAC1D,OAAO,CAAC,MAAM,CAAC;wBACX,IAAI;wBACJ,SAAS,EAAE,gBAAgB;qBAC9B,CAAC,CAAC;iBACN;gBAED,IAAI,gBAAgB,IAAI,CAAC,iBAAiB,IAAI,CAAC,cAAc,EAAE;oBAC3D,OAAO,CAAC,MAAM,CAAC;wBACX,IAAI;wBACJ,SAAS,EAAE,aAAa;qBAC3B,CAAC,CAAC;iBACN;YACL,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"destructure-default-import.d.ts","sourceRoot":"","sources":["../../../src/rules/react/destructure-default-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,eAAO,MAAM,6BAA6B,EAAE,IAAI,CAAC,UAsChD,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reactDestructureDefaultImport = void 0;
|
|
4
|
+
exports.reactDestructureDefaultImport = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Disallow importing React's default export",
|
|
9
|
+
category: 'Best Practices',
|
|
10
|
+
recommended: false,
|
|
11
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
importDefault: 'Avoid importing React default export',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
ImportDeclaration(node) {
|
|
20
|
+
const reactImportSpecifiers = new Set();
|
|
21
|
+
if (node.source.value !== 'react') {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
node.specifiers.forEach(specifier => {
|
|
25
|
+
if (specifier.type === 'ImportDefaultSpecifier' ||
|
|
26
|
+
specifier.type === 'ImportNamespaceSpecifier') {
|
|
27
|
+
context.report({
|
|
28
|
+
node,
|
|
29
|
+
messageId: 'importDefault',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
reactImportSpecifiers.add(specifier.imported);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=destructure-default-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"destructure-default-import.js","sourceRoot":"","sources":["../../../src/rules/react/destructure-default-import.ts"],"names":[],"mappings":";;;AAEa,QAAA,6BAA6B,GAAoB;IAC1D,IAAI,EAAE;QACF,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACF,WAAW,EAAE,2CAA2C;YACxD,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,2CAA2C;SACnD;QACD,QAAQ,EAAE;YACN,aAAa,EAAE,sCAAsC;SACxD;KACJ;IACD,MAAM,CAAC,OAAO;QACV,OAAO;YACH,iBAAiB,CAAC,IAAI;gBAClB,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAE,CAAC;gBAExC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE;oBAC/B,OAAO;iBACV;gBAED,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;oBAChC,IACI,SAAS,CAAC,IAAI,KAAK,wBAAwB;wBAC3C,SAAS,CAAC,IAAI,KAAK,0BAA0B,EAC/C;wBACE,OAAO,CAAC,MAAM,CAAC;4BACX,IAAI;4BACJ,SAAS,EAAE,eAAe;yBAC7B,CAAC,CAAC;qBACN;yBAAM;wBACH,qBAAqB,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;qBACjD;gBACL,CAAC,CAAC,CAAC;YACP,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-qualified-type.d.ts","sourceRoot":"","sources":["../../../src/rules/react/no-qualified-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,eAAO,MAAM,oBAAoB,EAAE,IAAI,CAAC,UA4BvC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reactNoQualifiedType = void 0;
|
|
4
|
+
exports.reactNoQualifiedType = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Disallow using React types from default export',
|
|
9
|
+
category: 'Best Practices',
|
|
10
|
+
recommended: false,
|
|
11
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
importDefault: "Import {{right}} from 'react' instead of using React.{{right}}",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
TSQualifiedName(node) {
|
|
20
|
+
if (node.left && node.left.name === 'React') {
|
|
21
|
+
context.report({
|
|
22
|
+
node,
|
|
23
|
+
messageId: 'importDefault',
|
|
24
|
+
data: {
|
|
25
|
+
right: node.right.name,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=no-qualified-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-qualified-type.js","sourceRoot":"","sources":["../../../src/rules/react/no-qualified-type.ts"],"names":[],"mappings":";;;AAEa,QAAA,oBAAoB,GAAoB;IACjD,IAAI,EAAE;QACF,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACF,WAAW,EAAE,gDAAgD;YAC7D,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,2CAA2C;SACnD;QACD,QAAQ,EAAE;YACN,aAAa,EAAE,gEAAgE;SAClF;KACJ;IACD,MAAM,CAAC,OAAO;QACV,OAAO;YACH,eAAe,CAAC,IAAS;gBACrB,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;oBACzC,OAAO,CAAC,MAAM,CAAC;wBACX,IAAI;wBACJ,SAAS,EAAE,eAAe;wBAC1B,IAAI,EAAE;4BACF,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;yBACzB;qBACJ,CAAC,CAAC;iBACN;YACL,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@servicetitan/eslint-plugin",
|
|
3
|
+
"version": "16.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/servicetitan/uikit.git",
|
|
8
|
+
"directory": "packages/eslint-plugin"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"typings": "./dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/eslint": "~7.28.0",
|
|
18
|
+
"eslint": "~7.31.0"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"eslint": "~7.31.0"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"cli": {
|
|
27
|
+
"webpack": false
|
|
28
|
+
},
|
|
29
|
+
"gitHead": "d2d6e21f4f639bcde5a9ab274a6fd47b14b26974"
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useDeclareWithDecorators } from './rules/decorators-declare';
|
|
2
|
+
import { mobxUseMakeObservableWithDecorators } from './rules/mobx/use-makeObservable-with-decorators';
|
|
3
|
+
import { mobxNoAbstractDecorators } from './rules/mobx/no-abstract-decorators';
|
|
4
|
+
import { reactDestructureDefaultImport } from './rules/react/destructure-default-import';
|
|
5
|
+
import { reactNoQualifiedType } from './rules/react/no-qualified-type';
|
|
6
|
+
import { stub } from './processors/stub';
|
|
7
|
+
|
|
8
|
+
export const rules = {
|
|
9
|
+
'use-declare-with-decorators': useDeclareWithDecorators,
|
|
10
|
+
'mobx/use-makeObservable-with-decorators': mobxUseMakeObservableWithDecorators,
|
|
11
|
+
'mobx/no-abstract-decorators': mobxNoAbstractDecorators,
|
|
12
|
+
'react/destructure-default-import': reactDestructureDefaultImport,
|
|
13
|
+
'react/no-qualified-type': reactNoQualifiedType,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const processors = { stub };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
const customDecorators = ['injectDependency', 'koObservableToMobx'];
|
|
4
|
+
|
|
5
|
+
export const useDeclareWithDecorators: Rule.RuleModule = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Disallow custom @servicetitan class field decorators without declare',
|
|
10
|
+
category: 'Possible Errors',
|
|
11
|
+
recommended: false,
|
|
12
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
decoratorsDeclare: "Use declare when decorating with '@{{name}}'",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
create(context) {
|
|
19
|
+
return {
|
|
20
|
+
ClassProperty(node: any) {
|
|
21
|
+
if (node.declare) {
|
|
22
|
+
return; // field is already defined with declare
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (node?.decorators?.length) {
|
|
26
|
+
node.decorators.forEach((decorator: any) => {
|
|
27
|
+
const name = decorator.expression?.callee?.name;
|
|
28
|
+
|
|
29
|
+
if (name && customDecorators.includes(name)) {
|
|
30
|
+
context.report({
|
|
31
|
+
node,
|
|
32
|
+
messageId: 'decoratorsDeclare',
|
|
33
|
+
data: {
|
|
34
|
+
name,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
const mobxDecorators = ['observable', 'action', 'computed', 'override'];
|
|
4
|
+
|
|
5
|
+
export const mobxNoAbstractDecorators: Rule.RuleModule = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Disallow MobX decorators on abstract class fields',
|
|
10
|
+
category: 'Possible Errors',
|
|
11
|
+
recommended: false,
|
|
12
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
noAbstractMobxDecorators:
|
|
16
|
+
"Don't decorate abstract class fields or methods with '@{{name}}'",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
create(context: any) {
|
|
20
|
+
function checkFn(node: any) {
|
|
21
|
+
if (node?.decorators?.length) {
|
|
22
|
+
node.decorators.forEach((decorator: any) => {
|
|
23
|
+
const name = decorator?.expression?.name || decorator?.expression?.object?.name;
|
|
24
|
+
|
|
25
|
+
if (name && mobxDecorators.includes(name)) {
|
|
26
|
+
context.report({
|
|
27
|
+
node,
|
|
28
|
+
messageId: 'noAbstractMobxDecorators',
|
|
29
|
+
data: {
|
|
30
|
+
name,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
TSAbstractClassProperty: checkFn,
|
|
40
|
+
TSAbstractMethodDefinition: checkFn,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
// NOTE: "action" also covers "action.bound"
|
|
4
|
+
const mobxDecorators = ['observable', 'action', 'computed', 'override'];
|
|
5
|
+
|
|
6
|
+
export const mobxUseMakeObservableWithDecorators: Rule.RuleModule = {
|
|
7
|
+
meta: {
|
|
8
|
+
type: 'problem',
|
|
9
|
+
docs: {
|
|
10
|
+
description: 'Testing makeObservable used with decorators',
|
|
11
|
+
category: 'Possible Errors',
|
|
12
|
+
recommended: false,
|
|
13
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
makeObservable: 'Use makeObservable in the constructor with MobX decorators',
|
|
17
|
+
constructor: 'Add constructor with makeObservable when using MobX decorators',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
ClassDeclaration(node) {
|
|
23
|
+
let hasMobxDecorator = false;
|
|
24
|
+
let hasConstructor = false;
|
|
25
|
+
let hasMakeObservable = false;
|
|
26
|
+
|
|
27
|
+
node.body.body.forEach((methodOrProperty: any) => {
|
|
28
|
+
if (methodOrProperty.decorators) {
|
|
29
|
+
methodOrProperty.decorators.forEach((decorator: any) => {
|
|
30
|
+
if (
|
|
31
|
+
mobxDecorators.includes(
|
|
32
|
+
decorator?.expression?.name ||
|
|
33
|
+
decorator?.expression?.object?.name
|
|
34
|
+
)
|
|
35
|
+
) {
|
|
36
|
+
hasMobxDecorator = true;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (methodOrProperty.kind === 'constructor') {
|
|
42
|
+
hasConstructor = true;
|
|
43
|
+
|
|
44
|
+
methodOrProperty.value?.body?.body.forEach((statement: any) => {
|
|
45
|
+
if (statement?.expression?.callee?.name === 'makeObservable') {
|
|
46
|
+
hasMakeObservable = true;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (hasMobxDecorator && !hasMakeObservable && hasConstructor) {
|
|
53
|
+
context.report({
|
|
54
|
+
node,
|
|
55
|
+
messageId: 'makeObservable',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (hasMobxDecorator && !hasMakeObservable && !hasConstructor) {
|
|
60
|
+
context.report({
|
|
61
|
+
node,
|
|
62
|
+
messageId: 'constructor',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export const reactDestructureDefaultImport: Rule.RuleModule = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'suggestion',
|
|
6
|
+
docs: {
|
|
7
|
+
description: "Disallow importing React's default export",
|
|
8
|
+
category: 'Best Practices',
|
|
9
|
+
recommended: false,
|
|
10
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
importDefault: 'Avoid importing React default export',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
create(context) {
|
|
17
|
+
return {
|
|
18
|
+
ImportDeclaration(node) {
|
|
19
|
+
const reactImportSpecifiers = new Set();
|
|
20
|
+
|
|
21
|
+
if (node.source.value !== 'react') {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
node.specifiers.forEach(specifier => {
|
|
26
|
+
if (
|
|
27
|
+
specifier.type === 'ImportDefaultSpecifier' ||
|
|
28
|
+
specifier.type === 'ImportNamespaceSpecifier'
|
|
29
|
+
) {
|
|
30
|
+
context.report({
|
|
31
|
+
node,
|
|
32
|
+
messageId: 'importDefault',
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
reactImportSpecifiers.add(specifier.imported);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export const reactNoQualifiedType: Rule.RuleModule = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'suggestion',
|
|
6
|
+
docs: {
|
|
7
|
+
description: 'Disallow using React types from default export',
|
|
8
|
+
category: 'Best Practices',
|
|
9
|
+
recommended: false,
|
|
10
|
+
url: 'https://github.com/servicetitan/uikit.git',
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
importDefault: "Import {{right}} from 'react' instead of using React.{{right}}",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
create(context) {
|
|
17
|
+
return {
|
|
18
|
+
TSQualifiedName(node: any) {
|
|
19
|
+
if (node.left && node.left.name === 'React') {
|
|
20
|
+
context.report({
|
|
21
|
+
node,
|
|
22
|
+
messageId: 'importDefault',
|
|
23
|
+
data: {
|
|
24
|
+
right: node.right.name,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
};
|