@pgsql/lint 18.1.1 → 18.2.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/README.md +38 -0
- package/changed.d.ts +41 -0
- package/changed.js +159 -0
- package/cli.d.ts +6 -4
- package/cli.js +158 -16
- package/config.d.ts +50 -0
- package/config.js +157 -0
- package/esm/changed.js +121 -0
- package/esm/cli.js +125 -16
- package/esm/config.js +118 -0
- package/esm/file-runner.js +6 -5
- package/esm/ignore.js +101 -0
- package/esm/index.js +3 -0
- package/esm/linter.js +2 -1
- package/file-runner.d.ts +16 -3
- package/file-runner.js +6 -5
- package/ignore.d.ts +22 -0
- package/ignore.js +138 -0
- package/index.d.ts +6 -1
- package/index.js +13 -1
- package/linter.d.ts +4 -0
- package/linter.js +2 -1
- package/package.json +6 -6
package/esm/ignore.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path exclusion for the file runner — `--ignore` / `ignore` in a config file.
|
|
3
|
+
*
|
|
4
|
+
* Most repositories that lint SQL on disk also *generate* SQL on disk
|
|
5
|
+
* (packaged modules, introspected schemas, codegen output), and linting
|
|
6
|
+
* generated output is noise. Patterns are gitignore-flavoured globs matched
|
|
7
|
+
* against the path relative to `cwd`:
|
|
8
|
+
*
|
|
9
|
+
* - `*` matches within a segment, `**` across segments, `?` one character.
|
|
10
|
+
* - A pattern with no glob character matches that path *and everything under
|
|
11
|
+
* it*, so `sql/` and `sql` both exclude `sql/app--1.0.0.sql`.
|
|
12
|
+
* - An unanchored pattern (no leading `/`) also matches at any segment
|
|
13
|
+
* boundary, so `generated/`, `**` patterns, and `*.gen.sql` all work.
|
|
14
|
+
* - A leading `/` anchors the pattern to `cwd`.
|
|
15
|
+
*/
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
/** Turn a glob into a `RegExp` source anchored at both ends. */
|
|
18
|
+
function globToRegExpSource(glob) {
|
|
19
|
+
let out = '';
|
|
20
|
+
for (let i = 0; i < glob.length; i++) {
|
|
21
|
+
const ch = glob[i];
|
|
22
|
+
if (ch === '*') {
|
|
23
|
+
if (glob[i + 1] === '*') {
|
|
24
|
+
// `**/` may match zero segments, so `**/gen/**` also matches `gen/x`.
|
|
25
|
+
if (glob[i + 2] === '/') {
|
|
26
|
+
out += '(?:.*/)?';
|
|
27
|
+
i += 2;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
out += '.*';
|
|
31
|
+
i += 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
out += '[^/]*';
|
|
36
|
+
}
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (ch === '?') {
|
|
40
|
+
out += '[^/]';
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
out += ch.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function compile(pattern) {
|
|
48
|
+
let p = pattern.trim().replace(/\\/g, '/');
|
|
49
|
+
if (!p || p.startsWith('#'))
|
|
50
|
+
return null;
|
|
51
|
+
const anchored = p.startsWith('/');
|
|
52
|
+
if (anchored)
|
|
53
|
+
p = p.slice(1);
|
|
54
|
+
p = p.replace(/^\.\//, '');
|
|
55
|
+
const dirOnly = p.endsWith('/');
|
|
56
|
+
if (dirOnly)
|
|
57
|
+
p = p.replace(/\/+$/, '');
|
|
58
|
+
if (!p)
|
|
59
|
+
return null;
|
|
60
|
+
// A plain path (or an explicit directory) excludes the subtree under it.
|
|
61
|
+
const source = /[*?]/.test(p) && !dirOnly
|
|
62
|
+
? globToRegExpSource(p)
|
|
63
|
+
: `${globToRegExpSource(p)}(?:/.*)?`;
|
|
64
|
+
return { re: new RegExp(`^${source}$`), anchored };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Build a predicate that answers "is this file ignored?". Paths may be
|
|
68
|
+
* absolute or relative; both are compared as `cwd`-relative POSIX paths.
|
|
69
|
+
*/
|
|
70
|
+
export function makeIgnoreFilter(patterns = [], cwd = process.cwd()) {
|
|
71
|
+
const compiled = patterns.map(compile).filter((c) => c !== null);
|
|
72
|
+
if (compiled.length === 0)
|
|
73
|
+
return () => false;
|
|
74
|
+
return (file) => {
|
|
75
|
+
const rel = path.relative(cwd, path.resolve(cwd, file)).replace(/\\/g, '/');
|
|
76
|
+
// Outside cwd entirely — no relative pattern can meaningfully describe it.
|
|
77
|
+
if (rel.startsWith('../'))
|
|
78
|
+
return false;
|
|
79
|
+
const segments = rel.split('/');
|
|
80
|
+
for (const { re, anchored } of compiled) {
|
|
81
|
+
if (re.test(rel))
|
|
82
|
+
return true;
|
|
83
|
+
if (anchored)
|
|
84
|
+
continue;
|
|
85
|
+
// Unanchored: also try every suffix that starts at a segment boundary,
|
|
86
|
+
// so `generated/` matches `packages/x/generated/y.sql`.
|
|
87
|
+
for (let i = 1; i < segments.length; i++) {
|
|
88
|
+
if (re.test(segments.slice(i).join('/')))
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** Filter a list of files through {@link makeIgnoreFilter}. */
|
|
96
|
+
export function applyIgnore(files, patterns, cwd) {
|
|
97
|
+
if (!patterns || patterns.length === 0)
|
|
98
|
+
return files;
|
|
99
|
+
const ignored = makeIgnoreFilter(patterns, cwd);
|
|
100
|
+
return files.filter((f) => !ignored(f));
|
|
101
|
+
}
|
package/esm/index.js
CHANGED
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
* Rules are injected as values, never discovered by npm name: build a linter
|
|
11
11
|
* with `createLinter({ rules, severity })` and pass your own rules in.
|
|
12
12
|
*/
|
|
13
|
+
export { changedFiles, changedSqlFiles, resolveChangedBase } from './changed';
|
|
14
|
+
export { CONFIG_FILENAMES, configDir, findConfigFile, loadLintConfig } from './config';
|
|
13
15
|
export { lintDefinition, severityOf } from './engine';
|
|
14
16
|
export { filesAdapter, lintFiles, lintSource, lintSqlText, resolveSqlFiles, sqlTextAdapter, sqlTextDefinitions } from './file-runner';
|
|
17
|
+
export { applyIgnore, makeIgnoreFilter } from './ignore';
|
|
15
18
|
export { createLinter } from './linter';
|
|
16
19
|
export { parseUnit } from './parse-unit';
|
|
17
20
|
export { LINT_RULES, LINT_RULES_BY_CODE, LINT_RULES_BY_ID, noDynamicSql, noSetSearchPath, noVariableConflict, requireQualifiedRefs } from './rules';
|
package/esm/linter.js
CHANGED
|
@@ -17,6 +17,7 @@ export function createLinter(config = {}) {
|
|
|
17
17
|
const rules = config.rules ?? LINT_RULES;
|
|
18
18
|
const severity = config.severity ?? {};
|
|
19
19
|
const keyword = config.keyword ?? DEFAULT_KEYWORDS;
|
|
20
|
+
const { ignore, cwd } = config;
|
|
20
21
|
const bind = (options = {}) => ({
|
|
21
22
|
ruleSet: rules,
|
|
22
23
|
severity,
|
|
@@ -29,7 +30,7 @@ export function createLinter(config = {}) {
|
|
|
29
30
|
keyword,
|
|
30
31
|
lintDefinition: (text, language, name, options) => lintDefinition(text, language, name, bind(options)),
|
|
31
32
|
lintSqlText: (source, options) => lintSqlText(source, bind(options)),
|
|
32
|
-
lintFiles: (paths, options) => lintFiles(paths, bind(options)),
|
|
33
|
+
lintFiles: (paths, options) => lintFiles(paths, { ...bind(options), ignore, cwd }),
|
|
33
34
|
lintSource: (adapter, options) => lintSource(adapter, bind(options))
|
|
34
35
|
};
|
|
35
36
|
}
|
package/file-runner.d.ts
CHANGED
|
@@ -51,14 +51,27 @@ export declare function sqlTextDefinitions(source: string, file?: string): Promi
|
|
|
51
51
|
* re-anchored to absolute lines within `source`.
|
|
52
52
|
*/
|
|
53
53
|
export declare function lintSqlText(source: string, options?: LintOptions): Promise<FileReport>;
|
|
54
|
+
/** File-selection options layered on top of the lint options. */
|
|
55
|
+
export interface FileLintOptions extends LintOptions {
|
|
56
|
+
/** Glob patterns to exclude (see `makeIgnoreFilter`). */
|
|
57
|
+
ignore?: string[];
|
|
58
|
+
/** Directory the `ignore` patterns are relative to (default `process.cwd()`). */
|
|
59
|
+
cwd?: string;
|
|
60
|
+
}
|
|
54
61
|
/** Resolve a mix of file and directory paths to a sorted list of `.sql` files. */
|
|
55
|
-
export declare function resolveSqlFiles(paths: string[]
|
|
62
|
+
export declare function resolveSqlFiles(paths: string[], options?: {
|
|
63
|
+
ignore?: string[];
|
|
64
|
+
cwd?: string;
|
|
65
|
+
}): Promise<string[]>;
|
|
56
66
|
/** Lint every `.sql` file reachable from `paths` (files or directories). */
|
|
57
|
-
export declare function lintFiles(paths: string[], options?:
|
|
67
|
+
export declare function lintFiles(paths: string[], options?: FileLintOptions): Promise<FileReport[]>;
|
|
58
68
|
/** A {@link SourceAdapter} over an in-memory SQL string. */
|
|
59
69
|
export declare function sqlTextAdapter(source: string, file?: string): SourceAdapter;
|
|
60
70
|
/** A {@link SourceAdapter} over `.sql` files/directories on disk. */
|
|
61
|
-
export declare function filesAdapter(paths: string[]
|
|
71
|
+
export declare function filesAdapter(paths: string[], options?: {
|
|
72
|
+
ignore?: string[];
|
|
73
|
+
cwd?: string;
|
|
74
|
+
}): SourceAdapter;
|
|
62
75
|
/**
|
|
63
76
|
* Lint every definition an adapter yields, grouped into one {@link FileReport}
|
|
64
77
|
* per origin file. This is the generic entry point: `@pgsql/lint` ships file
|
package/file-runner.js
CHANGED
|
@@ -55,6 +55,7 @@ const fs_1 = require("fs");
|
|
|
55
55
|
const path = __importStar(require("path"));
|
|
56
56
|
const pgsql_parser_1 = require("pgsql-parser");
|
|
57
57
|
const engine_1 = require("./engine");
|
|
58
|
+
const ignore_1 = require("./ignore");
|
|
58
59
|
const walk_1 = require("./walk");
|
|
59
60
|
/** Count newlines before `offset` — the 0-based line the offset sits on. */
|
|
60
61
|
function lineAtOffset(text, offset) {
|
|
@@ -196,7 +197,7 @@ async function sqlFilesUnder(dir) {
|
|
|
196
197
|
return out;
|
|
197
198
|
}
|
|
198
199
|
/** Resolve a mix of file and directory paths to a sorted list of `.sql` files. */
|
|
199
|
-
async function resolveSqlFiles(paths) {
|
|
200
|
+
async function resolveSqlFiles(paths, options = {}) {
|
|
200
201
|
const files = new Set();
|
|
201
202
|
for (const p of paths) {
|
|
202
203
|
const st = await fs_1.promises.stat(p);
|
|
@@ -208,11 +209,11 @@ async function resolveSqlFiles(paths) {
|
|
|
208
209
|
files.add(p);
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
|
-
return [...files].sort();
|
|
212
|
+
return (0, ignore_1.applyIgnore)([...files].sort(), options.ignore, options.cwd);
|
|
212
213
|
}
|
|
213
214
|
/** Lint every `.sql` file reachable from `paths` (files or directories). */
|
|
214
215
|
async function lintFiles(paths, options = {}) {
|
|
215
|
-
const files = await resolveSqlFiles(paths);
|
|
216
|
+
const files = await resolveSqlFiles(paths, { ignore: options.ignore, cwd: options.cwd });
|
|
216
217
|
const reports = [];
|
|
217
218
|
for (const file of files) {
|
|
218
219
|
const source = await fs_1.promises.readFile(file, 'utf8');
|
|
@@ -226,11 +227,11 @@ function sqlTextAdapter(source, file) {
|
|
|
226
227
|
return { id: 'sql-text', definitions: () => sqlTextDefinitions(source, file) };
|
|
227
228
|
}
|
|
228
229
|
/** A {@link SourceAdapter} over `.sql` files/directories on disk. */
|
|
229
|
-
function filesAdapter(paths) {
|
|
230
|
+
function filesAdapter(paths, options = {}) {
|
|
230
231
|
return {
|
|
231
232
|
id: 'files',
|
|
232
233
|
definitions: async () => {
|
|
233
|
-
const files = await resolveSqlFiles(paths);
|
|
234
|
+
const files = await resolveSqlFiles(paths, options);
|
|
234
235
|
const out = [];
|
|
235
236
|
for (const file of files) {
|
|
236
237
|
out.push(...(await sqlTextDefinitions(await fs_1.promises.readFile(file, 'utf8'), file)));
|
package/ignore.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path exclusion for the file runner — `--ignore` / `ignore` in a config file.
|
|
3
|
+
*
|
|
4
|
+
* Most repositories that lint SQL on disk also *generate* SQL on disk
|
|
5
|
+
* (packaged modules, introspected schemas, codegen output), and linting
|
|
6
|
+
* generated output is noise. Patterns are gitignore-flavoured globs matched
|
|
7
|
+
* against the path relative to `cwd`:
|
|
8
|
+
*
|
|
9
|
+
* - `*` matches within a segment, `**` across segments, `?` one character.
|
|
10
|
+
* - A pattern with no glob character matches that path *and everything under
|
|
11
|
+
* it*, so `sql/` and `sql` both exclude `sql/app--1.0.0.sql`.
|
|
12
|
+
* - An unanchored pattern (no leading `/`) also matches at any segment
|
|
13
|
+
* boundary, so `generated/`, `**` patterns, and `*.gen.sql` all work.
|
|
14
|
+
* - A leading `/` anchors the pattern to `cwd`.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Build a predicate that answers "is this file ignored?". Paths may be
|
|
18
|
+
* absolute or relative; both are compared as `cwd`-relative POSIX paths.
|
|
19
|
+
*/
|
|
20
|
+
export declare function makeIgnoreFilter(patterns?: string[], cwd?: string): (file: string) => boolean;
|
|
21
|
+
/** Filter a list of files through {@link makeIgnoreFilter}. */
|
|
22
|
+
export declare function applyIgnore(files: string[], patterns?: string[], cwd?: string): string[];
|
package/ignore.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Path exclusion for the file runner — `--ignore` / `ignore` in a config file.
|
|
4
|
+
*
|
|
5
|
+
* Most repositories that lint SQL on disk also *generate* SQL on disk
|
|
6
|
+
* (packaged modules, introspected schemas, codegen output), and linting
|
|
7
|
+
* generated output is noise. Patterns are gitignore-flavoured globs matched
|
|
8
|
+
* against the path relative to `cwd`:
|
|
9
|
+
*
|
|
10
|
+
* - `*` matches within a segment, `**` across segments, `?` one character.
|
|
11
|
+
* - A pattern with no glob character matches that path *and everything under
|
|
12
|
+
* it*, so `sql/` and `sql` both exclude `sql/app--1.0.0.sql`.
|
|
13
|
+
* - An unanchored pattern (no leading `/`) also matches at any segment
|
|
14
|
+
* boundary, so `generated/`, `**` patterns, and `*.gen.sql` all work.
|
|
15
|
+
* - A leading `/` anchors the pattern to `cwd`.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.makeIgnoreFilter = makeIgnoreFilter;
|
|
52
|
+
exports.applyIgnore = applyIgnore;
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
/** Turn a glob into a `RegExp` source anchored at both ends. */
|
|
55
|
+
function globToRegExpSource(glob) {
|
|
56
|
+
let out = '';
|
|
57
|
+
for (let i = 0; i < glob.length; i++) {
|
|
58
|
+
const ch = glob[i];
|
|
59
|
+
if (ch === '*') {
|
|
60
|
+
if (glob[i + 1] === '*') {
|
|
61
|
+
// `**/` may match zero segments, so `**/gen/**` also matches `gen/x`.
|
|
62
|
+
if (glob[i + 2] === '/') {
|
|
63
|
+
out += '(?:.*/)?';
|
|
64
|
+
i += 2;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
out += '.*';
|
|
68
|
+
i += 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
out += '[^/]*';
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (ch === '?') {
|
|
77
|
+
out += '[^/]';
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
out += ch.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
function compile(pattern) {
|
|
85
|
+
let p = pattern.trim().replace(/\\/g, '/');
|
|
86
|
+
if (!p || p.startsWith('#'))
|
|
87
|
+
return null;
|
|
88
|
+
const anchored = p.startsWith('/');
|
|
89
|
+
if (anchored)
|
|
90
|
+
p = p.slice(1);
|
|
91
|
+
p = p.replace(/^\.\//, '');
|
|
92
|
+
const dirOnly = p.endsWith('/');
|
|
93
|
+
if (dirOnly)
|
|
94
|
+
p = p.replace(/\/+$/, '');
|
|
95
|
+
if (!p)
|
|
96
|
+
return null;
|
|
97
|
+
// A plain path (or an explicit directory) excludes the subtree under it.
|
|
98
|
+
const source = /[*?]/.test(p) && !dirOnly
|
|
99
|
+
? globToRegExpSource(p)
|
|
100
|
+
: `${globToRegExpSource(p)}(?:/.*)?`;
|
|
101
|
+
return { re: new RegExp(`^${source}$`), anchored };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build a predicate that answers "is this file ignored?". Paths may be
|
|
105
|
+
* absolute or relative; both are compared as `cwd`-relative POSIX paths.
|
|
106
|
+
*/
|
|
107
|
+
function makeIgnoreFilter(patterns = [], cwd = process.cwd()) {
|
|
108
|
+
const compiled = patterns.map(compile).filter((c) => c !== null);
|
|
109
|
+
if (compiled.length === 0)
|
|
110
|
+
return () => false;
|
|
111
|
+
return (file) => {
|
|
112
|
+
const rel = path.relative(cwd, path.resolve(cwd, file)).replace(/\\/g, '/');
|
|
113
|
+
// Outside cwd entirely — no relative pattern can meaningfully describe it.
|
|
114
|
+
if (rel.startsWith('../'))
|
|
115
|
+
return false;
|
|
116
|
+
const segments = rel.split('/');
|
|
117
|
+
for (const { re, anchored } of compiled) {
|
|
118
|
+
if (re.test(rel))
|
|
119
|
+
return true;
|
|
120
|
+
if (anchored)
|
|
121
|
+
continue;
|
|
122
|
+
// Unanchored: also try every suffix that starts at a segment boundary,
|
|
123
|
+
// so `generated/` matches `packages/x/generated/y.sql`.
|
|
124
|
+
for (let i = 1; i < segments.length; i++) {
|
|
125
|
+
if (re.test(segments.slice(i).join('/')))
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Filter a list of files through {@link makeIgnoreFilter}. */
|
|
133
|
+
function applyIgnore(files, patterns, cwd) {
|
|
134
|
+
if (!patterns || patterns.length === 0)
|
|
135
|
+
return files;
|
|
136
|
+
const ignored = makeIgnoreFilter(patterns, cwd);
|
|
137
|
+
return files.filter((f) => !ignored(f));
|
|
138
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -10,9 +10,14 @@
|
|
|
10
10
|
* Rules are injected as values, never discovered by npm name: build a linter
|
|
11
11
|
* with `createLinter({ rules, severity })` and pass your own rules in.
|
|
12
12
|
*/
|
|
13
|
+
export type { ChangedFilesResult } from './changed';
|
|
14
|
+
export { changedFiles, changedSqlFiles, resolveChangedBase } from './changed';
|
|
15
|
+
export type { LintConfigFile, LoadedLintConfig } from './config';
|
|
16
|
+
export { CONFIG_FILENAMES, configDir, findConfigFile, loadLintConfig } from './config';
|
|
13
17
|
export type { LintOptions } from './engine';
|
|
14
18
|
export { lintDefinition, severityOf } from './engine';
|
|
15
|
-
export { FileFinding, FileReport, filesAdapter, lintFiles, lintSource, lintSqlText, resolveSqlFiles, sqlTextAdapter, sqlTextDefinitions } from './file-runner';
|
|
19
|
+
export { FileFinding, FileLintOptions, FileReport, filesAdapter, lintFiles, lintSource, lintSqlText, resolveSqlFiles, sqlTextAdapter, sqlTextDefinitions } from './file-runner';
|
|
20
|
+
export { applyIgnore, makeIgnoreFilter } from './ignore';
|
|
16
21
|
export type { CallOptions, Linter, LinterConfig } from './linter';
|
|
17
22
|
export { createLinter } from './linter';
|
|
18
23
|
export { parseUnit } from './parse-unit';
|
package/index.js
CHANGED
|
@@ -12,7 +12,16 @@
|
|
|
12
12
|
* with `createLinter({ rules, severity })` and pass your own rules in.
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.defineRule = exports.Suppressions = exports.DEFAULT_KEYWORDS = exports.requireQualifiedRefs = exports.noVariableConflict = exports.noSetSearchPath = exports.noDynamicSql = exports.LINT_RULES_BY_ID = exports.LINT_RULES_BY_CODE = exports.LINT_RULES = exports.parseUnit = exports.createLinter = exports.sqlTextDefinitions = exports.sqlTextAdapter = exports.resolveSqlFiles = exports.lintSqlText = exports.lintSource = exports.lintFiles = exports.filesAdapter = exports.severityOf = exports.lintDefinition = void 0;
|
|
15
|
+
exports.defineRule = exports.Suppressions = exports.DEFAULT_KEYWORDS = exports.requireQualifiedRefs = exports.noVariableConflict = exports.noSetSearchPath = exports.noDynamicSql = exports.LINT_RULES_BY_ID = exports.LINT_RULES_BY_CODE = exports.LINT_RULES = exports.parseUnit = exports.createLinter = exports.makeIgnoreFilter = exports.applyIgnore = exports.sqlTextDefinitions = exports.sqlTextAdapter = exports.resolveSqlFiles = exports.lintSqlText = exports.lintSource = exports.lintFiles = exports.filesAdapter = exports.severityOf = exports.lintDefinition = exports.loadLintConfig = exports.findConfigFile = exports.configDir = exports.CONFIG_FILENAMES = exports.resolveChangedBase = exports.changedSqlFiles = exports.changedFiles = void 0;
|
|
16
|
+
var changed_1 = require("./changed");
|
|
17
|
+
Object.defineProperty(exports, "changedFiles", { enumerable: true, get: function () { return changed_1.changedFiles; } });
|
|
18
|
+
Object.defineProperty(exports, "changedSqlFiles", { enumerable: true, get: function () { return changed_1.changedSqlFiles; } });
|
|
19
|
+
Object.defineProperty(exports, "resolveChangedBase", { enumerable: true, get: function () { return changed_1.resolveChangedBase; } });
|
|
20
|
+
var config_1 = require("./config");
|
|
21
|
+
Object.defineProperty(exports, "CONFIG_FILENAMES", { enumerable: true, get: function () { return config_1.CONFIG_FILENAMES; } });
|
|
22
|
+
Object.defineProperty(exports, "configDir", { enumerable: true, get: function () { return config_1.configDir; } });
|
|
23
|
+
Object.defineProperty(exports, "findConfigFile", { enumerable: true, get: function () { return config_1.findConfigFile; } });
|
|
24
|
+
Object.defineProperty(exports, "loadLintConfig", { enumerable: true, get: function () { return config_1.loadLintConfig; } });
|
|
16
25
|
var engine_1 = require("./engine");
|
|
17
26
|
Object.defineProperty(exports, "lintDefinition", { enumerable: true, get: function () { return engine_1.lintDefinition; } });
|
|
18
27
|
Object.defineProperty(exports, "severityOf", { enumerable: true, get: function () { return engine_1.severityOf; } });
|
|
@@ -24,6 +33,9 @@ Object.defineProperty(exports, "lintSqlText", { enumerable: true, get: function
|
|
|
24
33
|
Object.defineProperty(exports, "resolveSqlFiles", { enumerable: true, get: function () { return file_runner_1.resolveSqlFiles; } });
|
|
25
34
|
Object.defineProperty(exports, "sqlTextAdapter", { enumerable: true, get: function () { return file_runner_1.sqlTextAdapter; } });
|
|
26
35
|
Object.defineProperty(exports, "sqlTextDefinitions", { enumerable: true, get: function () { return file_runner_1.sqlTextDefinitions; } });
|
|
36
|
+
var ignore_1 = require("./ignore");
|
|
37
|
+
Object.defineProperty(exports, "applyIgnore", { enumerable: true, get: function () { return ignore_1.applyIgnore; } });
|
|
38
|
+
Object.defineProperty(exports, "makeIgnoreFilter", { enumerable: true, get: function () { return ignore_1.makeIgnoreFilter; } });
|
|
27
39
|
var linter_1 = require("./linter");
|
|
28
40
|
Object.defineProperty(exports, "createLinter", { enumerable: true, get: function () { return linter_1.createLinter; } });
|
|
29
41
|
var parse_unit_1 = require("./parse-unit");
|
package/linter.d.ts
CHANGED
|
@@ -19,6 +19,10 @@ export interface LinterConfig {
|
|
|
19
19
|
severity?: SeverityMap;
|
|
20
20
|
/** Suppression directive keyword(s). Defaults to `['pgsql-lint', 'safegres']`. */
|
|
21
21
|
keyword?: string | string[];
|
|
22
|
+
/** Glob patterns excluded by the file entry points (`lintFiles`). */
|
|
23
|
+
ignore?: string[];
|
|
24
|
+
/** Directory the `ignore` patterns are relative to (default `process.cwd()`). */
|
|
25
|
+
cwd?: string;
|
|
22
26
|
}
|
|
23
27
|
/** Narrow a single call to a subset of the linter's rules. */
|
|
24
28
|
export type CallOptions = Pick<LintOptions, 'rules'>;
|
package/linter.js
CHANGED
|
@@ -23,6 +23,7 @@ function createLinter(config = {}) {
|
|
|
23
23
|
const rules = config.rules ?? rules_1.LINT_RULES;
|
|
24
24
|
const severity = config.severity ?? {};
|
|
25
25
|
const keyword = config.keyword ?? suppressions_1.DEFAULT_KEYWORDS;
|
|
26
|
+
const { ignore, cwd } = config;
|
|
26
27
|
const bind = (options = {}) => ({
|
|
27
28
|
ruleSet: rules,
|
|
28
29
|
severity,
|
|
@@ -35,7 +36,7 @@ function createLinter(config = {}) {
|
|
|
35
36
|
keyword,
|
|
36
37
|
lintDefinition: (text, language, name, options) => (0, engine_1.lintDefinition)(text, language, name, bind(options)),
|
|
37
38
|
lintSqlText: (source, options) => (0, file_runner_1.lintSqlText)(source, bind(options)),
|
|
38
|
-
lintFiles: (paths, options) => (0, file_runner_1.lintFiles)(paths, bind(options)),
|
|
39
|
+
lintFiles: (paths, options) => (0, file_runner_1.lintFiles)(paths, { ...bind(options), ignore, cwd }),
|
|
39
40
|
lintSource: (adapter, options) => (0, file_runner_1.lintSource)(adapter, bind(options))
|
|
40
41
|
};
|
|
41
42
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgsql/lint",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.2.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Source-level SQL/PL/pgSQL convention linter: fully-qualified references, no search_path, no dynamic SQL, with ESLint-style inline waivers. Pure AST, no database.",
|
|
6
6
|
"main": "index.js",
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
"test:watch": "jest --watch"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pgsql/traverse": "18.7.
|
|
37
|
+
"@pgsql/traverse": "18.7.3",
|
|
38
38
|
"chalk": "^4.1.0",
|
|
39
|
-
"libpg-query": "18.1.
|
|
39
|
+
"libpg-query": "18.1.4",
|
|
40
40
|
"minimist": "1.2.8",
|
|
41
|
-
"pgsql-parser": "18.2.
|
|
41
|
+
"pgsql-parser": "18.2.3"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/minimist": "^1.2.5",
|
|
45
|
-
"makage": "^0.1
|
|
45
|
+
"makage": "^0.5.1"
|
|
46
46
|
},
|
|
47
47
|
"keywords": [
|
|
48
48
|
"sql",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"search_path",
|
|
57
57
|
"dynamic-sql"
|
|
58
58
|
],
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "fa4ea3167cadd5eb0e9a216a2abfa564f6c62364"
|
|
60
60
|
}
|