@sasjs/lint 2.5.0 → 2.6.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/.github/workflows/build.yml +5 -1
- package/lint/lintText.d.ts +6 -2
- package/lint/lintText.js +7 -4
- package/lint/lintText.js.map +1 -1
- package/package.json +3 -2
- package/scripts/audit.mjs +131 -0
|
@@ -25,7 +25,11 @@ jobs:
|
|
|
25
25
|
- name: Install Dependencies
|
|
26
26
|
run: npm ci
|
|
27
27
|
- name: Security Audit
|
|
28
|
-
|
|
28
|
+
# `npm audit` fails on advisories inside the `npm` package bundled by
|
|
29
|
+
# @semantic-release/npm, which no overrides entry can reach. The audit
|
|
30
|
+
# script names those and fails on everything else, so a new advisory
|
|
31
|
+
# anywhere in the tree still fails the build.
|
|
32
|
+
run: npm run audit
|
|
29
33
|
- name: Check Code Style
|
|
30
34
|
run: npm run lint
|
|
31
35
|
- name: Run Unit Tests
|
package/lint/lintText.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { Diagnostic, LintConfig } from '../types';
|
|
1
2
|
/**
|
|
2
3
|
* Analyses and produces a set of diagnostics for the given text content.
|
|
3
4
|
* @param {string} text - the text content to be linted.
|
|
4
|
-
* @
|
|
5
|
+
* @param {LintConfig} configuration - an optional lint configuration. The
|
|
6
|
+
* nearest `.sasjslint` file provides the configuration when it is omitted.
|
|
7
|
+
* @returns {Diagnostic[]} array of diagnostic objects, each containing a
|
|
8
|
+
* warning, line number and column number.
|
|
5
9
|
*/
|
|
6
|
-
export declare const lintText: (text: string) => Promise<
|
|
10
|
+
export declare const lintText: (text: string, configuration?: LintConfig) => Promise<Diagnostic[]>;
|
package/lint/lintText.js
CHANGED
|
@@ -10,15 +10,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.lintText = void 0;
|
|
13
|
-
const
|
|
13
|
+
const utils_1 = require("../utils");
|
|
14
14
|
const shared_1 = require("./shared");
|
|
15
15
|
/**
|
|
16
16
|
* Analyses and produces a set of diagnostics for the given text content.
|
|
17
17
|
* @param {string} text - the text content to be linted.
|
|
18
|
-
* @
|
|
18
|
+
* @param {LintConfig} configuration - an optional lint configuration. The
|
|
19
|
+
* nearest `.sasjslint` file provides the configuration when it is omitted.
|
|
20
|
+
* @returns {Diagnostic[]} array of diagnostic objects, each containing a
|
|
21
|
+
* warning, line number and column number.
|
|
19
22
|
*/
|
|
20
|
-
const lintText = (text) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
-
const config = yield (0,
|
|
23
|
+
const lintText = (text, configuration) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
const config = configuration || (yield (0, utils_1.getLintConfig)());
|
|
22
25
|
return (0, shared_1.processText)(text, config);
|
|
23
26
|
});
|
|
24
27
|
exports.lintText = lintText;
|
package/lint/lintText.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lintText.js","sourceRoot":"","sources":["../../src/lint/lintText.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"lintText.js","sourceRoot":"","sources":["../../src/lint/lintText.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oCAAwC;AACxC,qCAAsC;AAEtC;;;;;;;GAOG;AACI,MAAM,QAAQ,GAAG,CACtB,IAAY,EACZ,aAA0B,EACH,EAAE;IACzB,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,OAAO,IAAA,oBAAW,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAClC,CAAC,CAAA,CAAA;AANY,QAAA,QAAQ,YAMpB"}
|
package/package.json
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"package:lib": "npm run build && cp ./package.json ./checkNodeVersion.js build && cp README.md build && cd build && npm version \"5.0.0\" && npm pack",
|
|
11
11
|
"lint:fix": "npx prettier --write \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
|
|
12
12
|
"lint": "npx prettier --check \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
|
|
13
|
-
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
|
|
13
|
+
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true",
|
|
14
|
+
"audit": "node scripts/audit.mjs"
|
|
14
15
|
},
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public"
|
|
@@ -71,5 +72,5 @@
|
|
|
71
72
|
"@sasjs/utils": "3.6.2",
|
|
72
73
|
"ignore": "7.0.8"
|
|
73
74
|
},
|
|
74
|
-
"version": "2.
|
|
75
|
+
"version": "2.6.0"
|
|
75
76
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* A strict dependency audit.
|
|
4
|
+
*
|
|
5
|
+
* `npm audit` fails on ANY advisory, which cannot pass in this repo: the
|
|
6
|
+
* advisories below sit inside the `npm` package that `@semantic-release/npm`
|
|
7
|
+
* depends on, in its bundled tree, where no `overrides` entry can reach them.
|
|
8
|
+
* npm 12.1.0 bundles the same versions as 11.20.0, so no upgrade clears them.
|
|
9
|
+
* They are unreachable from this package's own code and its runtime
|
|
10
|
+
* dependencies.
|
|
11
|
+
*
|
|
12
|
+
* Lowering the threshold for everything would hide a new advisory anywhere
|
|
13
|
+
* else, so instead they are named below and every other advisory fails the
|
|
14
|
+
* build - including one of the same severity. If one disappears upstream, this
|
|
15
|
+
* script says so, so the exemption does not outlive its reason.
|
|
16
|
+
*
|
|
17
|
+
* Run with `npm run audit`.
|
|
18
|
+
*/
|
|
19
|
+
import { execFileSync } from 'node:child_process'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Advisories that cannot be fixed from this repo, and why.
|
|
23
|
+
*/
|
|
24
|
+
const EXEMPT = new Map([
|
|
25
|
+
['GHSA-rpw4-54j3-4h4q', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
|
|
26
|
+
['GHSA-2vr4-cq9g-pvrc', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
|
|
27
|
+
['GHSA-3wwx-pv8p-q78v', 'undici, inside the npm package bundled by @semantic-release/npm'],
|
|
28
|
+
// The advisories below landed upstream after the exemptions above were
|
|
29
|
+
// written, against the same bundled copies. npm 12.1.0 bundles identical
|
|
30
|
+
// versions of all three packages, so an upgrade clears none of them.
|
|
31
|
+
['GHSA-j6r3-76f7-8jcv', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
|
|
32
|
+
['GHSA-h3mg-xc3c-68pw', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
|
|
33
|
+
['GHSA-r53p-7pc4-xj5r', 'undici, inside the npm package bundled by @semantic-release/npm'],
|
|
34
|
+
['GHSA-rfgv-xxqx-mfg5', 'undici, inside the npm package bundled by @semantic-release/npm'],
|
|
35
|
+
[
|
|
36
|
+
'GHSA-q2hr-2g5m-vwhr',
|
|
37
|
+
'brace-expansion, inside the npm package bundled by @semantic-release/npm'
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
'GHSA-qhr7-859c-m2p7',
|
|
41
|
+
'brace-expansion, inside the npm package bundled by @semantic-release/npm'
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
'GHSA-6j4f-fj2g-mc7p',
|
|
45
|
+
'brace-expansion, inside the npm package bundled by @semantic-release/npm'
|
|
46
|
+
]
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
const run = () => {
|
|
50
|
+
try {
|
|
51
|
+
return execFileSync('npm', ['audit', '--json'], {
|
|
52
|
+
encoding: 'utf8',
|
|
53
|
+
stdio: ['ignore', 'pipe', 'ignore']
|
|
54
|
+
})
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// npm audit exits non-zero when it finds anything, which is the case we are
|
|
57
|
+
// here to read, so the report on stdout is the payload either way.
|
|
58
|
+
if (error.stdout) return error.stdout
|
|
59
|
+
throw error
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let report
|
|
64
|
+
try {
|
|
65
|
+
report = JSON.parse(run())
|
|
66
|
+
} catch {
|
|
67
|
+
console.error('could not read the npm audit report')
|
|
68
|
+
process.exit(1)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const ghsaOf = (via) => {
|
|
72
|
+
if (typeof via === 'string') return undefined
|
|
73
|
+
const match = /GHSA-[a-z0-9-]+/i.exec(via?.url ?? '')
|
|
74
|
+
return match ? match[0] : undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const found = new Map()
|
|
78
|
+
for (const vulnerability of Object.values(report.vulnerabilities ?? {})) {
|
|
79
|
+
for (const via of vulnerability.via ?? []) {
|
|
80
|
+
const id = ghsaOf(via)
|
|
81
|
+
if (!id) continue
|
|
82
|
+
if (!found.has(id)) {
|
|
83
|
+
found.set(id, {
|
|
84
|
+
id,
|
|
85
|
+
title: via.title ?? '',
|
|
86
|
+
severity: via.severity ?? vulnerability.severity,
|
|
87
|
+
packages: new Set()
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
found.get(id).packages.add(vulnerability.name)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const exempt = [...found.keys()].filter((id) => EXEMPT.has(id))
|
|
95
|
+
const failing = [...found.values()].filter((entry) => !EXEMPT.has(entry.id))
|
|
96
|
+
const stale = [...EXEMPT.keys()].filter((id) => !found.has(id))
|
|
97
|
+
|
|
98
|
+
console.log(`advisories found: ${found.size}`)
|
|
99
|
+
for (const entry of found.values()) {
|
|
100
|
+
const mark = EXEMPT.has(entry.id) ? 'exempt' : 'FAIL '
|
|
101
|
+
console.log(
|
|
102
|
+
` ${mark} ${entry.severity.padEnd(8)} ${entry.id} ${[...entry.packages].join(', ')}`
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
for (const id of stale) {
|
|
107
|
+
console.log(` GONE ${id} no longer reported - remove its exemption`)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (failing.length === 0 && stale.length === 0) {
|
|
111
|
+
console.log(
|
|
112
|
+
`audit clean: ${exempt.length} exempt, ${stale.length} stale, ${failing.length} failing`
|
|
113
|
+
)
|
|
114
|
+
process.exit(0)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (stale.length > 0) {
|
|
118
|
+
console.error(
|
|
119
|
+
`${stale.length} exemption(s) no longer match a reported advisory.`
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (failing.length > 0) {
|
|
124
|
+
console.error(`${failing.length} advisory(ies) are NOT exempt:`)
|
|
125
|
+
for (const entry of failing) {
|
|
126
|
+
console.error(` ${entry.severity} ${entry.id} ${entry.title}`)
|
|
127
|
+
console.error(` ${[...entry.packages].join(', ')}`)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
process.exit(1)
|