@pezkuwi/dev 0.86.2 → 0.86.4
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/cjs/packageInfo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.packageInfo = void 0;
|
|
4
|
-
exports.packageInfo = { name: '@pezkuwi/dev', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '0.86.
|
|
4
|
+
exports.packageInfo = { name: '@pezkuwi/dev', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '0.86.4' };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright 2017-2026 @pezkuwi/dev authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/** @type {Map<string, string>} */
|
|
5
|
+
const sources = new Map();
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Widens the fix eslint core gives an unused disable directive.
|
|
9
|
+
*
|
|
10
|
+
* Core removes only the comment and puts a single space in its place
|
|
11
|
+
* (lib/linter/apply-disable-directives.js), so --fix turns
|
|
12
|
+
*
|
|
13
|
+
* const a = 1;
|
|
14
|
+
* // eslint-disable-next-line no-console
|
|
15
|
+
* const b = 2;
|
|
16
|
+
*
|
|
17
|
+
* into a whitespace-only line between the two statements, which the layout
|
|
18
|
+
* rules then leave behind as a blank line. Measured on the consumers after the
|
|
19
|
+
* eslint 10 move: 23 such lines in api alone, each removed by hand.
|
|
20
|
+
*
|
|
21
|
+
* Only a fix that removes a whole directive comment is changed: alone on its
|
|
22
|
+
* line, the line goes; after code, the space before it goes; before code, the
|
|
23
|
+
* space after it goes. Removing one rule name out of several is left as core
|
|
24
|
+
* makes it, as is every message with a rule id.
|
|
25
|
+
*
|
|
26
|
+
* @param {import('eslint').Linter.LintMessage} message
|
|
27
|
+
* @param {string} text the source the message was produced from
|
|
28
|
+
* @returns {import('eslint').Linter.LintMessage}
|
|
29
|
+
*/
|
|
30
|
+
function widenDirectiveFix (message, text) {
|
|
31
|
+
if (message.ruleId !== null || message.fix?.text.trim() !== '') {
|
|
32
|
+
return message;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let [start, end] = message.fix.range;
|
|
36
|
+
|
|
37
|
+
if (!/^\/[/*]/.test(text.slice(start, end))) {
|
|
38
|
+
return message;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const lineStart = text.lastIndexOf('\n', start - 1) + 1;
|
|
42
|
+
const newline = text.indexOf('\n', end);
|
|
43
|
+
const lineEnd = newline === -1 ? text.length : newline;
|
|
44
|
+
const aloneBefore = text.slice(lineStart, start).trim() === '';
|
|
45
|
+
const aloneAfter = text.slice(end, lineEnd).trim() === '';
|
|
46
|
+
|
|
47
|
+
if (aloneBefore && aloneAfter) {
|
|
48
|
+
return { ...message, fix: { range: [lineStart, newline === -1 ? text.length : newline + 1], text: '' } };
|
|
49
|
+
} else if (aloneBefore) {
|
|
50
|
+
while (end < lineEnd && /[ \t]/.test(text[end] ?? '')) {
|
|
51
|
+
end++;
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
while (start > lineStart && /[ \t]/.test(text[start - 1] ?? '')) {
|
|
55
|
+
start--;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { ...message, fix: { range: [start, end], text: '' } };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @type {import('eslint').Linter.Processor} */
|
|
63
|
+
export const directiveLines = {
|
|
64
|
+
meta: { name: '@pezkuwi/dev/directive-lines' },
|
|
65
|
+
postprocess (lists, filename) {
|
|
66
|
+
const text = sources.get(filename) ?? '';
|
|
67
|
+
|
|
68
|
+
sources.delete(filename);
|
|
69
|
+
|
|
70
|
+
return lists.flat().map((m) => widenDirectiveFix(m, text));
|
|
71
|
+
},
|
|
72
|
+
preprocess (text, filename) {
|
|
73
|
+
sources.set(filename, text);
|
|
74
|
+
|
|
75
|
+
return [text];
|
|
76
|
+
},
|
|
77
|
+
supportsAutofix: true
|
|
78
|
+
};
|
package/config/eslint.js
CHANGED
|
@@ -22,8 +22,11 @@ import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort';
|
|
|
22
22
|
import sortDestructureKeysPlugin from 'eslint-plugin-sort-destructure-keys';
|
|
23
23
|
import globals from 'globals';
|
|
24
24
|
|
|
25
|
+
import { directiveLines } from './eslint.directives.js';
|
|
25
26
|
import { overrideAll, overrideJs, overrideJsx, overrideSpec } from './eslint.rules.js';
|
|
26
27
|
import { standardRules } from './eslint.standard.js';
|
|
28
|
+
import { withoutContextualAssertions } from './eslint.typeAssertion.js';
|
|
29
|
+
import { withoutExportAllFix } from './eslint.typeExports.js';
|
|
27
30
|
|
|
28
31
|
/**
|
|
29
32
|
* eslint-plugin-header declares no options schema, and eslint 9+ rejects
|
|
@@ -93,7 +96,8 @@ export default [
|
|
|
93
96
|
},
|
|
94
97
|
plugins: {
|
|
95
98
|
'@stylistic': stylisticPlugin,
|
|
96
|
-
|
|
99
|
+
// see eslint.typeAssertion.js and eslint.typeExports.js
|
|
100
|
+
'@typescript-eslint': withoutExportAllFix(withoutContextualAssertions(tsPlugin)),
|
|
97
101
|
// eslint-plugin-header reports at the first token after the leading
|
|
98
102
|
// comments, so a generated file's /* eslint-disable */ covers it; the
|
|
99
103
|
// maintained fork reports at line 1 instead. The compat layer supplies the
|
|
@@ -124,6 +128,8 @@ export default [
|
|
|
124
128
|
},
|
|
125
129
|
{
|
|
126
130
|
files: extsToGlobs(EXT_ALL),
|
|
131
|
+
// see eslint.directives.js
|
|
132
|
+
processor: directiveLines,
|
|
127
133
|
rules: {
|
|
128
134
|
...eslintJs.configs.recommended.rules,
|
|
129
135
|
...standardRules,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright 2017-2026 @pezkuwi/dev authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
const RULE = 'no-unnecessary-type-assertion';
|
|
5
|
+
const ASSERTIONS = ['TSAsExpression', 'TSTypeAssertion'];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* typescript-eslint 8 added a second check to no-unnecessary-type-assertion:
|
|
9
|
+
* an `x as T` is reported as unnecessary when the place it is passed to would
|
|
10
|
+
* accept `x` as it is ("the receiver accepts the original type"), and the
|
|
11
|
+
* autofix deletes the assertion. That is unsound when the assertion also
|
|
12
|
+
* drives inference around it: in
|
|
13
|
+
*
|
|
14
|
+
* const { validators } = found || { validators: {} as ValPoints };
|
|
15
|
+
*
|
|
16
|
+
* deleting `as ValPoints` leaves `validators` typed `{}`, and every use of it
|
|
17
|
+
* after that is an unresolved type. It also deletes assertions kept on
|
|
18
|
+
* purpose for another environment's typings (a Ledger transport under
|
|
19
|
+
* esm.sh). Measured across the consumers before this was added: 45 such
|
|
20
|
+
* reports, the first of them breaking the types of api-derive.
|
|
21
|
+
*
|
|
22
|
+
* This keeps the rule as it was before that check: an assertion to the type
|
|
23
|
+
* the expression already has is still reported and fixed, and so are non-null
|
|
24
|
+
* assertions the receiver makes unnecessary. Only the contextual report on
|
|
25
|
+
* `as` / `<T>` assertions is dropped.
|
|
26
|
+
*
|
|
27
|
+
* @template {object} P
|
|
28
|
+
* @param {P} plugin the @typescript-eslint plugin
|
|
29
|
+
* @returns {P}
|
|
30
|
+
*/
|
|
31
|
+
export function withoutContextualAssertions (plugin) {
|
|
32
|
+
const rules = /** @type {Record<string, import('eslint').Rule.RuleModule>} */ (/** @type {{ rules: unknown }} */ (plugin).rules);
|
|
33
|
+
const rule = rules[RULE];
|
|
34
|
+
|
|
35
|
+
return /** @type {P} */ ({
|
|
36
|
+
...plugin,
|
|
37
|
+
rules: {
|
|
38
|
+
...rules,
|
|
39
|
+
[RULE]: {
|
|
40
|
+
...rule,
|
|
41
|
+
/** @param {import('eslint').Rule.RuleContext} context */
|
|
42
|
+
create (context) {
|
|
43
|
+
const filtered = Object.create(context, {
|
|
44
|
+
report: {
|
|
45
|
+
value: (/** @type {import('eslint').Rule.ReportDescriptor} */ descriptor) => {
|
|
46
|
+
if (
|
|
47
|
+
'messageId' in descriptor &&
|
|
48
|
+
descriptor.messageId === 'contextuallyUnnecessary' &&
|
|
49
|
+
'node' in descriptor &&
|
|
50
|
+
ASSERTIONS.includes(descriptor.node.type)
|
|
51
|
+
) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
context.report(descriptor);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return rule.create(filtered);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright 2017-2026 @pezkuwi/dev authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
const RULE = 'consistent-type-exports';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* consistent-type-exports reports an `export * from './x'` whose module only
|
|
8
|
+
* exports types, and its autofix turns it into `export type * from './x'`.
|
|
9
|
+
* That changes what runs: `export *` loads the module, `export type *` is
|
|
10
|
+
* erased, so a module that only exports types but registers something when it
|
|
11
|
+
* loads (a Handlebars partial, an interface augmentation) silently stops being
|
|
12
|
+
* loaded. Measured on the consumers: the api typegen lost its `docs` partial
|
|
13
|
+
* this way and the build failed only at template time.
|
|
14
|
+
*
|
|
15
|
+
* Named re-exports do not have this problem: under verbatimModuleSyntax a
|
|
16
|
+
* type re-exported without `type` is already a compile error (TS1205).
|
|
17
|
+
*
|
|
18
|
+
* This keeps the report as it is and moves the `export *` fix into a
|
|
19
|
+
* suggestion, so --fix no longer applies it and an editor still offers it.
|
|
20
|
+
* Whoever accepts it decides whether the module needs a side-effect import.
|
|
21
|
+
*
|
|
22
|
+
* @template {object} P
|
|
23
|
+
* @param {P} plugin the @typescript-eslint plugin
|
|
24
|
+
* @returns {P}
|
|
25
|
+
*/
|
|
26
|
+
export function withoutExportAllFix (plugin) {
|
|
27
|
+
const rules = /** @type {Record<string, import('eslint').Rule.RuleModule>} */ (/** @type {{ rules: unknown }} */ (plugin).rules);
|
|
28
|
+
const rule = rules[RULE];
|
|
29
|
+
|
|
30
|
+
return /** @type {P} */ ({
|
|
31
|
+
...plugin,
|
|
32
|
+
rules: {
|
|
33
|
+
...rules,
|
|
34
|
+
[RULE]: {
|
|
35
|
+
...rule,
|
|
36
|
+
/** @param {import('eslint').Rule.RuleContext} context */
|
|
37
|
+
create (context) {
|
|
38
|
+
const filtered = Object.create(context, {
|
|
39
|
+
report: {
|
|
40
|
+
value: (/** @type {import('eslint').Rule.ReportDescriptor} */ descriptor) => {
|
|
41
|
+
if ('node' in descriptor && descriptor.node.type === 'ExportAllDeclaration' && descriptor.fix) {
|
|
42
|
+
const { fix, ...rest } = descriptor;
|
|
43
|
+
|
|
44
|
+
context.report({
|
|
45
|
+
...rest,
|
|
46
|
+
suggest: [{ desc: 'Use `export type *` (the module is no longer loaded: add a side-effect import if it registers anything)', fix }]
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
context.report(descriptor);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return rule.create(filtered);
|
|
58
|
+
},
|
|
59
|
+
meta: { ...rule.meta, hasSuggestions: true }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"sideEffects": false,
|
|
17
17
|
"type": "module",
|
|
18
|
-
"version": "0.86.
|
|
18
|
+
"version": "0.86.4",
|
|
19
19
|
"bin": {
|
|
20
20
|
"pezkuwi-ci-ghact-build": "./scripts/pezkuwi-ci-ghact-build.mjs",
|
|
21
21
|
"pezkuwi-ci-ghact-docs": "./scripts/pezkuwi-ci-ghact-docs.mjs",
|
|
@@ -63,8 +63,11 @@
|
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"./config/eslint": "./config/eslint.js",
|
|
66
|
+
"./config/eslint.directives": "./config/eslint.directives.js",
|
|
66
67
|
"./config/eslint.rules": "./config/eslint.rules.js",
|
|
67
68
|
"./config/eslint.standard": "./config/eslint.standard.js",
|
|
69
|
+
"./config/eslint.typeAssertion": "./config/eslint.typeAssertion.js",
|
|
70
|
+
"./config/eslint.typeExports": "./config/eslint.typeExports.js",
|
|
68
71
|
"./config/prettier.cjs": "./config/prettier.cjs",
|
|
69
72
|
"./config/prettier": "./config/prettier.cjs",
|
|
70
73
|
"./config/rollup": "./config/rollup.js",
|
|
@@ -288,8 +291,8 @@
|
|
|
288
291
|
"dependencies": {
|
|
289
292
|
"@eslint/compat": "^2.1.1",
|
|
290
293
|
"@eslint/js": "^10.0.1",
|
|
291
|
-
"@pezkuwi/dev-test": "^0.86.
|
|
292
|
-
"@pezkuwi/dev-ts": "^0.86.
|
|
294
|
+
"@pezkuwi/dev-test": "^0.86.4",
|
|
295
|
+
"@pezkuwi/dev-ts": "^0.86.4",
|
|
293
296
|
"@rollup/plugin-alias": "^5.1.1",
|
|
294
297
|
"@rollup/plugin-commonjs": "^29.0.3",
|
|
295
298
|
"@rollup/plugin-dynamic-import-vars": "^2.1.5",
|
package/packageInfo.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const packageInfo = { name: '@pezkuwi/dev', path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '0.86.
|
|
1
|
+
export const packageInfo = { name: '@pezkuwi/dev', path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '0.86.4' };
|
|
@@ -7,8 +7,6 @@ import yargs from 'yargs';
|
|
|
7
7
|
|
|
8
8
|
import { __dirname, execPm, GITHUB_REPO, logBin } from './util.mjs';
|
|
9
9
|
|
|
10
|
-
const TS_CONFIG_BUILD = true;
|
|
11
|
-
|
|
12
10
|
logBin('pezkuwi-dev-run-lint');
|
|
13
11
|
|
|
14
12
|
// Since yargs can also be a promise, we just relax the type here completely
|
|
@@ -36,5 +34,11 @@ if (!argv['skip-eslint']) {
|
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
if (!argv['skip-tsc']) {
|
|
39
|
-
|
|
37
|
+
// The root tsconfig.build.json has `files: []` and only references the
|
|
38
|
+
// packages, so `tsc --project` on it checks no file at all. --build follows
|
|
39
|
+
// the references; it cannot be combined with --noEmit, so it writes the
|
|
40
|
+
// declarations the build would. Previous build output is removed first, since
|
|
41
|
+
// package configs without an `include` would otherwise pick it up as source.
|
|
42
|
+
execPm('pezkuwi-dev-clean-build');
|
|
43
|
+
execPm('pezkuwi-exec-tsc --build tsconfig.build.json --pretty');
|
|
40
44
|
}
|