eslint-config-typed 7.8.0 → 7.9.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/plugins/ts-restrictions/rules/callee-path.d.mts +18 -0
- package/dist/plugins/ts-restrictions/rules/callee-path.d.mts.map +1 -0
- package/dist/plugins/ts-restrictions/rules/callee-path.mjs +54 -0
- package/dist/plugins/ts-restrictions/rules/callee-path.mjs.map +1 -0
- package/dist/plugins/ts-restrictions/rules/no-clock-read-at-module-load.d.mts +40 -0
- package/dist/plugins/ts-restrictions/rules/no-clock-read-at-module-load.d.mts.map +1 -0
- package/dist/plugins/ts-restrictions/rules/no-clock-read-at-module-load.mjs +148 -0
- package/dist/plugins/ts-restrictions/rules/no-clock-read-at-module-load.mjs.map +1 -0
- package/dist/plugins/ts-restrictions/rules/no-date-only-string-to-date.mjs +1 -49
- package/dist/plugins/ts-restrictions/rules/no-date-only-string-to-date.mjs.map +1 -1
- package/dist/plugins/ts-restrictions/rules/rules.d.mts +3 -0
- package/dist/plugins/ts-restrictions/rules/rules.d.mts.map +1 -1
- package/dist/plugins/ts-restrictions/rules/rules.mjs +2 -0
- package/dist/plugins/ts-restrictions/rules/rules.mjs.map +1 -1
- package/dist/rules/eslint-ts-restrictions-rules.d.mts +1 -0
- package/dist/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
- package/dist/rules/eslint-ts-restrictions-rules.mjs +1 -0
- package/dist/rules/eslint-ts-restrictions-rules.mjs.map +1 -1
- package/dist/types/rules/eslint-ts-restrictions-rules.d.mts +42 -0
- package/dist/types/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
- package/package.json +4 -4
- package/src/plugins/ts-restrictions/rules/callee-path.mts +76 -0
- package/src/plugins/ts-restrictions/rules/no-clock-read-at-module-load.mts +214 -0
- package/src/plugins/ts-restrictions/rules/no-clock-read-at-module-load.test.mts +169 -0
- package/src/plugins/ts-restrictions/rules/no-date-only-string-to-date.mts +1 -68
- package/src/plugins/ts-restrictions/rules/rules.mts +2 -0
- package/src/rules/eslint-ts-restrictions-rules.mts +1 -0
- package/src/types/rules/eslint-ts-restrictions-rules.mts +45 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
import type { DeepReadonly } from 'ts-type-forge';
|
|
3
|
+
/**
|
|
4
|
+
* The name of the member `node` reads: `a.b`, `a['b']` and ``a[`b`]`` are `b`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const memberName: (node: DeepReadonly<TSESTree.MemberExpression>) => string | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* `node` read through its type wrappers and an optional chain around them:
|
|
9
|
+
* `(Date?.parse)` is `Date.parse` wherever it is not `undefined`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const unwrapCallee: (node: DeepReadonly<TSESTree.Node>) => DeepReadonly<TSESTree.Node>;
|
|
12
|
+
/**
|
|
13
|
+
* `node` as a dotted path of names (`globalThis.Date`, `DateUtils.from`), read
|
|
14
|
+
* through type wrappers, optional chains and string-keyed computed members, or
|
|
15
|
+
* `undefined` for anything else.
|
|
16
|
+
*/
|
|
17
|
+
export declare const namePath: (node: DeepReadonly<TSESTree.Node>) => string | undefined;
|
|
18
|
+
//# sourceMappingURL=callee-path.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callee-path.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/callee-path.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAKlD;;GAEG;AACH,eAAO,MAAM,UAAU,SACf,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAC5C,MAAM,GAAG,SAKK,CAAC;AAElB;;;GAGG;AACH,eAAO,MAAM,YAAY,SACjB,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,KAChC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAM5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,SACb,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,KAChC,MAAM,GAAG,SAkBX,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { skipTypeWrappers } from 'eslint-rule-forge';
|
|
3
|
+
import { Arr } from 'ts-data-forge';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export const memberName = (node) => !node.computed && node.property.type === AST_NODE_TYPES.Identifier
|
|
10
|
+
? node.property.name
|
|
11
|
+
: node.computed
|
|
12
|
+
? staticString(node.property)
|
|
13
|
+
: undefined;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export const unwrapCallee = (node) => {
|
|
19
|
+
const unwrapped = skipTypeWrappers(node);
|
|
20
|
+
return unwrapped.type === AST_NODE_TYPES.ChainExpression
|
|
21
|
+
? skipTypeWrappers(unwrapped.expression)
|
|
22
|
+
: unwrapped;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export const namePath = (node) => {
|
|
30
|
+
const value = unwrapCallee(node);
|
|
31
|
+
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
32
|
+
return value.name;
|
|
33
|
+
}
|
|
34
|
+
if (value.type !== AST_NODE_TYPES.MemberExpression) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const object = namePath(value.object);
|
|
38
|
+
const name = memberName(value);
|
|
39
|
+
return object === undefined || name === undefined
|
|
40
|
+
? undefined
|
|
41
|
+
: `${object}.${name}`;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const staticString = (node) => {
|
|
45
|
+
const value = skipTypeWrappers(node);
|
|
46
|
+
if (value.type === AST_NODE_TYPES.Literal) {
|
|
47
|
+
return typeof value.value === 'string' ? value.value : undefined;
|
|
48
|
+
}
|
|
49
|
+
return value.type === AST_NODE_TYPES.TemplateLiteral &&
|
|
50
|
+
Arr.isEmpty(value.expressions)
|
|
51
|
+
? (value.quasis[0]?.value.cooked ?? undefined)
|
|
52
|
+
: undefined;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=callee-path.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callee-path.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/callee-path.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGpC,+EAA+E;AAC/E,gDAAgD;AAEhD;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,IAA6C,EACzB,EAAE,CACtB,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;IAChE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;IACpB,CAAC,CAAC,IAAI,CAAC,QAAQ;QACb,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7B,CAAC,CAAC,SAAS,CAAC;AAElB;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,IAAiC,EACJ,EAAE;IAC/B,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEzC,OAAO,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;QACtD,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC;QACxC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,IAAiC,EACb,EAAE;IACtB,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEjC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAAE,CAAC;QAC7C,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,EAAE,CAAC;QACnD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAE/B,OAAO,MAAM,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;QAC/C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF,gFAAgF;AAChF,MAAM,YAAY,GAAG,CACnB,IAAiC,EACb,EAAE;IACtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAErC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO,EAAE,CAAC;QAC1C,OAAO,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;QAClD,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;QAC9B,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC;QAC9C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [
|
|
3
|
+
Readonly<{
|
|
4
|
+
functions?: readonly string[];
|
|
5
|
+
}>?
|
|
6
|
+
];
|
|
7
|
+
type MessageIds = 'clockReadAtModuleLoad';
|
|
8
|
+
/**
|
|
9
|
+
* Disallow reading the clock when a module loads.
|
|
10
|
+
*
|
|
11
|
+
* ## Why
|
|
12
|
+
*
|
|
13
|
+
* A value computed at module load is computed once, and kept as long as the
|
|
14
|
+
* module is: a page left open past midnight, or a server instance that lives for
|
|
15
|
+
* days, keeps offering the day it loaded. Read the clock where the value is
|
|
16
|
+
* used, in a function.
|
|
17
|
+
*
|
|
18
|
+
* ## What it sees
|
|
19
|
+
*
|
|
20
|
+
* `Date.now()` and `new Date` with no argument, of the global `Date` (also as
|
|
21
|
+
* `globalThis.Date`), and the further callees named in `functions`, when the
|
|
22
|
+
* call runs as the module is evaluated: outside every function body, or inside
|
|
23
|
+
* one invoked where it is written (`(() => …)()`), or in a `static` field or
|
|
24
|
+
* block of a class that is itself evaluated then. A default parameter, a method
|
|
25
|
+
* and an instance field run later, on a call or a construction.
|
|
26
|
+
*
|
|
27
|
+
* The callee is read through `as` / `satisfies` / `!` / `<T>`, `?.` and
|
|
28
|
+
* string-keyed computed members. It is matched by the name written at the call,
|
|
29
|
+
* so a clock read behind a function that is called at load (`const d =
|
|
30
|
+
* makeDefault()`) is not seen, nor is `const D = Date`; name such a function in
|
|
31
|
+
* `functions` when it reads the clock itself.
|
|
32
|
+
*
|
|
33
|
+
* ## Options
|
|
34
|
+
*
|
|
35
|
+
* `functions` names further callees that read the clock, called or constructed,
|
|
36
|
+
* as dotted paths (`'DateUtils.today'`).
|
|
37
|
+
*/
|
|
38
|
+
export declare const noClockReadAtModuleLoad: TSESLint.RuleModule<MessageIds, Options>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=no-clock-read-at-module-load.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-clock-read-at-module-load.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/no-clock-read-at-module-load.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAWlC,KAAK,OAAO,GAAG,SAAS;IACtB,QAAQ,CAAC;QACP,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KAC/B,CAAC,CAAC;CACJ,CAAC;AAEF,KAAK,UAAU,GAAG,uBAAuB,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAgGjE,CAAC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
+
import { asNode, isRuntimeBound, isTypeWrapper, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
3
|
+
import { Arr } from 'ts-data-forge';
|
|
4
|
+
import { memberName, namePath, unwrapCallee } from './callee-path.mjs';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
export const noClockReadAtModuleLoad = {
|
|
36
|
+
meta: {
|
|
37
|
+
type: 'problem',
|
|
38
|
+
docs: {
|
|
39
|
+
description: 'Disallow reading the clock (`Date.now()`, `new Date()`) when a module loads, which keeps that moment for as long as the module lives',
|
|
40
|
+
},
|
|
41
|
+
schema: [
|
|
42
|
+
{
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
functions: {
|
|
46
|
+
type: 'array',
|
|
47
|
+
items: { type: 'string' },
|
|
48
|
+
description: 'Further callees that read the clock, called or constructed, as dotted paths such as `DateUtils.today`.',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
additionalProperties: false,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
messages: {
|
|
55
|
+
clockReadAtModuleLoad: '`{{callee}}` here runs once, when the module loads, and keeps that moment for as long as the module lives. Read the clock where the value is used, in a function.',
|
|
56
|
+
},
|
|
57
|
+
defaultOptions: [{}],
|
|
58
|
+
},
|
|
59
|
+
create: (context) => {
|
|
60
|
+
const functions = new Set(context.options[0]?.functions);
|
|
61
|
+
|
|
62
|
+
const isGlobalDate = (node) => {
|
|
63
|
+
const path = namePath(node);
|
|
64
|
+
const root = path === 'Date'
|
|
65
|
+
? 'Date'
|
|
66
|
+
: path === 'globalThis.Date'
|
|
67
|
+
? 'globalThis'
|
|
68
|
+
: undefined;
|
|
69
|
+
return (root !== undefined &&
|
|
70
|
+
!isRuntimeBound(context.sourceCode, asNode(node), root));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const clockCallee = (node) => {
|
|
74
|
+
const callee = unwrapCallee(node.callee);
|
|
75
|
+
if (node.type === AST_NODE_TYPES.NewExpression) {
|
|
76
|
+
if (Arr.isEmpty(node.arguments) && isGlobalDate(callee)) {
|
|
77
|
+
return 'new Date';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
81
|
+
memberName(callee) === 'now' &&
|
|
82
|
+
isGlobalDate(callee.object)) {
|
|
83
|
+
return 'Date.now';
|
|
84
|
+
}
|
|
85
|
+
const path = namePath(callee);
|
|
86
|
+
return path !== undefined && functions.has(path) ? path : undefined;
|
|
87
|
+
};
|
|
88
|
+
const check = (node) => {
|
|
89
|
+
|
|
90
|
+
const callee = clockCallee(node);
|
|
91
|
+
if (callee === undefined || !runsAtModuleLoad(node)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
context.report({
|
|
95
|
+
node: asNode(node),
|
|
96
|
+
messageId: 'clockReadAtModuleLoad',
|
|
97
|
+
data: { callee },
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
NewExpression: check,
|
|
102
|
+
CallExpression: check,
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const outsideTypeWrappers = (node) => node.parent !== undefined && isTypeWrapper(node.parent)
|
|
108
|
+
? outsideTypeWrappers(node.parent)
|
|
109
|
+
: node;
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
const isInvokedWhereWritten = (node) => {
|
|
115
|
+
const invoker = outsideTypeWrappers(node).parent;
|
|
116
|
+
return (invoker !== undefined &&
|
|
117
|
+
(invoker.type === AST_NODE_TYPES.CallExpression ||
|
|
118
|
+
invoker.type === AST_NODE_TYPES.NewExpression) &&
|
|
119
|
+
skipTypeWrappers(invoker.callee) === node);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
const runsAtModuleLoad = (node) => {
|
|
127
|
+
|
|
128
|
+
if (node.type === AST_NODE_TYPES.Program) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const { parent } = node;
|
|
132
|
+
if (parent.type === AST_NODE_TYPES.FunctionDeclaration) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (parent.type === AST_NODE_TYPES.FunctionExpression ||
|
|
137
|
+
parent.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
138
|
+
return isInvokedWhereWritten(parent) && runsAtModuleLoad(parent);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if (parent.type === AST_NODE_TYPES.PropertyDefinition ||
|
|
143
|
+
parent.type === AST_NODE_TYPES.AccessorProperty) {
|
|
144
|
+
return (parent.value !== node || parent.static) && runsAtModuleLoad(parent);
|
|
145
|
+
}
|
|
146
|
+
return runsAtModuleLoad(parent);
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=no-clock-read-at-module-load.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-clock-read-at-module-load.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/no-clock-read-at-module-load.mts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, ESLintUtils, } from '@typescript-eslint/utils';
|
|
2
2
|
import { asNode, createGetLayerTypes, isRuntimeBound, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
3
|
-
import { Arr } from 'ts-data-forge';
|
|
4
3
|
import * as ts from 'typescript';
|
|
4
|
+
import { memberName, namePath, unwrapCallee } from './callee-path.mjs';
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
@@ -182,52 +182,4 @@ export const noDateOnlyStringToDate = {
|
|
|
182
182
|
|
|
183
183
|
|
|
184
184
|
const dateOnlyPattern = /^(?:\d{4}|[+-]\d{6})(?:|-\d{2}|-\d{2}-\d{2})$/u;
|
|
185
|
-
|
|
186
|
-
const staticString = (node) => {
|
|
187
|
-
const value = skipTypeWrappers(node);
|
|
188
|
-
if (value.type === AST_NODE_TYPES.Literal) {
|
|
189
|
-
return typeof value.value === 'string' ? value.value : undefined;
|
|
190
|
-
}
|
|
191
|
-
return value.type === AST_NODE_TYPES.TemplateLiteral &&
|
|
192
|
-
Arr.isEmpty(value.expressions)
|
|
193
|
-
? (value.quasis[0]?.value.cooked ?? undefined)
|
|
194
|
-
: undefined;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const memberName = (node) => !node.computed && node.property.type === AST_NODE_TYPES.Identifier
|
|
200
|
-
? node.property.name
|
|
201
|
-
: node.computed
|
|
202
|
-
? staticString(node.property)
|
|
203
|
-
: undefined;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const unwrapCallee = (node) => {
|
|
209
|
-
const unwrapped = skipTypeWrappers(node);
|
|
210
|
-
return unwrapped.type === AST_NODE_TYPES.ChainExpression
|
|
211
|
-
? skipTypeWrappers(unwrapped.expression)
|
|
212
|
-
: unwrapped;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const namePath = (node) => {
|
|
220
|
-
const value = unwrapCallee(node);
|
|
221
|
-
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
222
|
-
return value.name;
|
|
223
|
-
}
|
|
224
|
-
if (value.type !== AST_NODE_TYPES.MemberExpression) {
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
|
-
const object = namePath(value.object);
|
|
228
|
-
const name = memberName(value);
|
|
229
|
-
return object === undefined || name === undefined
|
|
230
|
-
? undefined
|
|
231
|
-
: `${object}.${name}`;
|
|
232
|
-
};
|
|
233
185
|
//# sourceMappingURL=no-date-only-string-to-date.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-date-only-string-to-date.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/no-date-only-string-to-date.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,WAAW,GAGZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"no-date-only-string-to-date.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/no-date-only-string-to-date.mts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,9 @@ export declare const tsRestrictionsRules: {
|
|
|
6
6
|
readonly 'explicit-collection-type-arguments': import("@typescript-eslint/utils/ts-eslint").RuleModule<"addInferredTypeArguments" | "missingTypeArguments", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
7
7
|
readonly 'function-order': import("@typescript-eslint/utils/ts-eslint").RuleModule<"calleeAfterCaller" | "exportedAfterHelper", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
8
8
|
readonly 'jsx-boolean-logical-operands': import("@typescript-eslint/utils/ts-eslint").RuleModule<"booleanOperands" | "nonBooleanLeft", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
9
|
+
readonly 'no-clock-read-at-module-load': import("@typescript-eslint/utils/ts-eslint").RuleModule<"clockReadAtModuleLoad", readonly [(Readonly<{
|
|
10
|
+
functions?: readonly string[];
|
|
11
|
+
}> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
9
12
|
readonly 'no-date-only-string-to-date': import("@typescript-eslint/utils/ts-eslint").RuleModule<"dateOnlyString", readonly [(Readonly<{
|
|
10
13
|
functions?: readonly string[];
|
|
11
14
|
}> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BU,CAAC"}
|
|
@@ -2,6 +2,7 @@ import { checkDestructuringCompleteness } from './check-destructuring-completene
|
|
|
2
2
|
import { explicitCollectionTypeArguments } from './explicit-collection-type-arguments.mjs';
|
|
3
3
|
import { functionOrder } from './function-order.mjs';
|
|
4
4
|
import { jsxBooleanLogicalOperands } from './jsx-boolean-logical-operands.mjs';
|
|
5
|
+
import { noClockReadAtModuleLoad } from './no-clock-read-at-module-load.mjs';
|
|
5
6
|
import { noDateOnlyStringToDate } from './no-date-only-string-to-date.mjs';
|
|
6
7
|
import { noDetachedJsdoc } from './no-detached-jsdoc.mjs';
|
|
7
8
|
import { noExportTypeSideEffects } from './no-export-type-side-effects.mjs';
|
|
@@ -28,6 +29,7 @@ export const tsRestrictionsRules = {
|
|
|
28
29
|
'explicit-collection-type-arguments': explicitCollectionTypeArguments,
|
|
29
30
|
'function-order': functionOrder,
|
|
30
31
|
'jsx-boolean-logical-operands': jsxBooleanLogicalOperands,
|
|
32
|
+
'no-clock-read-at-module-load': noClockReadAtModuleLoad,
|
|
31
33
|
'no-date-only-string-to-date': noDateOnlyStringToDate,
|
|
32
34
|
'no-detached-jsdoc': noDetachedJsdoc,
|
|
33
35
|
'no-export-type-side-effects': noExportTypeSideEffects,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,kCAAkC,EAAE,8BAA8B;IAClE,oCAAoC,EAAE,+BAA+B;IACrE,gBAAgB,EAAE,aAAa;IAC/B,8BAA8B,EAAE,yBAAyB;IACzD,6BAA6B,EAAE,sBAAsB;IACrD,mBAAmB,EAAE,eAAe;IACpC,6BAA6B,EAAE,uBAAuB;IACtD,uBAAuB,EAAE,mBAAmB;IAC5C,wBAAwB,EAAE,mBAAmB;IAC7C,yBAAyB,EAAE,oBAAoB;IAC/C,sBAAsB,EAAE,kBAAkB;IAC1C,kBAAkB,EAAE,cAAc;IAClC,2BAA2B,EAAE,sBAAsB;IACnD,mCAAmC,EAAE,8BAA8B;IACnE,cAAc,EAAE,WAAW;IAC3B,qBAAqB,EAAE,iBAAiB;IACxC,eAAe,EAAE,YAAY;IAC7B,oBAAoB,EAAE,gBAAgB;IACtC,qCAAqC,EAAE,+BAA+B;IACtE,kCAAkC,EAAE,4BAA4B;IAChE,qCAAqC,EAAE,+BAA+B;IACtE,oCAAoC,EAAE,8BAA8B;IACpE,mCAAmC,EAAE,4BAA4B;IACjE,gBAAgB,EAAE,aAAa;IAC/B,4BAA4B,EAAE,sBAAsB;CACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"rules.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,kCAAkC,EAAE,8BAA8B;IAClE,oCAAoC,EAAE,+BAA+B;IACrE,gBAAgB,EAAE,aAAa;IAC/B,8BAA8B,EAAE,yBAAyB;IACzD,8BAA8B,EAAE,uBAAuB;IACvD,6BAA6B,EAAE,sBAAsB;IACrD,mBAAmB,EAAE,eAAe;IACpC,6BAA6B,EAAE,uBAAuB;IACtD,uBAAuB,EAAE,mBAAmB;IAC5C,wBAAwB,EAAE,mBAAmB;IAC7C,yBAAyB,EAAE,oBAAoB;IAC/C,sBAAsB,EAAE,kBAAkB;IAC1C,kBAAkB,EAAE,cAAc;IAClC,2BAA2B,EAAE,sBAAsB;IACnD,mCAAmC,EAAE,8BAA8B;IACnE,cAAc,EAAE,WAAW;IAC3B,qBAAqB,EAAE,iBAAiB;IACxC,eAAe,EAAE,YAAY;IAC7B,oBAAoB,EAAE,gBAAgB;IACtC,qCAAqC,EAAE,+BAA+B;IACtE,kCAAkC,EAAE,4BAA4B;IAChE,qCAAqC,EAAE,+BAA+B;IACtE,oCAAoC,EAAE,8BAA8B;IACpE,mCAAmC,EAAE,4BAA4B;IACjE,gBAAgB,EAAE,aAAa;IAC/B,4BAA4B,EAAE,sBAAsB;CACZ,CAAC"}
|
|
@@ -4,6 +4,7 @@ export declare const eslintTsRestrictionsRules: {
|
|
|
4
4
|
readonly 'ts-restrictions/explicit-collection-type-arguments': 'error';
|
|
5
5
|
readonly 'ts-restrictions/function-order': 'error';
|
|
6
6
|
readonly 'ts-restrictions/jsx-boolean-logical-operands': 'error';
|
|
7
|
+
readonly 'ts-restrictions/no-clock-read-at-module-load': 1 | 2;
|
|
7
8
|
readonly 'ts-restrictions/no-date-only-string-to-date': 1 | 2;
|
|
8
9
|
readonly 'ts-restrictions/no-negated-comparison': 'error';
|
|
9
10
|
readonly 'ts-restrictions/no-detached-jsdoc': 'error';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB;qDACI,KAAK;wDACF,KAAK;mEACM,OAAO;+CAC3B,OAAO;6DACO,OAAO
|
|
1
|
+
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB;qDACI,KAAK;wDACF,KAAK;mEACM,OAAO;+CAC3B,OAAO;6DACO,OAAO;;;sDAGd,OAAO;kDACX,OAAO;4DACG,OAAO;;iDAElB,OAAO;0DACE,OAAO;kEACC,OAAO;6CAC5B,OAAO;oDACA,OAAO;8CACb,OAAO;mDACF,OAAO;iEACO,OAAO;oEACJ,OAAO;oEACP,OAAO;mEACR,OAAO;kEACR,OAAO;;;;CAKhB,CAAC"}
|
|
@@ -5,6 +5,7 @@ export const eslintTsRestrictionsRules = {
|
|
|
5
5
|
'ts-restrictions/explicit-collection-type-arguments': 'error',
|
|
6
6
|
'ts-restrictions/function-order': 'error',
|
|
7
7
|
'ts-restrictions/jsx-boolean-logical-operands': 'error',
|
|
8
|
+
'ts-restrictions/no-clock-read-at-module-load': withDefaultOption('error'),
|
|
8
9
|
'ts-restrictions/no-date-only-string-to-date': withDefaultOption('error'),
|
|
9
10
|
'ts-restrictions/no-negated-comparison': 'error',
|
|
10
11
|
'ts-restrictions/no-detached-jsdoc': 'error',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-restrictions-rules.mjs","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,sCAAsC,EAAE,KAAK;IAC7C,yCAAyC,EAAE,KAAK;IAChD,oDAAoD,EAAE,OAAO;IAC7D,gCAAgC,EAAE,OAAO;IACzC,8CAA8C,EAAE,OAAO;IACvD,6CAA6C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACzE,uCAAuC,EAAE,OAAO;IAChD,mCAAmC,EAAE,OAAO;IAC5C,6CAA6C,EAAE,OAAO;IACtD,wCAAwC,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACpE,kCAAkC,EAAE,OAAO;IAC3C,2CAA2C,EAAE,OAAO;IACpD,mDAAmD,EAAE,OAAO;IAC5D,8BAA8B,EAAE,OAAO;IACvC,qCAAqC,EAAE,OAAO;IAC9C,+BAA+B,EAAE,OAAO;IACxC,oCAAoC,EAAE,OAAO;IAC7C,kDAAkD,EAAE,OAAO;IAC3D,qDAAqD,EAAE,OAAO;IAC9D,qDAAqD,EAAE,OAAO;IAC9D,oDAAoD,EAAE,OAAO;IAC7D,mDAAmD,EAAE,OAAO;IAC5D,gCAAgC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAC/D,4CAA4C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACxE,kDAAkD,EAChD,iBAAiB,CAAC,OAAO,CAAC;CACgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"eslint-ts-restrictions-rules.mjs","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,sCAAsC,EAAE,KAAK;IAC7C,yCAAyC,EAAE,KAAK;IAChD,oDAAoD,EAAE,OAAO;IAC7D,gCAAgC,EAAE,OAAO;IACzC,8CAA8C,EAAE,OAAO;IACvD,8CAA8C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IAC1E,6CAA6C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACzE,uCAAuC,EAAE,OAAO;IAChD,mCAAmC,EAAE,OAAO;IAC5C,6CAA6C,EAAE,OAAO;IACtD,wCAAwC,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACpE,kCAAkC,EAAE,OAAO;IAC3C,2CAA2C,EAAE,OAAO;IACpD,mDAAmD,EAAE,OAAO;IAC5D,8BAA8B,EAAE,OAAO;IACvC,qCAAqC,EAAE,OAAO;IAC9C,+BAA+B,EAAE,OAAO;IACxC,oCAAoC,EAAE,OAAO;IAC7C,kDAAkD,EAAE,OAAO;IAC3D,qDAAqD,EAAE,OAAO;IAC9D,qDAAqD,EAAE,OAAO;IAC9D,oDAAoD,EAAE,OAAO;IAC7D,mDAAmD,EAAE,OAAO;IAC5D,gCAAgC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAC/D,4CAA4C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACxE,kDAAkD,EAChD,iBAAiB,CAAC,OAAO,CAAC;CACgB,CAAC"}
|
|
@@ -88,6 +88,46 @@ declare namespace FunctionOrder {
|
|
|
88
88
|
declare namespace JsxBooleanLogicalOperands {
|
|
89
89
|
type RuleEntry = Linter.StringSeverity;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* @description Disallow reading the clock (`Date.now()`, `new Date()`) when a module loads, which keeps that moment for as long as the module lives
|
|
93
|
+
*
|
|
94
|
+
* ```md
|
|
95
|
+
* | key | value |
|
|
96
|
+
* | :--------- | :------ |
|
|
97
|
+
* | type | problem |
|
|
98
|
+
* | deprecated | false |
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
declare namespace NoClockReadAtModuleLoad {
|
|
102
|
+
/**
|
|
103
|
+
* ### schema
|
|
104
|
+
*
|
|
105
|
+
* ```json
|
|
106
|
+
* [
|
|
107
|
+
* {
|
|
108
|
+
* "type": "object",
|
|
109
|
+
* "properties": {
|
|
110
|
+
* "functions": {
|
|
111
|
+
* "type": "array",
|
|
112
|
+
* "items": {
|
|
113
|
+
* "type": "string"
|
|
114
|
+
* },
|
|
115
|
+
* "description": "Further callees that read the clock, called or constructed, as dotted paths such as `DateUtils.today`."
|
|
116
|
+
* }
|
|
117
|
+
* },
|
|
118
|
+
* "additionalProperties": false
|
|
119
|
+
* }
|
|
120
|
+
* ]
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
type Options = Readonly<{
|
|
124
|
+
/**
|
|
125
|
+
* Further callees that read the clock, called or constructed, as dotted paths such as `DateUtils.today`.
|
|
126
|
+
*/
|
|
127
|
+
functions?: readonly string[];
|
|
128
|
+
}>;
|
|
129
|
+
type RuleEntry = 'off' | Linter.Severity | readonly [Linter.StringSeverity, Options];
|
|
130
|
+
}
|
|
91
131
|
/**
|
|
92
132
|
* @description Disallow a date-only string (`YYYY-MM-DD`) read by `new Date` or `Date.parse`, which take it as midnight UTC rather than local midnight
|
|
93
133
|
*
|
|
@@ -614,6 +654,7 @@ export type EslintTsRestrictionsRules = Readonly<{
|
|
|
614
654
|
'ts-restrictions/explicit-collection-type-arguments': ExplicitCollectionTypeArguments.RuleEntry;
|
|
615
655
|
'ts-restrictions/function-order': FunctionOrder.RuleEntry;
|
|
616
656
|
'ts-restrictions/jsx-boolean-logical-operands': JsxBooleanLogicalOperands.RuleEntry;
|
|
657
|
+
'ts-restrictions/no-clock-read-at-module-load': NoClockReadAtModuleLoad.RuleEntry;
|
|
617
658
|
'ts-restrictions/no-date-only-string-to-date': NoDateOnlyStringToDate.RuleEntry;
|
|
618
659
|
'ts-restrictions/no-detached-jsdoc': NoDetachedJsdoc.RuleEntry;
|
|
619
660
|
'ts-restrictions/no-export-type-side-effects': NoExportTypeSideEffects.RuleEntry;
|
|
@@ -638,6 +679,7 @@ export type EslintTsRestrictionsRules = Readonly<{
|
|
|
638
679
|
}>;
|
|
639
680
|
export type EslintTsRestrictionsRulesOption = Readonly<{
|
|
640
681
|
'ts-restrictions/check-destructuring-completeness': CheckDestructuringCompleteness.Options;
|
|
682
|
+
'ts-restrictions/no-clock-read-at-module-load': NoClockReadAtModuleLoad.Options;
|
|
641
683
|
'ts-restrictions/no-date-only-string-to-date': NoDateOnlyStringToDate.Options;
|
|
642
684
|
'ts-restrictions/no-ragged-comment-wrap': NoRaggedCommentWrap.Options;
|
|
643
685
|
'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.Options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-config-typed",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript"
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"is-immutable-type": "^5.0.4",
|
|
78
78
|
"micromatch": "^4.0.8",
|
|
79
79
|
"ts-data-forge": "^14.13.0",
|
|
80
|
-
"ts-type-forge": "^9.2.
|
|
80
|
+
"ts-type-forge": "^9.2.5",
|
|
81
81
|
"tsutils": "^3.21.0"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
@@ -91,10 +91,10 @@
|
|
|
91
91
|
"@vitest/ui": "5.0.5",
|
|
92
92
|
"cspell": "10.4.0",
|
|
93
93
|
"dedent": "1.7.2",
|
|
94
|
-
"eslint-config-typed": "7.
|
|
94
|
+
"eslint-config-typed": "7.9.0",
|
|
95
95
|
"eslint-plugin-ts-data-forge": "0.11.2",
|
|
96
96
|
"eslint-plugin-ts-fortress": "1.3.17",
|
|
97
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
97
|
+
"eslint-plugin-ts-type-forge": "0.8.24",
|
|
98
98
|
"immer": "11.2.7",
|
|
99
99
|
"jiti": "2.7.0",
|
|
100
100
|
"json-schema": "0.4.0",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
import { skipTypeWrappers } from 'eslint-rule-forge';
|
|
3
|
+
import { Arr } from 'ts-data-forge';
|
|
4
|
+
import type { DeepReadonly } from 'ts-type-forge';
|
|
5
|
+
|
|
6
|
+
// How a callee is named at a call, shared by the rules that match callees by a
|
|
7
|
+
// dotted path (`Date.parse`, `DateUtils.from`).
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The name of the member `node` reads: `a.b`, `a['b']` and ``a[`b`]`` are `b`.
|
|
11
|
+
*/
|
|
12
|
+
export const memberName = (
|
|
13
|
+
node: DeepReadonly<TSESTree.MemberExpression>,
|
|
14
|
+
): string | undefined =>
|
|
15
|
+
!node.computed && node.property.type === AST_NODE_TYPES.Identifier
|
|
16
|
+
? node.property.name
|
|
17
|
+
: node.computed
|
|
18
|
+
? staticString(node.property)
|
|
19
|
+
: undefined;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* `node` read through its type wrappers and an optional chain around them:
|
|
23
|
+
* `(Date?.parse)` is `Date.parse` wherever it is not `undefined`.
|
|
24
|
+
*/
|
|
25
|
+
export const unwrapCallee = (
|
|
26
|
+
node: DeepReadonly<TSESTree.Node>,
|
|
27
|
+
): DeepReadonly<TSESTree.Node> => {
|
|
28
|
+
const unwrapped = skipTypeWrappers(node);
|
|
29
|
+
|
|
30
|
+
return unwrapped.type === AST_NODE_TYPES.ChainExpression
|
|
31
|
+
? skipTypeWrappers(unwrapped.expression)
|
|
32
|
+
: unwrapped;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* `node` as a dotted path of names (`globalThis.Date`, `DateUtils.from`), read
|
|
37
|
+
* through type wrappers, optional chains and string-keyed computed members, or
|
|
38
|
+
* `undefined` for anything else.
|
|
39
|
+
*/
|
|
40
|
+
export const namePath = (
|
|
41
|
+
node: DeepReadonly<TSESTree.Node>,
|
|
42
|
+
): string | undefined => {
|
|
43
|
+
const value = unwrapCallee(node);
|
|
44
|
+
|
|
45
|
+
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
46
|
+
return value.name;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (value.type !== AST_NODE_TYPES.MemberExpression) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const object = namePath(value.object);
|
|
54
|
+
|
|
55
|
+
const name = memberName(value);
|
|
56
|
+
|
|
57
|
+
return object === undefined || name === undefined
|
|
58
|
+
? undefined
|
|
59
|
+
: `${object}.${name}`;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** The value of a string literal or a template literal with no substitution. */
|
|
63
|
+
const staticString = (
|
|
64
|
+
node: DeepReadonly<TSESTree.Node>,
|
|
65
|
+
): string | undefined => {
|
|
66
|
+
const value = skipTypeWrappers(node);
|
|
67
|
+
|
|
68
|
+
if (value.type === AST_NODE_TYPES.Literal) {
|
|
69
|
+
return typeof value.value === 'string' ? value.value : undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return value.type === AST_NODE_TYPES.TemplateLiteral &&
|
|
73
|
+
Arr.isEmpty(value.expressions)
|
|
74
|
+
? (value.quasis[0]?.value.cooked ?? undefined)
|
|
75
|
+
: undefined;
|
|
76
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AST_NODE_TYPES,
|
|
3
|
+
type TSESLint,
|
|
4
|
+
type TSESTree,
|
|
5
|
+
} from '@typescript-eslint/utils';
|
|
6
|
+
import {
|
|
7
|
+
asNode,
|
|
8
|
+
isRuntimeBound,
|
|
9
|
+
isTypeWrapper,
|
|
10
|
+
skipTypeWrappers,
|
|
11
|
+
} from 'eslint-rule-forge';
|
|
12
|
+
import { Arr } from 'ts-data-forge';
|
|
13
|
+
import type { DeepReadonly } from 'ts-type-forge';
|
|
14
|
+
import { memberName, namePath, unwrapCallee } from './callee-path.mjs';
|
|
15
|
+
|
|
16
|
+
type Options = readonly [
|
|
17
|
+
Readonly<{
|
|
18
|
+
functions?: readonly string[];
|
|
19
|
+
}>?,
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
type MessageIds = 'clockReadAtModuleLoad';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Disallow reading the clock when a module loads.
|
|
26
|
+
*
|
|
27
|
+
* ## Why
|
|
28
|
+
*
|
|
29
|
+
* A value computed at module load is computed once, and kept as long as the
|
|
30
|
+
* module is: a page left open past midnight, or a server instance that lives for
|
|
31
|
+
* days, keeps offering the day it loaded. Read the clock where the value is
|
|
32
|
+
* used, in a function.
|
|
33
|
+
*
|
|
34
|
+
* ## What it sees
|
|
35
|
+
*
|
|
36
|
+
* `Date.now()` and `new Date` with no argument, of the global `Date` (also as
|
|
37
|
+
* `globalThis.Date`), and the further callees named in `functions`, when the
|
|
38
|
+
* call runs as the module is evaluated: outside every function body, or inside
|
|
39
|
+
* one invoked where it is written (`(() => …)()`), or in a `static` field or
|
|
40
|
+
* block of a class that is itself evaluated then. A default parameter, a method
|
|
41
|
+
* and an instance field run later, on a call or a construction.
|
|
42
|
+
*
|
|
43
|
+
* The callee is read through `as` / `satisfies` / `!` / `<T>`, `?.` and
|
|
44
|
+
* string-keyed computed members. It is matched by the name written at the call,
|
|
45
|
+
* so a clock read behind a function that is called at load (`const d =
|
|
46
|
+
* makeDefault()`) is not seen, nor is `const D = Date`; name such a function in
|
|
47
|
+
* `functions` when it reads the clock itself.
|
|
48
|
+
*
|
|
49
|
+
* ## Options
|
|
50
|
+
*
|
|
51
|
+
* `functions` names further callees that read the clock, called or constructed,
|
|
52
|
+
* as dotted paths (`'DateUtils.today'`).
|
|
53
|
+
*/
|
|
54
|
+
export const noClockReadAtModuleLoad: TSESLint.RuleModule<MessageIds, Options> =
|
|
55
|
+
{
|
|
56
|
+
meta: {
|
|
57
|
+
type: 'problem',
|
|
58
|
+
docs: {
|
|
59
|
+
description:
|
|
60
|
+
'Disallow reading the clock (`Date.now()`, `new Date()`) when a module loads, which keeps that moment for as long as the module lives',
|
|
61
|
+
},
|
|
62
|
+
schema: [
|
|
63
|
+
{
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
functions: {
|
|
67
|
+
type: 'array',
|
|
68
|
+
items: { type: 'string' },
|
|
69
|
+
description:
|
|
70
|
+
'Further callees that read the clock, called or constructed, as dotted paths such as `DateUtils.today`.',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
additionalProperties: false,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
messages: {
|
|
77
|
+
clockReadAtModuleLoad:
|
|
78
|
+
'`{{callee}}` here runs once, when the module loads, and keeps that moment for as long as the module lives. Read the clock where the value is used, in a function.',
|
|
79
|
+
},
|
|
80
|
+
defaultOptions: [{}],
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
create: (context) => {
|
|
84
|
+
const functions: ReadonlySet<string> = new Set(
|
|
85
|
+
context.options[0]?.functions,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
/** Whether `node` names the global `Date`, as `Date` or `globalThis.Date`. */
|
|
89
|
+
const isGlobalDate = (node: DeepReadonly<TSESTree.Node>): boolean => {
|
|
90
|
+
const path = namePath(node);
|
|
91
|
+
|
|
92
|
+
const root =
|
|
93
|
+
path === 'Date'
|
|
94
|
+
? 'Date'
|
|
95
|
+
: path === 'globalThis.Date'
|
|
96
|
+
? 'globalThis'
|
|
97
|
+
: undefined;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
root !== undefined &&
|
|
101
|
+
!isRuntimeBound(context.sourceCode, asNode(node), root)
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** The name `node` is reported under, or `undefined` if it reads no clock. */
|
|
106
|
+
const clockCallee = (
|
|
107
|
+
node: DeepReadonly<TSESTree.CallExpression | TSESTree.NewExpression>,
|
|
108
|
+
): string | undefined => {
|
|
109
|
+
const callee = unwrapCallee(node.callee);
|
|
110
|
+
|
|
111
|
+
if (node.type === AST_NODE_TYPES.NewExpression) {
|
|
112
|
+
if (Arr.isEmpty(node.arguments) && isGlobalDate(callee)) {
|
|
113
|
+
return 'new Date';
|
|
114
|
+
}
|
|
115
|
+
} else if (
|
|
116
|
+
callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
117
|
+
memberName(callee) === 'now' &&
|
|
118
|
+
isGlobalDate(callee.object)
|
|
119
|
+
) {
|
|
120
|
+
return 'Date.now';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const path = namePath(callee);
|
|
124
|
+
|
|
125
|
+
return path !== undefined && functions.has(path) ? path : undefined;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const check = (
|
|
129
|
+
node: DeepReadonly<TSESTree.CallExpression | TSESTree.NewExpression>,
|
|
130
|
+
): void => {
|
|
131
|
+
// The name first: the walk up is paid only by a clock read.
|
|
132
|
+
const callee = clockCallee(node);
|
|
133
|
+
|
|
134
|
+
if (callee === undefined || !runsAtModuleLoad(node)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
context.report({
|
|
139
|
+
node: asNode(node),
|
|
140
|
+
messageId: 'clockReadAtModuleLoad',
|
|
141
|
+
data: { callee },
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
NewExpression: check,
|
|
147
|
+
CallExpression: check,
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
} as const;
|
|
151
|
+
|
|
152
|
+
/** The outermost of the type wrappers around `node`, or `node` itself. */
|
|
153
|
+
const outsideTypeWrappers = (
|
|
154
|
+
node: DeepReadonly<TSESTree.Node>,
|
|
155
|
+
): DeepReadonly<TSESTree.Node> =>
|
|
156
|
+
node.parent !== undefined && isTypeWrapper(node.parent)
|
|
157
|
+
? outsideTypeWrappers(node.parent)
|
|
158
|
+
: node;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Whether the function `node` is called or constructed by the expression it is
|
|
162
|
+
* written in, through type wrappers: `(() => …)()`, `new (function () {})()`.
|
|
163
|
+
*/
|
|
164
|
+
const isInvokedWhereWritten = (
|
|
165
|
+
node: DeepReadonly<
|
|
166
|
+
TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression
|
|
167
|
+
>,
|
|
168
|
+
): boolean => {
|
|
169
|
+
const invoker = outsideTypeWrappers(node).parent;
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
invoker !== undefined &&
|
|
173
|
+
(invoker.type === AST_NODE_TYPES.CallExpression ||
|
|
174
|
+
invoker.type === AST_NODE_TYPES.NewExpression) &&
|
|
175
|
+
skipTypeWrappers(invoker.callee) === node
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Whether `node` is evaluated as its module is: no function body lies between
|
|
181
|
+
* it and the program, but one invoked where it is written, and a class field or
|
|
182
|
+
* block on the way is `static`.
|
|
183
|
+
*/
|
|
184
|
+
const runsAtModuleLoad = (node: DeepReadonly<TSESTree.Node>): boolean => {
|
|
185
|
+
// The program's `parent` is `null` at run time, whatever its type says.
|
|
186
|
+
if (node.type === AST_NODE_TYPES.Program) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const { parent } = node;
|
|
191
|
+
|
|
192
|
+
if (parent.type === AST_NODE_TYPES.FunctionDeclaration) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Its parameters and body run when it is called.
|
|
197
|
+
if (
|
|
198
|
+
parent.type === AST_NODE_TYPES.FunctionExpression ||
|
|
199
|
+
parent.type === AST_NODE_TYPES.ArrowFunctionExpression
|
|
200
|
+
) {
|
|
201
|
+
return isInvokedWhereWritten(parent) && runsAtModuleLoad(parent);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// An instance field's value is computed on each construction; a static one's,
|
|
205
|
+
// and a computed key, when the class is.
|
|
206
|
+
if (
|
|
207
|
+
parent.type === AST_NODE_TYPES.PropertyDefinition ||
|
|
208
|
+
parent.type === AST_NODE_TYPES.AccessorProperty
|
|
209
|
+
) {
|
|
210
|
+
return (parent.value !== node || parent.static) && runsAtModuleLoad(parent);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return runsAtModuleLoad(parent);
|
|
214
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import parser from '@typescript-eslint/parser';
|
|
2
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
3
|
+
import { noClockReadAtModuleLoad } from './no-clock-read-at-module-load.mjs';
|
|
4
|
+
|
|
5
|
+
const tester = new RuleTester({
|
|
6
|
+
languageOptions: {
|
|
7
|
+
parser,
|
|
8
|
+
parserOptions: {
|
|
9
|
+
ecmaVersion: 2022,
|
|
10
|
+
sourceType: 'module',
|
|
11
|
+
projectService: {
|
|
12
|
+
allowDefaultProject: ['*.ts*'],
|
|
13
|
+
},
|
|
14
|
+
tsconfigRootDir: `${import.meta.dirname}/../../../..`,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const messageId = 'clockReadAtModuleLoad';
|
|
20
|
+
|
|
21
|
+
const withHelpers = [
|
|
22
|
+
{ functions: ['DateUtils.today', 'todayYearMonthDate'] },
|
|
23
|
+
] as const;
|
|
24
|
+
|
|
25
|
+
describe('no-clock-read-at-module-load', () => {
|
|
26
|
+
tester.run('no-clock-read-at-module-load', noClockReadAtModuleLoad, {
|
|
27
|
+
valid: [
|
|
28
|
+
{
|
|
29
|
+
name: 'in a function declaration',
|
|
30
|
+
code: 'export function now(): number { return Date.now(); }',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'in an arrow function',
|
|
34
|
+
code: 'export const today = (): Date => new Date();',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'in a method',
|
|
38
|
+
code: 'export const clock = { now(): number { return Date.now(); } };',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'in a getter',
|
|
42
|
+
code: 'export const clock = { get now(): number { return Date.now(); } };',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'a default parameter, read on each call',
|
|
46
|
+
code: 'export const f = (at: number = Date.now()): number => at;',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'an instance field, read on each construction',
|
|
50
|
+
code: 'export class Stamp { readonly at = Date.now(); }',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'a static field of a class made in a function',
|
|
54
|
+
code: 'export const make = () => class { static at = Date.now(); };',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'a function passed along, not invoked here',
|
|
58
|
+
code: 'export const later = [() => Date.now()];',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: '`new Date` with an argument reads no clock',
|
|
62
|
+
code: "export const epoch = new Date(0);\nexport const day = new Date('2026-11-03T00:00:00Z');",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'Date.UTC',
|
|
66
|
+
code: 'export const t = Date.UTC(2026, 10, 3);',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'a local `Date`, which is not the global',
|
|
70
|
+
code: 'class Date { static now(): number { return 0; } }\nexport const t = Date.now();',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'a helper not named in `functions`',
|
|
74
|
+
code: 'declare const DateUtils: { today: () => Date };\nexport const t = DateUtils.today();',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'a function wrapped in a type, not invoked',
|
|
78
|
+
code: 'export const f = (() => Date.now()) as () => number;',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'a named helper inside a function',
|
|
82
|
+
code: 'declare const DateUtils: { today: () => Date };\nexport const f = (): Date => DateUtils.today();',
|
|
83
|
+
options: withHelpers,
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
invalid: [
|
|
87
|
+
{
|
|
88
|
+
name: 'Date.now() at the top level',
|
|
89
|
+
code: 'export const t = Date.now();',
|
|
90
|
+
errors: [{ messageId, data: { callee: 'Date.now' } }],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: '`new Date()` with no argument',
|
|
94
|
+
code: 'export const d = new Date();',
|
|
95
|
+
errors: [{ messageId, data: { callee: 'new Date' } }],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: '`new Date` with no parentheses',
|
|
99
|
+
code: 'export const d = new Date;',
|
|
100
|
+
errors: [{ messageId, data: { callee: 'new Date' } }],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'through globalThis',
|
|
104
|
+
code: 'export const t = globalThis.Date.now();\nexport const d = new globalThis.Date();',
|
|
105
|
+
errors: [
|
|
106
|
+
{ messageId, data: { callee: 'Date.now' } },
|
|
107
|
+
{ messageId, data: { callee: 'new Date' } },
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'through type wrappers and an optional call',
|
|
112
|
+
code: 'export const t = (Date as DateConstructor).now();\nexport const u = Date.now?.();\nexport const d = new (Date satisfies DateConstructor)();',
|
|
113
|
+
errors: [
|
|
114
|
+
{ messageId, data: { callee: 'Date.now' } },
|
|
115
|
+
{ messageId, data: { callee: 'Date.now' } },
|
|
116
|
+
{ messageId, data: { callee: 'new Date' } },
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'through `!` on the global',
|
|
121
|
+
code: 'export const t = Date!.now();\nexport const d = new Date!();',
|
|
122
|
+
errors: [
|
|
123
|
+
{ messageId, data: { callee: 'Date.now' } },
|
|
124
|
+
{ messageId, data: { callee: 'new Date' } },
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'the whole read wrapped in a type',
|
|
129
|
+
code: 'export const t = Date.now() satisfies number;',
|
|
130
|
+
errors: [{ messageId, data: { callee: 'Date.now' } }],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'a function wrapped in a type, then invoked at once',
|
|
134
|
+
code: 'export const t = ((() => Date.now()) as () => number)();',
|
|
135
|
+
errors: [{ messageId, data: { callee: 'Date.now' } }],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'nested in a value built at load',
|
|
139
|
+
code: 'export const initial = { title: "", ymd: [new Date()] } as const;',
|
|
140
|
+
errors: [{ messageId, data: { callee: 'new Date' } }],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'in a function invoked at once',
|
|
144
|
+
code: 'export const t = (() => Date.now())();\nexport const u = (function () { return new Date(); })();',
|
|
145
|
+
errors: [
|
|
146
|
+
{ messageId, data: { callee: 'Date.now' } },
|
|
147
|
+
{ messageId, data: { callee: 'new Date' } },
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'in a static field and a static block of a top-level class',
|
|
152
|
+
code: 'export class Clock { static at = Date.now(); static { new Date(); } }',
|
|
153
|
+
errors: [
|
|
154
|
+
{ messageId, data: { callee: 'Date.now' } },
|
|
155
|
+
{ messageId, data: { callee: 'new Date' } },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'helpers named in `functions`, called and constructed',
|
|
160
|
+
code: 'declare const DateUtils: { today: () => Date };\ndeclare const todayYearMonthDate: () => unknown;\nexport const a = DateUtils.today();\nexport const b = todayYearMonthDate();',
|
|
161
|
+
options: withHelpers,
|
|
162
|
+
errors: [
|
|
163
|
+
{ messageId, data: { callee: 'DateUtils.today' } },
|
|
164
|
+
{ messageId, data: { callee: 'todayYearMonthDate' } },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
});
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
isRuntimeBound,
|
|
11
11
|
skipTypeWrappers,
|
|
12
12
|
} from 'eslint-rule-forge';
|
|
13
|
-
import { Arr } from 'ts-data-forge';
|
|
14
13
|
import type { DeepReadonly } from 'ts-type-forge';
|
|
15
14
|
import * as ts from 'typescript';
|
|
15
|
+
import { memberName, namePath, unwrapCallee } from './callee-path.mjs';
|
|
16
16
|
|
|
17
17
|
type Options = readonly [
|
|
18
18
|
Readonly<{
|
|
@@ -261,70 +261,3 @@ export const noDateOnlyStringToDate: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
261
261
|
* digits or a sign and six.
|
|
262
262
|
*/
|
|
263
263
|
const dateOnlyPattern = /^(?:\d{4}|[+-]\d{6})(?:|-\d{2}|-\d{2}-\d{2})$/u;
|
|
264
|
-
|
|
265
|
-
/** The value of a string literal or a template literal with no substitution. */
|
|
266
|
-
const staticString = (
|
|
267
|
-
node: DeepReadonly<TSESTree.Node>,
|
|
268
|
-
): string | undefined => {
|
|
269
|
-
const value = skipTypeWrappers(node);
|
|
270
|
-
|
|
271
|
-
if (value.type === AST_NODE_TYPES.Literal) {
|
|
272
|
-
return typeof value.value === 'string' ? value.value : undefined;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return value.type === AST_NODE_TYPES.TemplateLiteral &&
|
|
276
|
-
Arr.isEmpty(value.expressions)
|
|
277
|
-
? (value.quasis[0]?.value.cooked ?? undefined)
|
|
278
|
-
: undefined;
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* The name of the member `node` reads: `a.b`, `a['b']` and ``a[`b`]`` are `b`.
|
|
283
|
-
*/
|
|
284
|
-
const memberName = (
|
|
285
|
-
node: DeepReadonly<TSESTree.MemberExpression>,
|
|
286
|
-
): string | undefined =>
|
|
287
|
-
!node.computed && node.property.type === AST_NODE_TYPES.Identifier
|
|
288
|
-
? node.property.name
|
|
289
|
-
: node.computed
|
|
290
|
-
? staticString(node.property)
|
|
291
|
-
: undefined;
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* `node` read through its type wrappers and an optional chain around them:
|
|
295
|
-
* `(Date?.parse)` is `Date.parse` wherever it is not `undefined`.
|
|
296
|
-
*/
|
|
297
|
-
const unwrapCallee = (
|
|
298
|
-
node: DeepReadonly<TSESTree.Node>,
|
|
299
|
-
): DeepReadonly<TSESTree.Node> => {
|
|
300
|
-
const unwrapped = skipTypeWrappers(node);
|
|
301
|
-
|
|
302
|
-
return unwrapped.type === AST_NODE_TYPES.ChainExpression
|
|
303
|
-
? skipTypeWrappers(unwrapped.expression)
|
|
304
|
-
: unwrapped;
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* `node` as a dotted path of names (`globalThis.Date`, `DateUtils.from`), read
|
|
309
|
-
* through type wrappers, optional chains and string-keyed computed members, or
|
|
310
|
-
* `undefined` for anything else.
|
|
311
|
-
*/
|
|
312
|
-
const namePath = (node: DeepReadonly<TSESTree.Node>): string | undefined => {
|
|
313
|
-
const value = unwrapCallee(node);
|
|
314
|
-
|
|
315
|
-
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
316
|
-
return value.name;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (value.type !== AST_NODE_TYPES.MemberExpression) {
|
|
320
|
-
return undefined;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const object = namePath(value.object);
|
|
324
|
-
|
|
325
|
-
const name = memberName(value);
|
|
326
|
-
|
|
327
|
-
return object === undefined || name === undefined
|
|
328
|
-
? undefined
|
|
329
|
-
: `${object}.${name}`;
|
|
330
|
-
};
|
|
@@ -3,6 +3,7 @@ import { checkDestructuringCompleteness } from './check-destructuring-completene
|
|
|
3
3
|
import { explicitCollectionTypeArguments } from './explicit-collection-type-arguments.mjs';
|
|
4
4
|
import { functionOrder } from './function-order.mjs';
|
|
5
5
|
import { jsxBooleanLogicalOperands } from './jsx-boolean-logical-operands.mjs';
|
|
6
|
+
import { noClockReadAtModuleLoad } from './no-clock-read-at-module-load.mjs';
|
|
6
7
|
import { noDateOnlyStringToDate } from './no-date-only-string-to-date.mjs';
|
|
7
8
|
import { noDetachedJsdoc } from './no-detached-jsdoc.mjs';
|
|
8
9
|
import { noExportTypeSideEffects } from './no-export-type-side-effects.mjs';
|
|
@@ -30,6 +31,7 @@ export const tsRestrictionsRules = {
|
|
|
30
31
|
'explicit-collection-type-arguments': explicitCollectionTypeArguments,
|
|
31
32
|
'function-order': functionOrder,
|
|
32
33
|
'jsx-boolean-logical-operands': jsxBooleanLogicalOperands,
|
|
34
|
+
'no-clock-read-at-module-load': noClockReadAtModuleLoad,
|
|
33
35
|
'no-date-only-string-to-date': noDateOnlyStringToDate,
|
|
34
36
|
'no-detached-jsdoc': noDetachedJsdoc,
|
|
35
37
|
'no-export-type-side-effects': noExportTypeSideEffects,
|
|
@@ -9,6 +9,7 @@ export const eslintTsRestrictionsRules = {
|
|
|
9
9
|
'ts-restrictions/explicit-collection-type-arguments': 'error',
|
|
10
10
|
'ts-restrictions/function-order': 'error',
|
|
11
11
|
'ts-restrictions/jsx-boolean-logical-operands': 'error',
|
|
12
|
+
'ts-restrictions/no-clock-read-at-module-load': withDefaultOption('error'),
|
|
12
13
|
'ts-restrictions/no-date-only-string-to-date': withDefaultOption('error'),
|
|
13
14
|
'ts-restrictions/no-negated-comparison': 'error',
|
|
14
15
|
'ts-restrictions/no-detached-jsdoc': 'error',
|
|
@@ -101,6 +101,49 @@ namespace JsxBooleanLogicalOperands {
|
|
|
101
101
|
export type RuleEntry = Linter.StringSeverity;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* @description Disallow reading the clock (`Date.now()`, `new Date()`) when a module loads, which keeps that moment for as long as the module lives
|
|
106
|
+
*
|
|
107
|
+
* ```md
|
|
108
|
+
* | key | value |
|
|
109
|
+
* | :--------- | :------ |
|
|
110
|
+
* | type | problem |
|
|
111
|
+
* | deprecated | false |
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
namespace NoClockReadAtModuleLoad {
|
|
115
|
+
/**
|
|
116
|
+
* ### schema
|
|
117
|
+
*
|
|
118
|
+
* ```json
|
|
119
|
+
* [
|
|
120
|
+
* {
|
|
121
|
+
* "type": "object",
|
|
122
|
+
* "properties": {
|
|
123
|
+
* "functions": {
|
|
124
|
+
* "type": "array",
|
|
125
|
+
* "items": {
|
|
126
|
+
* "type": "string"
|
|
127
|
+
* },
|
|
128
|
+
* "description": "Further callees that read the clock, called or constructed, as dotted paths such as `DateUtils.today`."
|
|
129
|
+
* }
|
|
130
|
+
* },
|
|
131
|
+
* "additionalProperties": false
|
|
132
|
+
* }
|
|
133
|
+
* ]
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export type Options = Readonly<{
|
|
137
|
+
/**
|
|
138
|
+
* Further callees that read the clock, called or constructed, as dotted paths such as `DateUtils.today`.
|
|
139
|
+
*/
|
|
140
|
+
functions?: readonly string[];
|
|
141
|
+
}>;
|
|
142
|
+
|
|
143
|
+
export type RuleEntry =
|
|
144
|
+
'off' | Linter.Severity | readonly [Linter.StringSeverity, Options];
|
|
145
|
+
}
|
|
146
|
+
|
|
104
147
|
/**
|
|
105
148
|
* @description Disallow a date-only string (`YYYY-MM-DD`) read by `new Date` or `Date.parse`, which take it as midnight UTC rather than local midnight
|
|
106
149
|
*
|
|
@@ -673,6 +716,7 @@ export type EslintTsRestrictionsRules = Readonly<{
|
|
|
673
716
|
'ts-restrictions/explicit-collection-type-arguments': ExplicitCollectionTypeArguments.RuleEntry;
|
|
674
717
|
'ts-restrictions/function-order': FunctionOrder.RuleEntry;
|
|
675
718
|
'ts-restrictions/jsx-boolean-logical-operands': JsxBooleanLogicalOperands.RuleEntry;
|
|
719
|
+
'ts-restrictions/no-clock-read-at-module-load': NoClockReadAtModuleLoad.RuleEntry;
|
|
676
720
|
'ts-restrictions/no-date-only-string-to-date': NoDateOnlyStringToDate.RuleEntry;
|
|
677
721
|
'ts-restrictions/no-detached-jsdoc': NoDetachedJsdoc.RuleEntry;
|
|
678
722
|
'ts-restrictions/no-export-type-side-effects': NoExportTypeSideEffects.RuleEntry;
|
|
@@ -698,6 +742,7 @@ export type EslintTsRestrictionsRules = Readonly<{
|
|
|
698
742
|
|
|
699
743
|
export type EslintTsRestrictionsRulesOption = Readonly<{
|
|
700
744
|
'ts-restrictions/check-destructuring-completeness': CheckDestructuringCompleteness.Options;
|
|
745
|
+
'ts-restrictions/no-clock-read-at-module-load': NoClockReadAtModuleLoad.Options;
|
|
701
746
|
'ts-restrictions/no-date-only-string-to-date': NoDateOnlyStringToDate.Options;
|
|
702
747
|
'ts-restrictions/no-ragged-comment-wrap': NoRaggedCommentWrap.Options;
|
|
703
748
|
'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.Options;
|