@futdevpro/dynamo-eslint 1.20.29 → 1.20.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -0
- package/build/configs/ngx.d.ts +29 -0
- package/build/configs/ngx.d.ts.map +1 -1
- package/build/configs/ngx.js +57 -0
- package/build/configs/ngx.js.map +1 -1
- package/build/plugin/index.d.ts +5 -0
- package/build/plugin/index.d.ts.map +1 -1
- package/build/plugin/index.js +13 -0
- package/build/plugin/index.js.map +1 -1
- package/build/plugin/rules/angular/empty-state-guard.util.d.ts +58 -0
- package/build/plugin/rules/angular/empty-state-guard.util.d.ts.map +1 -0
- package/build/plugin/rules/angular/empty-state-guard.util.js +158 -0
- package/build/plugin/rules/angular/empty-state-guard.util.js.map +1 -0
- package/build/plugin/rules/angular/empty-state-requires-guard.d.ts +10 -0
- package/build/plugin/rules/angular/empty-state-requires-guard.d.ts.map +1 -0
- package/build/plugin/rules/angular/empty-state-requires-guard.js +61 -0
- package/build/plugin/rules/angular/empty-state-requires-guard.js.map +1 -0
- package/build/plugin/rules/angular/module-load-failed-branch.d.ts +11 -0
- package/build/plugin/rules/angular/module-load-failed-branch.d.ts.map +1 -0
- package/build/plugin/rules/angular/module-load-failed-branch.js +58 -0
- package/build/plugin/rules/angular/module-load-failed-branch.js.map +1 -0
- package/build/plugin/rules/angular/no-unlisted-inner-html.d.ts +15 -0
- package/build/plugin/rules/angular/no-unlisted-inner-html.d.ts.map +1 -0
- package/build/plugin/rules/angular/no-unlisted-inner-html.js +106 -0
- package/build/plugin/rules/angular/no-unlisted-inner-html.js.map +1 -0
- package/build/plugin/rules/angular/no-unused-component.d.ts +11 -0
- package/build/plugin/rules/angular/no-unused-component.d.ts.map +1 -0
- package/build/plugin/rules/angular/no-unused-component.js +78 -0
- package/build/plugin/rules/angular/no-unused-component.js.map +1 -0
- package/build/plugin/rules/angular/scroll-container-min-h-0.d.ts +11 -0
- package/build/plugin/rules/angular/scroll-container-min-h-0.d.ts.map +1 -0
- package/build/plugin/rules/angular/scroll-container-min-h-0.js +59 -0
- package/build/plugin/rules/angular/scroll-container-min-h-0.js.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.d.ts +15 -0
- package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.d.ts.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.js +3 -0
- package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.js.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-element.interface.d.ts +19 -0
- package/build/plugin/rules/angular/ui-building-blocks-element.interface.d.ts.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-element.interface.js +3 -0
- package/build/plugin/rules/angular/ui-building-blocks-element.interface.js.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.d.ts +28 -0
- package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.d.ts.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.js +50 -0
- package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.js.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.d.ts +12 -0
- package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.d.ts.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.js +3 -0
- package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.js.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks.util.d.ts +111 -0
- package/build/plugin/rules/angular/ui-building-blocks.util.d.ts.map +1 -0
- package/build/plugin/rules/angular/ui-building-blocks.util.js +377 -0
- package/build/plugin/rules/angular/ui-building-blocks.util.js.map +1 -0
- package/build/plugin/rules/angular/unused-component-finding.interface.d.ts +14 -0
- package/build/plugin/rules/angular/unused-component-finding.interface.d.ts.map +1 -0
- package/build/plugin/rules/angular/unused-component-finding.interface.js +3 -0
- package/build/plugin/rules/angular/unused-component-finding.interface.js.map +1 -0
- package/build/plugin/rules/angular/unused-component.util.d.ts +86 -0
- package/build/plugin/rules/angular/unused-component.util.d.ts.map +1 -0
- package/build/plugin/rules/angular/unused-component.util.js +243 -0
- package/build/plugin/rules/angular/unused-component.util.js.map +1 -0
- package/build/plugin/rules/angular/xss-surface-baseline-files.interface.d.ts +8 -0
- package/build/plugin/rules/angular/xss-surface-baseline-files.interface.d.ts.map +1 -0
- package/build/plugin/rules/angular/xss-surface-baseline-files.interface.js +3 -0
- package/build/plugin/rules/angular/xss-surface-baseline-files.interface.js.map +1 -0
- package/build/plugin/rules/angular/xss-surface-occurrences.interface.d.ts +6 -0
- package/build/plugin/rules/angular/xss-surface-occurrences.interface.d.ts.map +1 -0
- package/build/plugin/rules/angular/xss-surface-occurrences.interface.js +3 -0
- package/build/plugin/rules/angular/xss-surface-occurrences.interface.js.map +1 -0
- package/build/plugin/rules/angular/xss-surface.util.d.ts +44 -0
- package/build/plugin/rules/angular/xss-surface.util.d.ts.map +1 -0
- package/build/plugin/rules/angular/xss-surface.util.js +121 -0
- package/build/plugin/rules/angular/xss-surface.util.js.map +1 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.d.ts.map +1 -1
- package/build/plugin/rules/prefer-interface-over-duplicate-types.js +31 -19
- package/build/plugin/rules/prefer-interface-over-duplicate-types.js.map +1 -1
- package/build/scripts/lint-strict.d.ts +62 -0
- package/build/scripts/lint-strict.d.ts.map +1 -0
- package/build/scripts/lint-strict.js +151 -0
- package/build/scripts/lint-strict.js.map +1 -0
- package/build/scripts/ui-building-blocks-baseline.d.ts +21 -0
- package/build/scripts/ui-building-blocks-baseline.d.ts.map +1 -0
- package/build/scripts/ui-building-blocks-baseline.js +123 -0
- package/build/scripts/ui-building-blocks-baseline.js.map +1 -0
- package/build/scripts/unused-components-baseline.d.ts +17 -0
- package/build/scripts/unused-components-baseline.d.ts.map +1 -0
- package/build/scripts/unused-components-baseline.js +62 -0
- package/build/scripts/unused-components-baseline.js.map +1 -0
- package/build/scripts/xss-surface-baseline.d.ts +17 -0
- package/build/scripts/xss-surface-baseline.d.ts.map +1 -0
- package/build/scripts/xss-surface-baseline.js +73 -0
- package/build/scripts/xss-surface-baseline.js.map +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Strict lint entry point — `dynamo-lint-strict` (BFR-WARFACTORY-003)
|
|
4
|
+
*
|
|
5
|
+
* Runs ESLint (flat config, the project's own `eslint.config.*`) and sets the process exit code from the
|
|
6
|
+
* AGGREGATED result counters — never from a wrapper's own success path:
|
|
7
|
+
*
|
|
8
|
+
* | exit | meaning |
|
|
9
|
+
* |---|---|
|
|
10
|
+
* | `0` | 0 errors (incl. fatal/parsing errors) and the warnings are within the budget |
|
|
11
|
+
* | `1` | at least one error, OR more warnings than `--max-warnings` |
|
|
12
|
+
* | `2` | lint could not run (config error, NO file linted, crash) — never reported as a pass |
|
|
13
|
+
*
|
|
14
|
+
* **Warning budget:** without `--max-warnings` warnings are reported but do not fail (the budget is unlimited);
|
|
15
|
+
* `--max-warnings 0` is the zero-warning gate; `--max-warnings <n>` a ratchet for a known backlog.
|
|
16
|
+
*
|
|
17
|
+
* **`.eslintignore`:** flat config does NOT read it (ESLint 9) — files listed there ARE linted. If one exists, the
|
|
18
|
+
* run says so loudly and points at the `ignores` migration; it does not fail on it.
|
|
19
|
+
*
|
|
20
|
+
* @usage
|
|
21
|
+
* ```bash
|
|
22
|
+
* dynamo-lint-strict [patterns...] [--max-warnings <n>] [--json]
|
|
23
|
+
* dynamo-lint-strict src --max-warnings 0
|
|
24
|
+
* dynamo-lint-strict --json # last stdout line: machine-readable summary (CI)
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { ESLint } from 'eslint';
|
|
28
|
+
/** Parsed command-line options of `dynamo-lint-strict`. */
|
|
29
|
+
export interface DyESL_LintStrictOptions_Interface {
|
|
30
|
+
patterns: string[];
|
|
31
|
+
/** `undefined` = unlimited warning budget */
|
|
32
|
+
maxWarnings?: number;
|
|
33
|
+
json: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** Aggregated result of one strict lint run. */
|
|
36
|
+
export interface DyESL_LintStrictSummary_Interface {
|
|
37
|
+
errorCount: number;
|
|
38
|
+
fatalErrorCount: number;
|
|
39
|
+
warningCount: number;
|
|
40
|
+
fileCount: number;
|
|
41
|
+
maxWarnings: number | null;
|
|
42
|
+
legacyEslintignore: boolean;
|
|
43
|
+
passed: boolean;
|
|
44
|
+
exitCode: number;
|
|
45
|
+
}
|
|
46
|
+
/** Strict lint runner — pure helpers (unit-testable) + the CLI `run`. */
|
|
47
|
+
export declare class DyESL_LintStrict_Util {
|
|
48
|
+
/**
|
|
49
|
+
* Parses `[patterns...] [--max-warnings <n>] [--json]`.
|
|
50
|
+
* @throws Error on an invalid / missing `--max-warnings` value or an unknown option
|
|
51
|
+
*/
|
|
52
|
+
static parseArgs(argv: string[]): DyESL_LintStrictOptions_Interface;
|
|
53
|
+
/** Aggregates the ESLint results into the summary + the exit code (0 pass / 1 fail). */
|
|
54
|
+
static summarize(results: ESLint.LintResult[], maxWarnings: number | undefined, legacyEslintignore: boolean): DyESL_LintStrictSummary_Interface;
|
|
55
|
+
/** Human-readable one-line verdict. */
|
|
56
|
+
static formatVerdict(summary: DyESL_LintStrictSummary_Interface): string;
|
|
57
|
+
/**
|
|
58
|
+
* Runs the strict lint in `cwd` and returns the exit code (0 / 1 / 2). Output goes to stdout/stderr.
|
|
59
|
+
*/
|
|
60
|
+
static run(argv: string[], cwd?: string): Promise<number>;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=lint-strict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint-strict.d.ts","sourceRoot":"","sources":["../../src/scripts/lint-strict.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,2DAA2D;AAC3D,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,gDAAgD;AAChD,MAAM,WAAW,iCAAiC;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,yEAAyE;AACzE,qBAAa,qBAAqB;IAEhC;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,iCAAiC;IA6BnE,wFAAwF;IACxF,MAAM,CAAC,SAAS,CACd,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,EAC5B,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,kBAAkB,EAAE,OAAO,GAC1B,iCAAiC;IAsBpC,uCAAuC;IACvC,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,iCAAiC,GAAG,MAAM;IAQxE;;OAEG;WACU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;CAkD/E"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Strict lint entry point — `dynamo-lint-strict` (BFR-WARFACTORY-003)
|
|
5
|
+
*
|
|
6
|
+
* Runs ESLint (flat config, the project's own `eslint.config.*`) and sets the process exit code from the
|
|
7
|
+
* AGGREGATED result counters — never from a wrapper's own success path:
|
|
8
|
+
*
|
|
9
|
+
* | exit | meaning |
|
|
10
|
+
* |---|---|
|
|
11
|
+
* | `0` | 0 errors (incl. fatal/parsing errors) and the warnings are within the budget |
|
|
12
|
+
* | `1` | at least one error, OR more warnings than `--max-warnings` |
|
|
13
|
+
* | `2` | lint could not run (config error, NO file linted, crash) — never reported as a pass |
|
|
14
|
+
*
|
|
15
|
+
* **Warning budget:** without `--max-warnings` warnings are reported but do not fail (the budget is unlimited);
|
|
16
|
+
* `--max-warnings 0` is the zero-warning gate; `--max-warnings <n>` a ratchet for a known backlog.
|
|
17
|
+
*
|
|
18
|
+
* **`.eslintignore`:** flat config does NOT read it (ESLint 9) — files listed there ARE linted. If one exists, the
|
|
19
|
+
* run says so loudly and points at the `ignores` migration; it does not fail on it.
|
|
20
|
+
*
|
|
21
|
+
* @usage
|
|
22
|
+
* ```bash
|
|
23
|
+
* dynamo-lint-strict [patterns...] [--max-warnings <n>] [--json]
|
|
24
|
+
* dynamo-lint-strict src --max-warnings 0
|
|
25
|
+
* dynamo-lint-strict --json # last stdout line: machine-readable summary (CI)
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.DyESL_LintStrict_Util = void 0;
|
|
30
|
+
const fs_1 = require("fs");
|
|
31
|
+
const path_1 = require("path");
|
|
32
|
+
const eslint_1 = require("eslint");
|
|
33
|
+
/** Strict lint runner — pure helpers (unit-testable) + the CLI `run`. */
|
|
34
|
+
class DyESL_LintStrict_Util {
|
|
35
|
+
/**
|
|
36
|
+
* Parses `[patterns...] [--max-warnings <n>] [--json]`.
|
|
37
|
+
* @throws Error on an invalid / missing `--max-warnings` value or an unknown option
|
|
38
|
+
*/
|
|
39
|
+
static parseArgs(argv) {
|
|
40
|
+
const options = { patterns: [], json: false };
|
|
41
|
+
for (let i = 0; i < argv.length; i++) {
|
|
42
|
+
const arg = argv[i];
|
|
43
|
+
if (arg === '--json') {
|
|
44
|
+
options.json = true;
|
|
45
|
+
}
|
|
46
|
+
else if (arg === '--max-warnings') {
|
|
47
|
+
const value = Number(argv[i + 1]);
|
|
48
|
+
if (argv[i + 1] === undefined || !Number.isInteger(value) || value < 0) {
|
|
49
|
+
throw new Error(`--max-warnings needs a non-negative integer (got: ${argv[i + 1] ?? 'nothing'})`);
|
|
50
|
+
}
|
|
51
|
+
options.maxWarnings = value;
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
else if (arg.startsWith('-')) {
|
|
55
|
+
throw new Error(`unknown option: ${arg}`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
options.patterns.push(arg);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!options.patterns.length) {
|
|
62
|
+
options.patterns.push('.');
|
|
63
|
+
}
|
|
64
|
+
return options;
|
|
65
|
+
}
|
|
66
|
+
/** Aggregates the ESLint results into the summary + the exit code (0 pass / 1 fail). */
|
|
67
|
+
static summarize(results, maxWarnings, legacyEslintignore) {
|
|
68
|
+
const errorCount = results.reduce((sum, r) => sum + r.errorCount, 0);
|
|
69
|
+
const fatalErrorCount = results
|
|
70
|
+
.reduce((sum, r) => sum + r.fatalErrorCount, 0);
|
|
71
|
+
const warningCount = results
|
|
72
|
+
.reduce((sum, r) => sum + r.warningCount, 0);
|
|
73
|
+
// a `fatalErrorCount` az `errorCount` RÉSZE (ESLint 9) — külön is számoljuk, hogy a parsing-hiba látsszon
|
|
74
|
+
const overBudget = maxWarnings !== undefined && warningCount > maxWarnings;
|
|
75
|
+
const passed = !errorCount && !fatalErrorCount && !overBudget;
|
|
76
|
+
return {
|
|
77
|
+
errorCount: errorCount,
|
|
78
|
+
fatalErrorCount: fatalErrorCount,
|
|
79
|
+
warningCount: warningCount,
|
|
80
|
+
fileCount: results.length,
|
|
81
|
+
maxWarnings: maxWarnings ?? null,
|
|
82
|
+
legacyEslintignore: legacyEslintignore,
|
|
83
|
+
passed: passed,
|
|
84
|
+
exitCode: passed ? 0 : 1,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Human-readable one-line verdict. */
|
|
88
|
+
static formatVerdict(summary) {
|
|
89
|
+
const budget = summary.maxWarnings === null ? 'unlimited' : `${summary.maxWarnings}`;
|
|
90
|
+
return `[dynamo-lint-strict] ${summary.passed ? 'PASS' : 'FAIL'} — errors: ${summary.errorCount}`
|
|
91
|
+
+ ` (fatal: ${summary.fatalErrorCount}) · warnings: ${summary.warningCount} (budget: ${budget})`
|
|
92
|
+
+ ` · files: ${summary.fileCount}`;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Runs the strict lint in `cwd` and returns the exit code (0 / 1 / 2). Output goes to stdout/stderr.
|
|
96
|
+
*/
|
|
97
|
+
static async run(argv, cwd = process.cwd()) {
|
|
98
|
+
let options;
|
|
99
|
+
try {
|
|
100
|
+
options = DyESL_LintStrict_Util.parseArgs(argv);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error(`[dynamo-lint-strict] usage error: ${error instanceof Error ? error.message : String(error)}`);
|
|
104
|
+
return 2;
|
|
105
|
+
}
|
|
106
|
+
const legacyEslintignore = (0, fs_1.existsSync)((0, path_1.join)(cwd, '.eslintignore'));
|
|
107
|
+
if (legacyEslintignore) {
|
|
108
|
+
console.error('[dynamo-lint-strict] ⚠️ .eslintignore found — ESLint 9 flat config does NOT read it, the files'
|
|
109
|
+
+ ' listed there ARE linted. Move the patterns into an `ignores` entry of eslint.config.* and delete the file.');
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const eslint = new eslint_1.ESLint({ cwd: cwd });
|
|
113
|
+
const results = await eslint.lintFiles(options.patterns);
|
|
114
|
+
// üres futás ⛔ zöld: az ESLint `errorOnUnmatchedPattern`-je MÉRTEN nem megbízható (nem létező mappára 5/5
|
|
115
|
+
// futásban 0 fájlt adott vissza, hiba nélkül) — ezért a kapu maga ellenőrzi
|
|
116
|
+
if (!results.length) {
|
|
117
|
+
console.error(`[dynamo-lint-strict] no file was linted for: ${options.patterns.join(' ')} (exit 2)`
|
|
118
|
+
+ ' — an empty run is not a pass. Check the patterns and the `ignores` of eslint.config.*.');
|
|
119
|
+
return 2;
|
|
120
|
+
}
|
|
121
|
+
const summary = DyESL_LintStrict_Util.summarize(results, options.maxWarnings, legacyEslintignore);
|
|
122
|
+
const formatter = await eslint.loadFormatter('stylish');
|
|
123
|
+
const formatted = await formatter.format(results);
|
|
124
|
+
if (formatted) {
|
|
125
|
+
console.log(formatted);
|
|
126
|
+
}
|
|
127
|
+
console.log(DyESL_LintStrict_Util.formatVerdict(summary));
|
|
128
|
+
if (options.json) {
|
|
129
|
+
console.log(JSON.stringify(summary));
|
|
130
|
+
}
|
|
131
|
+
return summary.exitCode;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
// a lint NEM futott le ⇒ ⛔ soha nem „zöld"
|
|
135
|
+
console.error('[dynamo-lint-strict] lint could not run (exit 2):', error instanceof Error ? error.message : String(error));
|
|
136
|
+
return 2;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.DyESL_LintStrict_Util = DyESL_LintStrict_Util;
|
|
141
|
+
if (require.main === module) {
|
|
142
|
+
DyESL_LintStrict_Util.run(process.argv.slice(2))
|
|
143
|
+
.then((code) => {
|
|
144
|
+
process.exitCode = code;
|
|
145
|
+
})
|
|
146
|
+
.catch((error) => {
|
|
147
|
+
console.error('[dynamo-lint-strict] crashed (exit 2):', error);
|
|
148
|
+
process.exitCode = 2;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=lint-strict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint-strict.js","sourceRoot":"","sources":["../../src/scripts/lint-strict.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview UI-building-blocks baseline generator (BFR-QA-004)
|
|
4
|
+
*
|
|
5
|
+
* Writes the committed per-project baseline of the `@futdevpro/dynamo/scroll-container-min-h-0` and
|
|
6
|
+
* `@futdevpro/dynamo/module-load-failed-branch` rules: the scroll containers that will not scroll (per file) and the
|
|
7
|
+
* modules that show a loading state without a load-failed state — as they are TODAY. The rules then accept those and
|
|
8
|
+
* fail only on new ones. The analysis is the rules' own scanner.
|
|
9
|
+
*
|
|
10
|
+
* `settings.scrollerTags` (component tags that ARE scroll containers) is kept from the existing baseline; add more
|
|
11
|
+
* with `--scroller-tag <tag>` (repeatable).
|
|
12
|
+
*
|
|
13
|
+
* @usage
|
|
14
|
+
* ```bash
|
|
15
|
+
* npx dynamo-ui-building-blocks-baseline # run in the folder ESLint runs in (e.g. client/)
|
|
16
|
+
* npx dynamo-ui-building-blocks-baseline --scroller-tag app-a-pull-to-refresh
|
|
17
|
+
* npx dynamo-ui-building-blocks-baseline --check # exit 1 if a new case appeared
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=ui-building-blocks-baseline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-building-blocks-baseline.d.ts","sourceRoot":"","sources":["../../src/scripts/ui-building-blocks-baseline.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview UI-building-blocks baseline generator (BFR-QA-004)
|
|
5
|
+
*
|
|
6
|
+
* Writes the committed per-project baseline of the `@futdevpro/dynamo/scroll-container-min-h-0` and
|
|
7
|
+
* `@futdevpro/dynamo/module-load-failed-branch` rules: the scroll containers that will not scroll (per file) and the
|
|
8
|
+
* modules that show a loading state without a load-failed state — as they are TODAY. The rules then accept those and
|
|
9
|
+
* fail only on new ones. The analysis is the rules' own scanner.
|
|
10
|
+
*
|
|
11
|
+
* `settings.scrollerTags` (component tags that ARE scroll containers) is kept from the existing baseline; add more
|
|
12
|
+
* with `--scroller-tag <tag>` (repeatable).
|
|
13
|
+
*
|
|
14
|
+
* @usage
|
|
15
|
+
* ```bash
|
|
16
|
+
* npx dynamo-ui-building-blocks-baseline # run in the folder ESLint runs in (e.g. client/)
|
|
17
|
+
* npx dynamo-ui-building-blocks-baseline --scroller-tag app-a-pull-to-refresh
|
|
18
|
+
* npx dynamo-ui-building-blocks-baseline --check # exit 1 if a new case appeared
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
const tslib_1 = require("tslib");
|
|
23
|
+
const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
|
24
|
+
const fs_1 = require("fs");
|
|
25
|
+
const path = tslib_1.__importStar(require("path"));
|
|
26
|
+
const ui_building_blocks_util_1 = require("../plugin/rules/angular/ui-building-blocks.util");
|
|
27
|
+
const empty_state_guard_util_1 = require("../plugin/rules/angular/empty-state-guard.util");
|
|
28
|
+
/** Scans a project folder into baseline form. */
|
|
29
|
+
function scanProject(root, scrollerTags) {
|
|
30
|
+
const files = fast_glob_1.default.sync(['**/*.html', '**/*.ts'], {
|
|
31
|
+
cwd: root,
|
|
32
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.angular/**', '**/coverage/**'],
|
|
33
|
+
dot: false,
|
|
34
|
+
});
|
|
35
|
+
const scrollContainers = {};
|
|
36
|
+
const loadingModules = new Set();
|
|
37
|
+
const failedModules = new Set();
|
|
38
|
+
const emptyStatesWithoutGuard = {};
|
|
39
|
+
files.sort().forEach((rel) => {
|
|
40
|
+
if (!ui_building_blocks_util_1.UiBuildingBlocks_Util.isInScope(rel)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const full = path.join(root, rel);
|
|
44
|
+
const text = (0, fs_1.readFileSync)(full, 'utf8');
|
|
45
|
+
const findings = ui_building_blocks_util_1.UiBuildingBlocks_Util.scrollFindings(text, rel, scrollerTags).length;
|
|
46
|
+
if (findings) {
|
|
47
|
+
scrollContainers[ui_building_blocks_util_1.UiBuildingBlocks_Util.normalize(rel)] = findings;
|
|
48
|
+
}
|
|
49
|
+
// BFR-QA-003: unguarded empty-state messages (own ancestor block OR the rendering parent's guard clears them)
|
|
50
|
+
const unguarded = empty_state_guard_util_1.EmptyStateGuard_Util.findings(text, rel)
|
|
51
|
+
.filter((f) => !f.ownGuard).length;
|
|
52
|
+
if (unguarded && !empty_state_guard_util_1.EmptyStateGuard_Util.guardedByParent(full, root)) {
|
|
53
|
+
emptyStatesWithoutGuard[ui_building_blocks_util_1.UiBuildingBlocks_Util.normalize(rel)] = unguarded;
|
|
54
|
+
}
|
|
55
|
+
const moduleDir = ui_building_blocks_util_1.UiBuildingBlocks_Util.moduleDir(full);
|
|
56
|
+
if (moduleDir) {
|
|
57
|
+
const key = ui_building_blocks_util_1.UiBuildingBlocks_Util.relativeKey(moduleDir, root);
|
|
58
|
+
if (ui_building_blocks_util_1.UiBuildingBlocks_Util.loadingOffsets(text, rel).length) {
|
|
59
|
+
loadingModules.add(key);
|
|
60
|
+
}
|
|
61
|
+
if (ui_building_blocks_util_1.UiBuildingBlocks_Util.hasFailedBranch(text, rel)) {
|
|
62
|
+
failedModules.add(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
scrollerTags: scrollerTags,
|
|
68
|
+
scrollContainers: scrollContainers,
|
|
69
|
+
modulesWithoutLoadFailedBranch: [...loadingModules].filter((m) => !failedModules.has(m)).sort(),
|
|
70
|
+
emptyStatesWithoutGuard: emptyStatesWithoutGuard,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** The CLI. */
|
|
74
|
+
function main(args) {
|
|
75
|
+
const outIndex = args.indexOf('--out');
|
|
76
|
+
const root = process.cwd();
|
|
77
|
+
const out = path.resolve(root, outIndex >= 0 ? args[outIndex + 1] : ui_building_blocks_util_1.UiBuildingBlocks_Util.defaultBaselineFile);
|
|
78
|
+
const committed = ui_building_blocks_util_1.UiBuildingBlocks_Util.readBaseline(out);
|
|
79
|
+
const extraTags = args
|
|
80
|
+
.map((arg, index) => (arg === '--scroller-tag' ? args[index + 1] : undefined))
|
|
81
|
+
.filter((tag) => !!tag);
|
|
82
|
+
const scrollerTags = [...new Set([...committed.scrollerTags, ...extraTags])].sort();
|
|
83
|
+
const current = scanProject(root, scrollerTags);
|
|
84
|
+
const scrollTotal = Object.values(current.scrollContainers).reduce((a, b) => a + b, 0);
|
|
85
|
+
if (args.includes('--check')) {
|
|
86
|
+
const grownFiles = Object.entries(current.scrollContainers)
|
|
87
|
+
.filter(([key, count]) => count > (committed.scrollContainers[key] ?? 0))
|
|
88
|
+
.map(([key]) => key);
|
|
89
|
+
const newModules = current.modulesWithoutLoadFailedBranch
|
|
90
|
+
.filter((m) => !committed.modulesWithoutLoadFailedBranch.includes(m));
|
|
91
|
+
const grownEmpty = Object.entries(current.emptyStatesWithoutGuard ?? {})
|
|
92
|
+
.filter(([key, count]) => count > (committed.emptyStatesWithoutGuard?.[key] ?? 0))
|
|
93
|
+
.map(([key]) => key);
|
|
94
|
+
grownFiles.forEach((key) => console.log(`NEW scroll container without min-h-0 chain: ${key}`));
|
|
95
|
+
newModules.forEach((m) => console.log(`NEW module with a loading state but no failed state: ${m}`));
|
|
96
|
+
grownEmpty.forEach((key) => console.log(`NEW empty-state message without a loading / failed guard: ${key}`));
|
|
97
|
+
if (!grownFiles.length && !newModules.length && !grownEmpty.length) {
|
|
98
|
+
console.log('UI building blocks within the baseline.');
|
|
99
|
+
}
|
|
100
|
+
process.exitCode = grownFiles.length || newModules.length || grownEmpty.length ? 1 : 0;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
(0, fs_1.mkdirSync)(path.dirname(out), { recursive: true });
|
|
104
|
+
(0, fs_1.writeFileSync)(out, JSON.stringify({
|
|
105
|
+
rules: ui_building_blocks_util_1.UiBuildingBlocks_Util.ruleIds,
|
|
106
|
+
note: 'Accepted cases that existed when the guard was adopted. New ones fail the rules. Regenerate ONLY after a '
|
|
107
|
+
+ 'reviewed change; lower it when you fix one (BFR-QA-004).',
|
|
108
|
+
generatedAt: new Date().toISOString(),
|
|
109
|
+
settings: { scrollerTags: scrollerTags },
|
|
110
|
+
totals: {
|
|
111
|
+
scrollContainers: scrollTotal,
|
|
112
|
+
modulesWithoutLoadFailedBranch: current.modulesWithoutLoadFailedBranch.length,
|
|
113
|
+
emptyStatesWithoutGuard: Object.values(current.emptyStatesWithoutGuard ?? {}).reduce((a, b) => a + b, 0),
|
|
114
|
+
},
|
|
115
|
+
scrollContainers: current.scrollContainers,
|
|
116
|
+
modulesWithoutLoadFailedBranch: current.modulesWithoutLoadFailedBranch,
|
|
117
|
+
emptyStatesWithoutGuard: current.emptyStatesWithoutGuard ?? {},
|
|
118
|
+
}, null, 2) + '\n');
|
|
119
|
+
console.log(`UI-building-blocks baseline written: ${path.relative(root, out)} — ${scrollTotal} scroll container(s) `
|
|
120
|
+
+ `without a min-h-0 chain, ${current.modulesWithoutLoadFailedBranch.length} module(s) without a load-failed state.`);
|
|
121
|
+
}
|
|
122
|
+
main(process.argv.slice(2));
|
|
123
|
+
//# sourceMappingURL=ui-building-blocks-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-building-blocks-baseline.js","sourceRoot":"","sources":["../../src/scripts/ui-building-blocks-baseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Unused-components baseline generator (BFR-QA-006)
|
|
4
|
+
*
|
|
5
|
+
* Writes the committed per-project baseline of the `@futdevpro/dynamo/no-unused-component` rule: the components that
|
|
6
|
+
* are built but used nowhere TODAY (`<file>#<Class>`). The rule then accepts those and fails only on new ones. The
|
|
7
|
+
* scan is the rule's own (`UnusedComponent_Util`). Meant for apps: a library's public components are "unused" inside
|
|
8
|
+
* the package, so the generator warns when it finds an `ng-package.json`.
|
|
9
|
+
*
|
|
10
|
+
* @usage
|
|
11
|
+
* ```bash
|
|
12
|
+
* npx dynamo-unused-components-baseline # run in the folder ESLint runs in (e.g. client/)
|
|
13
|
+
* npx dynamo-unused-components-baseline --check # exit 1 if a NEW unused component appeared
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=unused-components-baseline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unused-components-baseline.d.ts","sourceRoot":"","sources":["../../src/scripts/unused-components-baseline.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Unused-components baseline generator (BFR-QA-006)
|
|
5
|
+
*
|
|
6
|
+
* Writes the committed per-project baseline of the `@futdevpro/dynamo/no-unused-component` rule: the components that
|
|
7
|
+
* are built but used nowhere TODAY (`<file>#<Class>`). The rule then accepts those and fails only on new ones. The
|
|
8
|
+
* scan is the rule's own (`UnusedComponent_Util`). Meant for apps: a library's public components are "unused" inside
|
|
9
|
+
* the package, so the generator warns when it finds an `ng-package.json`.
|
|
10
|
+
*
|
|
11
|
+
* @usage
|
|
12
|
+
* ```bash
|
|
13
|
+
* npx dynamo-unused-components-baseline # run in the folder ESLint runs in (e.g. client/)
|
|
14
|
+
* npx dynamo-unused-components-baseline --check # exit 1 if a NEW unused component appeared
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const tslib_1 = require("tslib");
|
|
19
|
+
const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
|
20
|
+
const fs_1 = require("fs");
|
|
21
|
+
const path = tslib_1.__importStar(require("path"));
|
|
22
|
+
const unused_component_util_1 = require("../plugin/rules/angular/unused-component.util");
|
|
23
|
+
/** The CLI. */
|
|
24
|
+
function main(args) {
|
|
25
|
+
const outIndex = args.indexOf('--out');
|
|
26
|
+
const root = process.cwd();
|
|
27
|
+
const out = path.resolve(root, outIndex >= 0 ? args[outIndex + 1] : unused_component_util_1.UnusedComponent_Util.defaultBaselineFile);
|
|
28
|
+
const project = unused_component_util_1.UnusedComponent_Util.projectIndex(root);
|
|
29
|
+
const findings = unused_component_util_1.UnusedComponent_Util.findUnused(project.sources, project.index);
|
|
30
|
+
const keys = findings.map((f) => unused_component_util_1.UnusedComponent_Util.key(f)).sort();
|
|
31
|
+
if (fast_glob_1.default.sync(['**/ng-package.json'], { cwd: root, ignore: ['**/node_modules/**'] }).length) {
|
|
32
|
+
console.warn('⚠️ ng-package.json found: this looks like a LIBRARY — its public components are used by consumers, '
|
|
33
|
+
+ 'not inside the package. The rule is meant for apps.');
|
|
34
|
+
}
|
|
35
|
+
if (args.includes('--check')) {
|
|
36
|
+
const committed = unused_component_util_1.UnusedComponent_Util.readBaseline(out);
|
|
37
|
+
const fresh = keys.filter((k) => !committed.includes(k));
|
|
38
|
+
fresh.forEach((k) => console.log(`NEW unused component: ${k}`));
|
|
39
|
+
if (!fresh.length) {
|
|
40
|
+
console.log('Unused components within the baseline.');
|
|
41
|
+
}
|
|
42
|
+
process.exitCode = fresh.length ? 1 : 0;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
(0, fs_1.mkdirSync)(path.dirname(out), { recursive: true });
|
|
46
|
+
(0, fs_1.writeFileSync)(out, JSON.stringify({
|
|
47
|
+
rule: unused_component_util_1.UnusedComponent_Util.ruleId,
|
|
48
|
+
note: 'Components that were built but used nowhere when the guard was adopted. New ones fail the rule. Remove an '
|
|
49
|
+
+ 'entry when you wire the component in or delete it (BFR-QA-006).',
|
|
50
|
+
generatedAt: new Date().toISOString(),
|
|
51
|
+
totals: {
|
|
52
|
+
unused: keys.length,
|
|
53
|
+
commentedOut: findings.filter((f) => f.commentedOut).length,
|
|
54
|
+
},
|
|
55
|
+
components: keys,
|
|
56
|
+
commentedOut: findings.filter((f) => f.commentedOut)
|
|
57
|
+
.map((f) => unused_component_util_1.UnusedComponent_Util.key(f)).sort(),
|
|
58
|
+
}, null, 2) + '\n');
|
|
59
|
+
console.log(`Unused-components baseline written: ${path.relative(root, out)} — ${keys.length} unused component(s).`);
|
|
60
|
+
}
|
|
61
|
+
main(process.argv.slice(2));
|
|
62
|
+
//# sourceMappingURL=unused-components-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unused-components-baseline.js","sourceRoot":"","sources":["../../src/scripts/unused-components-baseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview XSS-surface baseline generator (BFR-QA-005)
|
|
4
|
+
*
|
|
5
|
+
* Writes the committed per-project baseline of the `@futdevpro/dynamo/no-unlisted-inner-html` rule: for every
|
|
6
|
+
* `.html` / `.ts` file (tests excluded) the number of `[innerHTML]` bindings and `bypassSecurityTrust…(…)` calls it has
|
|
7
|
+
* TODAY. The rule then accepts those and fails only on new ones. The counting is the rule's own scanner.
|
|
8
|
+
*
|
|
9
|
+
* @usage
|
|
10
|
+
* ```bash
|
|
11
|
+
* npx dynamo-xss-surface-baseline # run in the folder ESLint runs in (e.g. client/)
|
|
12
|
+
* npx dynamo-xss-surface-baseline --check # exit 1 if the surface grew beyond the committed baseline
|
|
13
|
+
* npx dynamo-xss-surface-baseline --out .dynamo/xss-surface-baseline.json
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=xss-surface-baseline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xss-surface-baseline.d.ts","sourceRoot":"","sources":["../../src/scripts/xss-surface-baseline.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview XSS-surface baseline generator (BFR-QA-005)
|
|
5
|
+
*
|
|
6
|
+
* Writes the committed per-project baseline of the `@futdevpro/dynamo/no-unlisted-inner-html` rule: for every
|
|
7
|
+
* `.html` / `.ts` file (tests excluded) the number of `[innerHTML]` bindings and `bypassSecurityTrust…(…)` calls it has
|
|
8
|
+
* TODAY. The rule then accepts those and fails only on new ones. The counting is the rule's own scanner.
|
|
9
|
+
*
|
|
10
|
+
* @usage
|
|
11
|
+
* ```bash
|
|
12
|
+
* npx dynamo-xss-surface-baseline # run in the folder ESLint runs in (e.g. client/)
|
|
13
|
+
* npx dynamo-xss-surface-baseline --check # exit 1 if the surface grew beyond the committed baseline
|
|
14
|
+
* npx dynamo-xss-surface-baseline --out .dynamo/xss-surface-baseline.json
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const tslib_1 = require("tslib");
|
|
19
|
+
const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
|
20
|
+
const fs_1 = require("fs");
|
|
21
|
+
const path = tslib_1.__importStar(require("path"));
|
|
22
|
+
const xss_surface_util_1 = require("../plugin/rules/angular/xss-surface.util");
|
|
23
|
+
/** Scans a project folder into baseline form (only files that HAVE a surface are listed). */
|
|
24
|
+
function scanProject(root) {
|
|
25
|
+
const files = fast_glob_1.default.sync(['**/*.html', '**/*.ts'], {
|
|
26
|
+
cwd: root,
|
|
27
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.angular/**', '**/coverage/**'],
|
|
28
|
+
dot: false,
|
|
29
|
+
});
|
|
30
|
+
const result = {};
|
|
31
|
+
files.sort().forEach((rel) => {
|
|
32
|
+
if (!xss_surface_util_1.XssSurface_Util.isInScope(rel)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const found = xss_surface_util_1.XssSurface_Util.scan((0, fs_1.readFileSync)(path.join(root, rel), 'utf8'), rel);
|
|
36
|
+
if (found.innerHtml.length || found.bypass.length) {
|
|
37
|
+
result[xss_surface_util_1.XssSurface_Util.normalize(rel)] = { innerHtml: found.innerHtml.length, bypass: found.bypass.length };
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
/** The CLI. */
|
|
43
|
+
function main(args) {
|
|
44
|
+
const outIndex = args.indexOf('--out');
|
|
45
|
+
const root = process.cwd();
|
|
46
|
+
const out = path.resolve(root, outIndex >= 0 ? args[outIndex + 1] : xss_surface_util_1.XssSurface_Util.defaultBaselineFile);
|
|
47
|
+
const current = scanProject(root);
|
|
48
|
+
const totals = Object.values(current).reduce((sum, entry) => ({
|
|
49
|
+
files: sum.files + 1, innerHtml: sum.innerHtml + entry.innerHtml, bypass: sum.bypass + entry.bypass,
|
|
50
|
+
}), { files: 0, innerHtml: 0, bypass: 0 });
|
|
51
|
+
if (args.includes('--check')) {
|
|
52
|
+
const committed = xss_surface_util_1.XssSurface_Util.readBaseline(out);
|
|
53
|
+
const grown = Object.entries(current)
|
|
54
|
+
.filter(([key, entry]) => entry.innerHtml > (committed[key]?.innerHtml ?? 0) || entry.bypass > (committed[key]?.bypass ?? 0))
|
|
55
|
+
.map(([key]) => key);
|
|
56
|
+
console.log(grown.length ? `XSS surface GREW in: ${grown.join(', ')}` : 'XSS surface within the baseline.');
|
|
57
|
+
process.exitCode = grown.length ? 1 : 0;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
(0, fs_1.mkdirSync)(path.dirname(out), { recursive: true });
|
|
61
|
+
(0, fs_1.writeFileSync)(out, JSON.stringify({
|
|
62
|
+
rule: xss_surface_util_1.XssSurface_Util.ruleId,
|
|
63
|
+
note: 'Accepted XSS surfaces that existed when the guard was adopted. New ones fail the rule. Regenerate ONLY '
|
|
64
|
+
+ 'after a reviewed change (BFR-QA-005).',
|
|
65
|
+
generatedAt: new Date().toISOString(),
|
|
66
|
+
totals: totals,
|
|
67
|
+
files: current,
|
|
68
|
+
}, null, 2) + '\n');
|
|
69
|
+
console.log(`XSS-surface baseline written: ${path.relative(root, out)} — ${totals.files} file(s), `
|
|
70
|
+
+ `${totals.innerHtml} [innerHTML], ${totals.bypass} bypassSecurityTrust.`);
|
|
71
|
+
}
|
|
72
|
+
main(process.argv.slice(2));
|
|
73
|
+
//# sourceMappingURL=xss-surface-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xss-surface-baseline.js","sourceRoot":"","sources":["../../src/scripts/xss-surface-baseline.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@futdevpro/dynamo-eslint",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.55",
|
|
4
4
|
"description": "Shared ESLint configs, Dynamo-powered plugin and validators for FutDevPro stacks",
|
|
5
5
|
"author": "Future Development Program Ltd.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -68,7 +68,11 @@
|
|
|
68
68
|
"dynamo-validate-naming": "./build/scripts/validate-naming.js",
|
|
69
69
|
"dynamo-eslintrc-audit": "./build/scripts/eslintrc-audit.js",
|
|
70
70
|
"dynamo-fix": "./build/scripts/dynamo-fix.js",
|
|
71
|
-
"dynamo-fix-return-types": "./build/scripts/fix-return-types.js"
|
|
71
|
+
"dynamo-fix-return-types": "./build/scripts/fix-return-types.js",
|
|
72
|
+
"dynamo-xss-surface-baseline": "./build/scripts/xss-surface-baseline.js",
|
|
73
|
+
"dynamo-ui-building-blocks-baseline": "./build/scripts/ui-building-blocks-baseline.js",
|
|
74
|
+
"dynamo-unused-components-baseline": "./build/scripts/unused-components-baseline.js",
|
|
75
|
+
"dynamo-lint-strict": "./build/scripts/lint-strict.js"
|
|
72
76
|
},
|
|
73
77
|
"keywords": [
|
|
74
78
|
"eslint",
|
|
@@ -89,7 +93,7 @@
|
|
|
89
93
|
}
|
|
90
94
|
},
|
|
91
95
|
"dependencies": {
|
|
92
|
-
"@futdevpro/fsm-dynamo": "1.20.
|
|
96
|
+
"@futdevpro/fsm-dynamo": "1.20.93",
|
|
93
97
|
"eslint-plugin-max-params-no-constructor": "0.0.4",
|
|
94
98
|
"eslint-plugin-unused-imports": "4.4.1",
|
|
95
99
|
"fast-glob": "3.3.3",
|